Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/geometry/polyhedron/constructor.py
4058 views
1
r"""
2
Polyhedra
3
4
In this module, a polyhedron is a convex (possibly unbounded) set in
5
Euclidean space cut out by a finite set of linear inequalities and
6
linear equations. Note that the dimension of the polyhedron can be
7
less than the dimension of the ambient space. There are two
8
complementary representations of the same data:
9
10
**H(alf-space/Hyperplane)-representation**
11
This describes a polyhedron as the common solution set of a
12
finite number of
13
14
* linear inequalities `A \vec{x} + b \geq 0`, and
15
* linear equations `C \vec{x} + d \geq 0`.
16
17
18
**V(ertex)-representation**
19
The other representation is as the convex hull of vertices (and
20
rays and lines to all for unbounded polyhedra) as generators. The
21
polyhedron is then the Minkowski sum
22
23
.. MATH::
24
25
P = \text{conv}\{v_1,\dots,v_k\} +
26
\sum_{i=1}^m \RR_+ r_i +
27
\sum_{j=1}^n \RR \ell_j
28
29
where
30
31
* `v_1`, `\dots`, `v_k` are a finite number of vertices,
32
* `r_1`, `\dots`, `r_m` are generators of rays,
33
* and `\ell_1`, `\dots`, `\ell_n` are generators of full lines.
34
35
36
A polytope is defined as a bounded polyhedron.
37
38
EXAMPLES::
39
40
sage: trunc_quadr = Polyhedron(vertices=[[1,0],[0,1]], rays=[[1,0],[0,1]])
41
sage: trunc_quadr
42
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 2 rays
43
sage: v = trunc_quadr.vertex_generator().next() # the first vertex in the internal enumeration
44
sage: v
45
A vertex at (0, 1)
46
sage: v.vector()
47
(0, 1)
48
sage: list(v)
49
[0, 1]
50
sage: len(v)
51
2
52
sage: v[0] + v[1]
53
1
54
sage: v.is_vertex()
55
True
56
sage: type(v)
57
<class 'sage.geometry.polyhedron.representation.Vertex'>
58
sage: type( v() )
59
<type 'sage.modules.vector_rational_dense.Vector_rational_dense'>
60
sage: v.polyhedron()
61
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 2 rays
62
sage: r = trunc_quadr.ray_generator().next()
63
sage: r
64
A ray in the direction (0, 1)
65
sage: r.vector()
66
(0, 1)
67
sage: [x for x in v.neighbors()]
68
[A ray in the direction (0, 1), A ray in the direction (1, 0), A vertex at (1, 0)]
69
70
Inequalities `A \vec{x} + b \geq 0` (and, similarly, equations) are
71
specified by a list ``[b, A]``::
72
73
sage: Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,-1]]).Hrepresentation()
74
(An inequality (-1, -1) x + 1 >= 0,
75
An inequality (1, 0) x + 0 >= 0,
76
An inequality (0, 1) x + 0 >= 0)
77
78
See :func:`Polyhedron` for a detailed description of all possible ways
79
to construct a polyhedron.
80
81
REFERENCES:
82
83
Komei Fukuda's `FAQ in Polyhedral Computation
84
<http://www.ifor.math.ethz.ch/~fukuda/polyfaq/polyfaq.html>`_
85
86
AUTHORS:
87
88
- Marshall Hampton: first version, bug fixes, and various improvements, 2008 and 2009
89
- Arnaud Bergeron: improvements to triangulation and rendering, 2008
90
- Sebastien Barthelemy: documentation improvements, 2008
91
- Volker Braun: refactoring, handle non-compact case, 2009 and 2010
92
- Andrey Novoseltsev: added Hasse_diagram_from_incidences, 2010
93
- Volker Braun: rewrite to use PPL instead of cddlib, 2011
94
"""
95
96
########################################################################
97
# Copyright (C) 2008 Marshall Hampton <[email protected]>
98
# Copyright (C) 2011 Volker Braun <[email protected]>
99
#
100
# Distributed under the terms of the GNU General Public License (GPL)
101
#
102
# http://www.gnu.org/licenses/
103
########################################################################
104
105
from sage.rings.all import QQ, ZZ, RDF
106
from sage.misc.decorators import rename_keyword
107
108
from misc import (
109
_set_to_None_if_empty, _set_to_empty_if_None,
110
_common_length_of )
111
112
113
114
115
116
117
#########################################################################
118
@rename_keyword(deprecated='Sage version 4.7.2', field='base_ring')
119
def Polyhedron(vertices=None, rays=None, lines=None,
120
ieqs=None, eqns=None,
121
base_ring=QQ, minimize=True, verbose=False,
122
backend=None):
123
"""
124
Construct a polyhedron object.
125
126
You may either define it with vertex/ray/line or
127
inequalities/equations data, but not both. Redundant data will
128
automatically be removed (unless ``minimize=False``), and the
129
complementary representation will be computed.
130
131
INPUT:
132
133
- ``vertices`` -- list of point. Each point can be specified as
134
any iterable container of ``base_ring`` elements.
135
136
- ``rays`` -- list of rays. Each ray can be specified as any
137
iterable container of ``base_ring`` elements.
138
139
- ``lines`` -- list of lines. Each line can be specified as any
140
iterable container of ``base_ring`` elements.
141
142
- ``ieqs`` -- list of inequalities. Each line can be specified as
143
any iterable container of ``base_ring`` elements.
144
145
- ``eqns`` -- list of equalities. Each line can be specified as
146
any iterable container of ``base_ring`` elements.
147
148
- ``base_ring`` -- either ``QQ`` or ``RDF``. The field over which
149
the polyhedron will be defined. For ``QQ``, exact arithmetic
150
will be used. For ``RDF``, floating point numbers will be
151
used. Floating point arithmetic is faster but might give the
152
wrong result for degenerate input.
153
154
- ``backend`` -- string or ``None`` (default). The backend to use. Valid choices are
155
156
* ``'cddr'``: cdd (:mod:`~sage.geometry.polyhedron.backend_cdd`)
157
with rational coefficients
158
159
* ``'cddf'``: cdd with floating-point coefficients
160
161
* ``'ppl'``: use ppl
162
(:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\QQ`
163
coefficients.
164
165
Some backends support further optional arguments:
166
167
- ``minimize`` -- boolean (default: ``True``). Whether to
168
immediately remove redundant H/V-representation data. Currently
169
not used.
170
171
- ``verbose`` -- boolean (default: ``False``). Whether to print
172
verbose output for debugging purposes. Only supported by the cdd
173
backends.
174
175
OUTPUT:
176
177
The polyhedron defined by the input data.
178
179
EXAMPLES:
180
181
Construct some polyhedra::
182
183
sage: square_from_vertices = Polyhedron(vertices = [[1, 1], [1, -1], [-1, 1], [-1, -1]])
184
sage: square_from_ieqs = Polyhedron(ieqs = [[1, 0, 1], [1, 1, 0], [1, 0, -1], [1, -1, 0]])
185
sage: list(square_from_ieqs.vertex_generator())
186
[A vertex at (1, -1),
187
A vertex at (1, 1),
188
A vertex at (-1, 1),
189
A vertex at (-1, -1)]
190
sage: list(square_from_vertices.inequality_generator())
191
[An inequality (1, 0) x + 1 >= 0,
192
An inequality (0, 1) x + 1 >= 0,
193
An inequality (-1, 0) x + 1 >= 0,
194
An inequality (0, -1) x + 1 >= 0]
195
sage: p = Polyhedron(vertices = [[1.1, 2.2], [3.3, 4.4]], base_ring=RDF)
196
sage: p.n_inequalities()
197
2
198
199
The same polyhedron given in two ways::
200
201
sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0]])
202
sage: p.Vrepresentation()
203
(A line in the direction (0, 0, 1),
204
A ray in the direction (1, 0, 0),
205
A ray in the direction (0, 1, 0),
206
A vertex at (0, 0, 0))
207
sage: q = Polyhedron(vertices=[[0,0,0]], rays=[[1,0,0],[0,1,0]], lines=[[0,0,1]])
208
sage: q.Hrepresentation()
209
(An inequality (1, 0, 0) x + 0 >= 0,
210
An inequality (0, 1, 0) x + 0 >= 0)
211
212
Finally, a more complicated example. Take `\mathbb{R}_{\geq 0}^6` with
213
coordinates `a, b, \dots, f` and
214
215
* The inequality `e+b \geq c+d`
216
* The inequality `e+c \geq b+d`
217
* The equation `a+b+c+d+e+f = 31`
218
219
::
220
221
sage: positive_coords = Polyhedron(ieqs=[
222
... [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0],
223
... [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1]])
224
sage: P = Polyhedron(ieqs=positive_coords.inequalities() + [
225
... [0,0,1,-1,-1,1,0], [0,0,-1,1,-1,1,0]], eqns=[[-31,1,1,1,1,1,1]])
226
sage: P
227
A 5-dimensional polyhedron in QQ^6 defined as the convex hull of 7 vertices
228
sage: P.dim()
229
5
230
sage: P.Vrepresentation()
231
(A vertex at (31, 0, 0, 0, 0, 0), A vertex at (0, 0, 0, 0, 0, 31),
232
A vertex at (0, 0, 0, 0, 31, 0), A vertex at (0, 0, 31/2, 0, 31/2, 0),
233
A vertex at (0, 31/2, 31/2, 0, 0, 0), A vertex at (0, 31/2, 0, 0, 31/2, 0),
234
A vertex at (0, 0, 0, 31/2, 31/2, 0))
235
236
.. NOTE::
237
238
* Once constructed, a ``Polyhedron`` object is immutable.
239
* Although the option ``field=RDF`` allows numerical data to
240
be used, it might not give the right answer for degenerate
241
input data - the results can depend upon the tolerance
242
setting of cdd.
243
"""
244
# Clean up the arguments
245
vertices = _set_to_None_if_empty(vertices)
246
rays = _set_to_None_if_empty(rays)
247
lines = _set_to_None_if_empty(lines)
248
ieqs = _set_to_None_if_empty(ieqs)
249
eqns = _set_to_None_if_empty(eqns)
250
251
got_Vrep = (vertices is not None or rays is not None or lines is not None)
252
got_Hrep = (ieqs is not None or eqns is not None)
253
254
if got_Vrep and got_Hrep:
255
raise ValueError('You cannot specify both H- and V-representation.')
256
elif got_Vrep:
257
vertices = _set_to_empty_if_None(vertices)
258
rays = _set_to_empty_if_None(rays)
259
lines = _set_to_empty_if_None(lines)
260
Vrep = [vertices, rays, lines]
261
Hrep = None
262
ambient_dim = _common_length_of(*Vrep)[1]
263
elif got_Hrep:
264
ieqs = _set_to_empty_if_None(ieqs)
265
eqns = _set_to_empty_if_None(eqns)
266
Vrep = None
267
Hrep = [ieqs, eqns]
268
ambient_dim = _common_length_of(*Hrep)[1] - 1
269
else:
270
Vrep = None
271
Hrep = None
272
ambient_dim = 0
273
274
if backend is not None:
275
if backend=='ppl':
276
from backend_ppl import Polyhedron_QQ_ppl
277
return Polyhedron_QQ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
278
if backend=='cddr':
279
from backend_cdd import Polyhedron_QQ_cdd
280
return Polyhedron_QQ_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
281
if backend=='cddf':
282
from backend_cdd import Polyhedron_RDF_cdd
283
return Polyhedron_RDF_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
284
285
if base_ring is QQ:
286
from backend_ppl import Polyhedron_QQ_ppl
287
return Polyhedron_QQ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
288
elif base_ring is RDF:
289
from backend_cdd import Polyhedron_RDF_cdd
290
return Polyhedron_RDF_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
291
else:
292
raise ValueError('Polyhedron objects can only be constructed over QQ and RDF')
293
294
295
296
297
298
299