Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/geometry/polytope.py
4056 views
1
"""
2
Polytopes
3
4
This module provides access to polymake, which 'has been developed
5
since 1997 in the Discrete Geometry group at the Institute of
6
Mathematics of Technische Universitat Berlin. Since 2004 the
7
development is shared with Fachbereich Mathematik, Technische
8
Universitat Darmstadt. The system offers access to a wide variety
9
of algorithms and packages within a common framework. polymake is
10
flexible and continuously expanding. The software supplies C++ and
11
Perl interfaces which make it highly adaptable to individual
12
needs.'
13
14
.. note::
15
16
If you have trouble with this module do::
17
18
sage: !polymake --reconfigure # not tested
19
20
at the command line.
21
22
AUTHORS:
23
24
- Ewgenij Gawrilow, Michael Joswig: main authors of polymake
25
26
- William Stein: Sage interface
27
"""
28
29
########################################################################
30
# Copyright (C) 2006 William Stein <[email protected]>
31
#
32
# Distributed under the terms of the GNU General Public License (GPL)
33
#
34
# http://www.gnu.org/licenses/
35
########################################################################
36
37
38
from sage.misc.all import SAGE_TMP, tmp_filename
39
from sage.rings.all import Integer, QQ
40
from sage.structure.all import Sequence
41
from sage.modules.all import VectorSpace
42
from sage.structure.sage_object import SageObject
43
44
import os
45
from subprocess import *
46
47
path = '%s/local/polymake/bin/'%os.environ['SAGE_ROOT']
48
polymake_command = path + 'polymake'
49
50
if os.path.exists(path):
51
os.environ['PATH'] = '%s:'%path + os.environ['PATH']
52
53
tmp_file = '%s/tmp.poly'%SAGE_TMP
54
55
class Polytope(SageObject):
56
"""
57
Create a polytope.
58
59
EXAMPLES::
60
61
sage: P = polymake.convex_hull([[1,0,0,0], [1,0,0,1], [1,0,1,0], [1,0,1,1], [1,1,0,0], [1,1,0,1], [1,1,1,0], [1,1,1,1]]) # optional - polymake
62
63
.. note::
64
65
If you have trouble with this module do::
66
67
sage: !polymake --reconfigure # not tested
68
69
at the command line.
70
"""
71
def __init__(self, datafile, desc):
72
self.__data = datafile
73
self.__desc = desc
74
75
def _repr_(self):
76
s = self.__desc
77
# vertices, facets, points, inequalities
78
try:
79
s += '\nVertices:\n%s'%self.__vertices
80
except AttributeError:
81
pass
82
try:
83
s += '\nFacets:\n%s'%self.__facets
84
except AttributeError:
85
pass
86
return s
87
88
89
90
def __add__(self, other):
91
if not isinstance(other, Polytope):
92
raise TypeError, "other (=%s) must be a polytope"%other
93
output_file = tmp_filename()
94
infile1 = tmp_filename()
95
open(infile1,'w').write(self.__data)
96
infile2 = tmp_filename()
97
open(infile2,'w').write(other.__data)
98
cmd = "minkowski_sum %s 1 %s 1 %s"%(output_file, infile1,
99
infile2)
100
stdin, stdout, stderr = os.popen3(cmd)
101
stdin.close()
102
err = stderr.read()
103
if len(err) > 0:
104
raise RuntimeError, err
105
print stdout.read(), err
106
S = polymake.from_data(open(output_file).read())
107
os.unlink(infile1)
108
os.unlink(infile2)
109
os.unlink(output_file)
110
return S
111
112
113
def data(self):
114
return self.__data
115
116
def write(self, filename):
117
open(filename,'w').write(self.__data)
118
119
def cmd(self, cmd):
120
cmd = cmd.upper()
121
# First check if the value of the command
122
# is already known.
123
D = self.data()
124
cmd2='\n%s\n'%cmd
125
i = D.find(cmd2)
126
if i != -1:
127
j = D[i:].find('\n\n')
128
if j == -1:
129
j = len(D)
130
else:
131
j += i
132
return D[i+len(cmd2)-1:j]
133
134
F = tmp_file
135
open(F,'w').write(self.__data)
136
c = '%s %s %s'%(polymake_command, F, cmd)
137
polymake_processes = Popen([polymake_command, F, cmd],stdout=PIPE,stderr=PIPE)
138
ans, err = polymake_processes.communicate()
139
if len(err) > 0:
140
raise RuntimeError, err
141
if len(ans) == 0:
142
raise ValueError, "%s\nError executing polymake command %s"%(
143
err,cmd)
144
self.__data = open(F).read()
145
return ans
146
147
148
def facets(self):
149
"""
150
EXAMPLES::
151
152
sage: P = polymake.convex_hull([[1,0,0,0], [1,0,0,1], [1,0,1,0], [1,0,1,1], [1,1,0,0], [1,1,0,1], [1,1,1,0], [1,1,1,1]]) # optional - polymake
153
sage: P.facets() # optional - polymake
154
[(0, 0, 0, 1), (0, 1, 0, 0), (0, 0, 1, 0), (1, 0, 0, -1), (1, 0, -1, 0), (1, -1, 0, 0)]
155
"""
156
try:
157
return self.__facets
158
except AttributeError:
159
pass
160
s = self.cmd('FACETS')
161
s = s.rstrip().split('\n')[1:]
162
if len(s) == 0:
163
ans = Sequence([], immutable=True)
164
else:
165
n = len(s[0].split())
166
V = VectorSpace(QQ, n)
167
ans = Sequence((V(x.split()) for x in s), immutable=True)
168
self.__facets = ans
169
return ans
170
171
def vertices(self):
172
"""
173
EXAMPLES::
174
175
sage: P = polymake.convex_hull([[1,0,0,0], [1,0,0,1], [1,0,1,0], [1,0,1,1], [1,1,0,0], [1,1,0,1], [1,1,1,0], [1,1,1,1]]) # optional - polymake
176
sage: P.vertices() # optional - polymake
177
[(1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 1, 0), (1, 0, 1, 1), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 1, 0), (1, 1, 1, 1)]
178
"""
179
try:
180
return self.__vertices
181
except AttributeError:
182
pass
183
s = self.cmd('VERTICES')
184
s = s.rstrip().split('\n')[1:]
185
if len(s) == 0:
186
ans = Sequence([], immutable=True)
187
else:
188
n = len(s[0].split())
189
V = VectorSpace(QQ, n)
190
ans = Sequence((V(x.split()) for x in s), immutable=True)
191
self.__vertices = ans
192
return ans
193
194
def visual(self):
195
try:
196
self.cmd('visual')
197
except ValueError:
198
pass
199
200
def graph(self):
201
try:
202
return self.__graph
203
except AttributeError:
204
pass
205
g = self.cmd('GRAPH')
206
return g
207
208
def is_simple(self):
209
r"""
210
Return True if this polytope is simple.
211
212
A polytope is *simple* if the degree of each vertex equals the
213
dimension of the polytope.
214
215
EXAMPLES::
216
217
sage: P = polymake.convex_hull([[1,0,0,0], [1,0,0,1], [1,0,1,0], [1,0,1,1], [1,1,0,0], [1,1,0,1], [1,1,1,0], [1,1,1,1]]) # optional - polymake
218
sage: P.is_simple() # optional - polymake
219
True
220
221
AUTHORS:
222
223
- Edwin O'Shea (2006-05-02): Definition of simple.
224
"""
225
try:
226
return self.__is_simple
227
except AttributeError:
228
pass
229
s = self.cmd('SIMPLE')
230
i = s.find('\n')
231
self.__is_simple = bool(int(s[i:]))
232
return self.__is_simple
233
234
235
236
def n_facets(self):
237
"""
238
EXAMPLES::
239
240
sage: P = polymake.convex_hull([[1,0,0,0], [1,0,0,1], [1,0,1,0], [1,0,1,1], [1,1,0,0], [1,1,0,1], [1,1,1,0], [1,1,1,1]]) # optional - polymake
241
sage: P.n_facets() # optional - polymake
242
6
243
"""
244
try:
245
return self.__n_facets
246
except AttributeError:
247
pass
248
s = self.cmd('N_FACETS')
249
i = s.find('\n')
250
self.__n_facets = Integer(s[i:])
251
return self.__n_facets
252
253
class Polymake:
254
def __repr__(self):
255
return "Object that makes polytopes."
256
257
def __make(self, cmd, name):
258
os.system(cmd)
259
try:
260
d = open(tmp_file).read()
261
except IOError:
262
raise RuntimeError, "You may need to install the polymake package"
263
return Polytope(d, name)
264
265
def reconfigure(self):
266
"""
267
Reconfigure polymake.
268
269
Remember to run polymake.reconfigure() as soon as you have changed
270
the customization file and/or installed missing software!
271
"""
272
os.system("polymake --reconfigure")
273
274
def associahedron(self, dimension):
275
return self.__make('associahedron %s %s'%(tmp_file, dimension),
276
'%s-dimensional associahedron'%dimension)
277
278
def birkhoff(self, n):
279
return self.__make('birkhoff %s %s'%(tmp_file, n),
280
'Birkhoff %s'%n)
281
282
283
def cell24(self):
284
"""
285
EXAMPLES::
286
287
sage: polymake.cell24() # optional - polymake
288
The 24-cell
289
"""
290
return self.__make('24-cell %s'%tmp_file,
291
'The 24-cell')
292
293
def convex_hull(self, points=[]):
294
r"""
295
EXAMPLES::
296
297
sage: R.<x,y,z> = PolynomialRing(QQ,3)
298
sage: f = x^3 + y^3 + z^3 + x*y*z
299
sage: e = f.exponents()
300
sage: a = [[1] + list(v) for v in e]
301
sage: a
302
[[1, 3, 0, 0], [1, 0, 3, 0], [1, 1, 1, 1], [1, 0, 0, 3]]
303
sage: n = polymake.convex_hull(a) # optional - polymake
304
sage: n # optional - polymake
305
Convex hull of points [[1, 0, 0, 3], [1, 0, 3, 0], [1, 1, 1, 1], [1, 3, 0, 0]]
306
sage: n.facets() # optional - polymake
307
[(0, 1, 0, 0), (3, -1, -1, 0), (0, 0, 1, 0)]
308
sage: n.is_simple() # optional - polymake
309
True
310
sage: n.graph() # optional - polymake
311
'GRAPH\n{1 2}\n{0 2}\n{0 1}\n\n'
312
"""
313
f = 'POINTS\n'
314
points.sort()
315
for p in points:
316
f += ' '.join(str(x) for x in p) + '\n'
317
f += '\n'
318
return Polytope(f, 'Convex hull of points %s'%points)
319
320
def cube(self, dimension, scale=0):
321
return self.__make('cube %s %s %s'%(tmp_file, dimension, scale),
322
'Cube of dimension %s (scale %s)'%(dimension, scale))
323
324
def from_data(self, data):
325
return Polytope(data, 'A Polytope')
326
327
def rand01(self, d, n, seed=None):
328
cmd = 'rand01 %s %s %s'%(tmp_file, d, n)
329
if not seed is None:
330
cmd += ' -seed %s'%seed
331
return self.__make(cmd,
332
'%s-dimensional 0/1-polytope with %s random vertices (uniform distribution)'%(d, n))
333
334
335
336
polymake = Polymake()
337
338