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