passagemath-polyhedra 10.6.31rc3__cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-polyhedra might be problematic. Click here for more details.
- passagemath_polyhedra-10.6.31rc3.dist-info/METADATA +367 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/METADATA.bak +369 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/RECORD +206 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +6 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_polyhedra.libs/libgmp-6e109695.so.10.5.0 +0 -0
- passagemath_polyhedra.libs/libgomp-e985bcbb.so.1.0.0 +0 -0
- sage/all__sagemath_polyhedra.py +50 -0
- sage/game_theory/all.py +8 -0
- sage/game_theory/catalog.py +6 -0
- sage/game_theory/catalog_normal_form_games.py +923 -0
- sage/game_theory/cooperative_game.py +844 -0
- sage/game_theory/matching_game.py +1181 -0
- sage/game_theory/normal_form_game.py +2697 -0
- sage/game_theory/parser.py +275 -0
- sage/geometry/all__sagemath_polyhedra.py +22 -0
- sage/geometry/cone.py +6940 -0
- sage/geometry/cone_catalog.py +847 -0
- sage/geometry/cone_critical_angles.py +1027 -0
- sage/geometry/convex_set.py +1119 -0
- sage/geometry/fan.py +3743 -0
- sage/geometry/fan_isomorphism.py +389 -0
- sage/geometry/fan_morphism.py +1884 -0
- sage/geometry/hasse_diagram.py +202 -0
- sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
- sage/geometry/hyperplane_arrangement/all.py +1 -0
- sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
- sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
- sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
- sage/geometry/hyperplane_arrangement/library.py +825 -0
- sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
- sage/geometry/hyperplane_arrangement/plot.py +520 -0
- sage/geometry/integral_points.py +35 -0
- sage/geometry/integral_points_generic_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/integral_points_generic_dense.pyx +7 -0
- sage/geometry/lattice_polytope.py +5894 -0
- sage/geometry/linear_expression.py +773 -0
- sage/geometry/newton_polygon.py +767 -0
- sage/geometry/point_collection.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/point_collection.pyx +1008 -0
- sage/geometry/polyhedral_complex.py +2616 -0
- sage/geometry/polyhedron/all.py +8 -0
- sage/geometry/polyhedron/backend_cdd.py +460 -0
- sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
- sage/geometry/polyhedron/backend_field.py +347 -0
- sage/geometry/polyhedron/backend_normaliz.py +2503 -0
- sage/geometry/polyhedron/backend_number_field.py +168 -0
- sage/geometry/polyhedron/backend_polymake.py +765 -0
- sage/geometry/polyhedron/backend_ppl.py +582 -0
- sage/geometry/polyhedron/base.py +1206 -0
- sage/geometry/polyhedron/base0.py +1444 -0
- sage/geometry/polyhedron/base1.py +886 -0
- sage/geometry/polyhedron/base2.py +812 -0
- sage/geometry/polyhedron/base3.py +1845 -0
- sage/geometry/polyhedron/base4.py +1262 -0
- sage/geometry/polyhedron/base5.py +2700 -0
- sage/geometry/polyhedron/base6.py +1741 -0
- sage/geometry/polyhedron/base7.py +997 -0
- sage/geometry/polyhedron/base_QQ.py +1258 -0
- sage/geometry/polyhedron/base_RDF.py +98 -0
- sage/geometry/polyhedron/base_ZZ.py +934 -0
- sage/geometry/polyhedron/base_mutable.py +215 -0
- sage/geometry/polyhedron/base_number_field.py +122 -0
- sage/geometry/polyhedron/cdd_file_format.py +155 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
- sage/geometry/polyhedron/constructor.py +773 -0
- sage/geometry/polyhedron/double_description.py +753 -0
- sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
- sage/geometry/polyhedron/face.py +1060 -0
- sage/geometry/polyhedron/generating_function.py +1810 -0
- sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
- sage/geometry/polyhedron/library.py +3502 -0
- sage/geometry/polyhedron/misc.py +121 -0
- sage/geometry/polyhedron/modules/all.py +1 -0
- sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
- sage/geometry/polyhedron/palp_database.py +447 -0
- sage/geometry/polyhedron/parent.py +1279 -0
- sage/geometry/polyhedron/plot.py +1986 -0
- sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
- sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
- sage/geometry/polyhedron/representation.py +1723 -0
- sage/geometry/pseudolines.py +515 -0
- sage/geometry/relative_interior.py +445 -0
- sage/geometry/toric_plotter.py +1103 -0
- sage/geometry/triangulation/all.py +2 -0
- sage/geometry/triangulation/base.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/triangulation/base.pyx +963 -0
- sage/geometry/triangulation/data.h +147 -0
- sage/geometry/triangulation/data.pxd +4 -0
- sage/geometry/triangulation/element.py +914 -0
- sage/geometry/triangulation/functions.h +10 -0
- sage/geometry/triangulation/functions.pxd +4 -0
- sage/geometry/triangulation/point_configuration.py +2256 -0
- sage/geometry/triangulation/triangulations.h +49 -0
- sage/geometry/triangulation/triangulations.pxd +7 -0
- sage/geometry/voronoi_diagram.py +319 -0
- sage/interfaces/all__sagemath_polyhedra.py +1 -0
- sage/interfaces/polymake.py +2028 -0
- sage/numerical/all.py +13 -0
- sage/numerical/all__sagemath_polyhedra.py +11 -0
- sage/numerical/backends/all.py +1 -0
- sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
- sage/numerical/backends/cvxopt_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/cvxopt_backend.pyx +1006 -0
- sage/numerical/backends/cvxopt_backend_test.py +19 -0
- sage/numerical/backends/cvxopt_sdp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
- sage/numerical/backends/cvxpy_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/cvxpy_backend.pxd +41 -0
- sage/numerical/backends/cvxpy_backend.pyx +934 -0
- sage/numerical/backends/cvxpy_backend_test.py +13 -0
- sage/numerical/backends/generic_backend_test.py +24 -0
- sage/numerical/backends/interactivelp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/interactivelp_backend.pxd +36 -0
- sage/numerical/backends/interactivelp_backend.pyx +1231 -0
- sage/numerical/backends/interactivelp_backend_test.py +12 -0
- sage/numerical/backends/logging_backend.py +391 -0
- sage/numerical/backends/matrix_sdp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
- sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
- sage/numerical/backends/ppl_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/ppl_backend.pyx +1126 -0
- sage/numerical/backends/ppl_backend_test.py +13 -0
- sage/numerical/backends/scip_backend.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/backends/scip_backend.pxd +22 -0
- sage/numerical/backends/scip_backend.pyx +1289 -0
- sage/numerical/backends/scip_backend_test.py +13 -0
- sage/numerical/interactive_simplex_method.py +5338 -0
- sage/numerical/knapsack.py +665 -0
- sage/numerical/linear_functions.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/linear_functions.pxd +31 -0
- sage/numerical/linear_functions.pyx +1648 -0
- sage/numerical/linear_tensor.py +470 -0
- sage/numerical/linear_tensor_constraints.py +448 -0
- sage/numerical/linear_tensor_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/linear_tensor_element.pxd +6 -0
- sage/numerical/linear_tensor_element.pyx +459 -0
- sage/numerical/mip.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/mip.pxd +40 -0
- sage/numerical/mip.pyx +3667 -0
- sage/numerical/sdp.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/sdp.pxd +39 -0
- sage/numerical/sdp.pyx +1433 -0
- sage/rings/all__sagemath_polyhedra.py +3 -0
- sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
- sage/rings/polynomial/omega.py +982 -0
- sage/schemes/all__sagemath_polyhedra.py +2 -0
- sage/schemes/toric/all.py +10 -0
- sage/schemes/toric/chow_group.py +1248 -0
- sage/schemes/toric/divisor.py +2082 -0
- sage/schemes/toric/divisor_class.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/schemes/toric/divisor_class.pyx +322 -0
- sage/schemes/toric/fano_variety.py +1606 -0
- sage/schemes/toric/homset.py +650 -0
- sage/schemes/toric/ideal.py +451 -0
- sage/schemes/toric/library.py +1322 -0
- sage/schemes/toric/morphism.py +1958 -0
- sage/schemes/toric/points.py +1032 -0
- sage/schemes/toric/sheaf/all.py +1 -0
- sage/schemes/toric/sheaf/constructor.py +302 -0
- sage/schemes/toric/sheaf/klyachko.py +921 -0
- sage/schemes/toric/toric_subscheme.py +905 -0
- sage/schemes/toric/variety.py +3460 -0
- sage/schemes/toric/weierstrass.py +1078 -0
- sage/schemes/toric/weierstrass_covering.py +457 -0
- sage/schemes/toric/weierstrass_higher.py +288 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
|
@@ -0,0 +1,773 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-polyhedra
|
|
2
|
+
r"""
|
|
3
|
+
Polyhedra
|
|
4
|
+
|
|
5
|
+
In this module, a polyhedron is a convex (possibly unbounded) set in
|
|
6
|
+
Euclidean space cut out by a finite set of linear inequalities and
|
|
7
|
+
linear equations. Note that the dimension of the polyhedron can be
|
|
8
|
+
less than the dimension of the ambient space. There are two
|
|
9
|
+
complementary representations of the same data:
|
|
10
|
+
|
|
11
|
+
**H(alf-space/Hyperplane)-representation**
|
|
12
|
+
This describes a polyhedron as the common solution set of a
|
|
13
|
+
finite number of
|
|
14
|
+
|
|
15
|
+
* linear **inequalities** `A \vec{x} + b \geq 0`, and
|
|
16
|
+
|
|
17
|
+
* linear **equations** `C \vec{x} + d = 0`.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
**V(ertex)-representation**
|
|
21
|
+
The other representation is as the convex hull of vertices (and
|
|
22
|
+
rays and lines to all for unbounded polyhedra) as generators. The
|
|
23
|
+
polyhedron is then the Minkowski sum
|
|
24
|
+
|
|
25
|
+
.. MATH::
|
|
26
|
+
|
|
27
|
+
P = \text{conv}\{v_1,\dots,v_k\} +
|
|
28
|
+
\sum_{i=1}^m \RR_+ r_i +
|
|
29
|
+
\sum_{j=1}^n \RR \ell_j
|
|
30
|
+
|
|
31
|
+
where
|
|
32
|
+
|
|
33
|
+
* **vertices** `v_1,\dots,v_k` are a finite number of
|
|
34
|
+
points. Each vertex is specified by an arbitrary vector, and two
|
|
35
|
+
points are equal if and only if the vector is the same.
|
|
36
|
+
|
|
37
|
+
* **rays** `r_1,\dots,r_m` are a finite number of directions
|
|
38
|
+
(directions of infinity). Each ray is specified by a nonzero
|
|
39
|
+
vector, and two rays are equal if and only if the vectors are
|
|
40
|
+
the same up to rescaling with a positive constant.
|
|
41
|
+
|
|
42
|
+
* **lines** `\ell_1,\dots,\ell_n` are a finite number of
|
|
43
|
+
unoriented directions. In other words, a line is equivalent to
|
|
44
|
+
the set `\{r, -r\}` for a ray `r`. Each line is specified by a
|
|
45
|
+
nonzero vector, and two lines are equivalent if and only if the
|
|
46
|
+
vectors are the same up to rescaling with a nonzero (possibly
|
|
47
|
+
negative) constant.
|
|
48
|
+
|
|
49
|
+
When specifying a polyhedron, you can input a non-minimal set of
|
|
50
|
+
inequalities/equations or generating vertices/rays/lines. The
|
|
51
|
+
non-minimal generators are usually called points, non-extremal rays,
|
|
52
|
+
and non-extremal lines, but for our purposes it is more convenient to
|
|
53
|
+
always talk about vertices/rays/lines. Sage will remove any
|
|
54
|
+
superfluous representation objects and always return a minimal
|
|
55
|
+
representation. For example, `(0,0)` is a superfluous vertex here::
|
|
56
|
+
|
|
57
|
+
sage: triangle = Polyhedron(vertices=[(0,2), (-1,0), (1,0), (0,0)])
|
|
58
|
+
sage: triangle.vertices()
|
|
59
|
+
(A vertex at (-1, 0), A vertex at (1, 0), A vertex at (0, 2))
|
|
60
|
+
|
|
61
|
+
.. SEEALSO::
|
|
62
|
+
|
|
63
|
+
If one only needs to keep track of a system of linear system of
|
|
64
|
+
inequalities, one should also consider the class for mixed integer linear
|
|
65
|
+
programming.
|
|
66
|
+
|
|
67
|
+
- :mod:`Mixed Integer Linear Programming <sage.numerical.mip>`
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
Unbounded Polyhedra
|
|
71
|
+
-------------------
|
|
72
|
+
|
|
73
|
+
A polytope is defined as a bounded polyhedron. In this case, the
|
|
74
|
+
minimal representation is unique and a vertex of the minimal
|
|
75
|
+
representation is equivalent to a 0-dimensional face of the
|
|
76
|
+
polytope. This is why one generally does not distinguish vertices and
|
|
77
|
+
0-dimensional faces. But for non-bounded polyhedra we have to allow
|
|
78
|
+
for a more general notion of "vertex" in order to make sense of the
|
|
79
|
+
Minkowski sum presentation::
|
|
80
|
+
|
|
81
|
+
sage: half_plane = Polyhedron(ieqs=[(0,1,0)])
|
|
82
|
+
sage: half_plane.Hrepresentation()
|
|
83
|
+
(An inequality (1, 0) x + 0 >= 0,)
|
|
84
|
+
sage: half_plane.Vrepresentation()
|
|
85
|
+
(A line in the direction (0, 1), A ray in the direction (1, 0), A vertex at (0, 0))
|
|
86
|
+
|
|
87
|
+
Note how we need a point in the above example to anchor the ray and
|
|
88
|
+
line. But any point on the boundary of the half-plane would serve the
|
|
89
|
+
purpose just as well. Sage picked the origin here, but this choice is
|
|
90
|
+
not unique. Similarly, the choice of ray is arbitrary but necessary to
|
|
91
|
+
generate the half-plane.
|
|
92
|
+
|
|
93
|
+
Finally, note that while rays and lines generate unbounded edges of
|
|
94
|
+
the polyhedron they are not in a one-to-one correspondence with
|
|
95
|
+
them. For example, the infinite strip has two infinite edges (1-faces)
|
|
96
|
+
but only one generating line::
|
|
97
|
+
|
|
98
|
+
sage: strip = Polyhedron(vertices=[(1,0),(-1,0)], lines=[(0,1)])
|
|
99
|
+
sage: strip.Hrepresentation()
|
|
100
|
+
(An inequality (1, 0) x + 1 >= 0, An inequality (-1, 0) x + 1 >= 0)
|
|
101
|
+
sage: strip.lines()
|
|
102
|
+
(A line in the direction (0, 1),)
|
|
103
|
+
sage: [f.ambient_V_indices() for f in strip.faces(1)]
|
|
104
|
+
[(0, 2), (0, 1)]
|
|
105
|
+
sage: for face in strip.faces(1):
|
|
106
|
+
....: print(face.ambient_V_indices())
|
|
107
|
+
(0, 2)
|
|
108
|
+
(0, 1)
|
|
109
|
+
sage: for face in strip.faces(1):
|
|
110
|
+
....: print("{} = {}".format(face.ambient_V_indices(), face.as_polyhedron().Vrepresentation()))
|
|
111
|
+
(0, 2) = (A line in the direction (0, 1), A vertex at (1, 0))
|
|
112
|
+
(0, 1) = (A line in the direction (0, 1), A vertex at (-1, 0))
|
|
113
|
+
|
|
114
|
+
EXAMPLES::
|
|
115
|
+
|
|
116
|
+
sage: trunc_quadr = Polyhedron(vertices=[[1,0],[0,1]], rays=[[1,0],[0,1]])
|
|
117
|
+
sage: trunc_quadr
|
|
118
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 2 rays
|
|
119
|
+
sage: v = next(trunc_quadr.vertex_generator()) # the first vertex in the internal enumeration
|
|
120
|
+
sage: v
|
|
121
|
+
A vertex at (0, 1)
|
|
122
|
+
sage: v.vector()
|
|
123
|
+
(0, 1)
|
|
124
|
+
sage: list(v)
|
|
125
|
+
[0, 1]
|
|
126
|
+
sage: len(v)
|
|
127
|
+
2
|
|
128
|
+
sage: v[0] + v[1]
|
|
129
|
+
1
|
|
130
|
+
sage: v.is_vertex()
|
|
131
|
+
True
|
|
132
|
+
sage: type(v)
|
|
133
|
+
<class 'sage.geometry.polyhedron.representation.Vertex'>
|
|
134
|
+
sage: type( v() )
|
|
135
|
+
<class 'sage.modules.vector_rational_dense.Vector_rational_dense'>
|
|
136
|
+
sage: v.polyhedron()
|
|
137
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 2 rays
|
|
138
|
+
sage: r = next(trunc_quadr.ray_generator())
|
|
139
|
+
sage: r
|
|
140
|
+
A ray in the direction (0, 1)
|
|
141
|
+
sage: r.vector()
|
|
142
|
+
(0, 1)
|
|
143
|
+
sage: list( v.neighbors() )
|
|
144
|
+
[A ray in the direction (0, 1), A vertex at (1, 0)]
|
|
145
|
+
|
|
146
|
+
Inequalities `A \vec{x} + b \geq 0` (and, similarly, equations) are
|
|
147
|
+
specified by a list ``[b, A]``::
|
|
148
|
+
|
|
149
|
+
sage: Polyhedron(ieqs=[(0,1,0),(0,0,1),(1,-1,-1)]).Hrepresentation()
|
|
150
|
+
(An inequality (-1, -1) x + 1 >= 0,
|
|
151
|
+
An inequality (1, 0) x + 0 >= 0,
|
|
152
|
+
An inequality (0, 1) x + 0 >= 0)
|
|
153
|
+
|
|
154
|
+
See :func:`Polyhedron` for a detailed description of all possible ways
|
|
155
|
+
to construct a polyhedron.
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
Base Rings
|
|
159
|
+
----------
|
|
160
|
+
|
|
161
|
+
The base ring of the polyhedron can be specified by the ``base_ring``
|
|
162
|
+
optional keyword argument. If not specified, a suitable common base
|
|
163
|
+
ring for all coordinates and coefficients will be chosen
|
|
164
|
+
automatically. Important cases are:
|
|
165
|
+
|
|
166
|
+
* ``base_ring=QQ`` uses a fast implementation for exact rational numbers.
|
|
167
|
+
|
|
168
|
+
* ``base_ring=ZZ`` is similar to ``QQ``, but the resulting polyhedron
|
|
169
|
+
object will have extra methods for lattice polyhedra.
|
|
170
|
+
|
|
171
|
+
* ``base_ring=RDF`` uses floating point numbers, this is fast but
|
|
172
|
+
susceptible to numerical errors.
|
|
173
|
+
|
|
174
|
+
Polyhedra with symmetries often are defined over some algebraic field
|
|
175
|
+
extension of the rationals. As a simple example, consider the
|
|
176
|
+
equilateral triangle whose vertex coordinates involve `\sqrt{3}`. An
|
|
177
|
+
exact way to work with roots in Sage is the
|
|
178
|
+
:mod:`Algebraic Real Field <sage.rings.qqbar>` ::
|
|
179
|
+
|
|
180
|
+
sage: triangle = Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)], base_ring=AA) # needs sage.rings.number_field sage.symbolic
|
|
181
|
+
sage: triangle.Hrepresentation() # needs sage.rings.number_field sage.symbolic
|
|
182
|
+
(An inequality (-1, -0.5773502691896258?) x + 1 >= 0,
|
|
183
|
+
An inequality (1, -0.5773502691896258?) x + 0 >= 0,
|
|
184
|
+
An inequality (0, 1.154700538379252?) x + 0 >= 0)
|
|
185
|
+
|
|
186
|
+
Without specifying the ``base_ring``, the ``sqrt(3)`` would be a
|
|
187
|
+
symbolic ring element and, therefore, the polyhedron defined over the
|
|
188
|
+
symbolic ring. This is currently not supported as SR is not exact::
|
|
189
|
+
|
|
190
|
+
sage: Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)]) # needs sage.symbolic
|
|
191
|
+
Traceback (most recent call last):
|
|
192
|
+
...
|
|
193
|
+
ValueError: no default backend for computations with Symbolic Ring
|
|
194
|
+
|
|
195
|
+
sage: SR.is_exact() # needs sage.symbolic
|
|
196
|
+
False
|
|
197
|
+
|
|
198
|
+
Even faster than all algebraic real numbers (the field ``AA``) is
|
|
199
|
+
to take the smallest extension field. For the equilateral
|
|
200
|
+
triangle, that would be::
|
|
201
|
+
|
|
202
|
+
sage: x = polygen(ZZ, 'x')
|
|
203
|
+
sage: K.<sqrt3> = NumberField(x^2 - 3, embedding=AA(3)**(1/2)) # needs sage.rings.number_field
|
|
204
|
+
sage: Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # needs sage.rings.number_field
|
|
205
|
+
A 2-dimensional polyhedron in
|
|
206
|
+
(Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)^2
|
|
207
|
+
defined as the convex hull of 3 vertices
|
|
208
|
+
|
|
209
|
+
.. WARNING::
|
|
210
|
+
|
|
211
|
+
Be careful when you construct polyhedra with floating point numbers. The only
|
|
212
|
+
available backend for such computation is ``cdd`` which uses machine floating
|
|
213
|
+
point numbers which have limited precision. If the input consists of
|
|
214
|
+
floating point numbers and the ``base_ring`` is not specified, the base ring is
|
|
215
|
+
set to be the ``RealField`` with the precision given by the minimal bit precision
|
|
216
|
+
of the input. Then, if the obtained minimum is 53 bits of precision, the
|
|
217
|
+
constructor converts automatically the base ring to ``RDF``. Otherwise,
|
|
218
|
+
it returns an error::
|
|
219
|
+
|
|
220
|
+
sage: Polyhedron(vertices=[[1.12345678901234, 2.12345678901234]]) # needs cddexec
|
|
221
|
+
A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex
|
|
222
|
+
sage: Polyhedron(vertices=[[1.12345678901234, 2.123456789012345]]) # needs cddexec
|
|
223
|
+
A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex
|
|
224
|
+
sage: Polyhedron(vertices=[[1.123456789012345, 2.123456789012345]]) # needs sage.rings.real_mpfr
|
|
225
|
+
Traceback (most recent call last):
|
|
226
|
+
...
|
|
227
|
+
ValueError: the only allowed inexact ring is 'RDF' with backend 'cdd'
|
|
228
|
+
|
|
229
|
+
The strongly suggested method to input floating point numbers is to specify the
|
|
230
|
+
``base_ring`` to be ``RDF``::
|
|
231
|
+
|
|
232
|
+
sage: Polyhedron(vertices=[[1.123456789012345, 2.123456789012345]], base_ring=RDF) # needs cddexec
|
|
233
|
+
A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex
|
|
234
|
+
|
|
235
|
+
.. SEEALSO::
|
|
236
|
+
|
|
237
|
+
:mod:`Parents for polyhedra <sage.geometry.polyhedron.parent.Polyhedra>`
|
|
238
|
+
|
|
239
|
+
Base classes
|
|
240
|
+
------------
|
|
241
|
+
|
|
242
|
+
Depending on the chosen base ring, a specific class is used to represent the polyhedron object.
|
|
243
|
+
|
|
244
|
+
.. SEEALSO::
|
|
245
|
+
|
|
246
|
+
- :mod:`Base class for polyhedra <sage.geometry.polyhedron.base.Polyhedron_base>`
|
|
247
|
+
- :mod:`Base class for polyhedra over integers <sage.geometry.polyhedron.base_ZZ.Polyhedron_ZZ>`
|
|
248
|
+
- :mod:`Base class for polyhedra over rationals <sage.geometry.polyhedron.base_QQ.Polyhedron_QQ>`
|
|
249
|
+
- :mod:`Base class for polyhedra over RDF <sage.geometry.polyhedron.base_RDF.Polyhedron_RDF>`
|
|
250
|
+
|
|
251
|
+
The most important base class is **Base class for polyhedra** from which other base classes and backends inherit.
|
|
252
|
+
|
|
253
|
+
Backends
|
|
254
|
+
--------
|
|
255
|
+
|
|
256
|
+
There are different backends available to deal with polyhedron objects.
|
|
257
|
+
|
|
258
|
+
.. SEEALSO::
|
|
259
|
+
|
|
260
|
+
- :mod:`cdd backend for polyhedra <sage.geometry.polyhedron.backend_cdd.Polyhedron_cdd>`
|
|
261
|
+
- :mod:`field backend for polyhedra <sage.geometry.polyhedron.backend_field.Polyhedron_field>`
|
|
262
|
+
- :mod:`normaliz backend for polyhedra <sage.geometry.polyhedron.backend_normaliz.Polyhedron_normaliz>`
|
|
263
|
+
- :mod:`ppl backend for polyhedra <sage.geometry.polyhedron.backend_ppl.Polyhedron_ppl>`
|
|
264
|
+
|
|
265
|
+
.. NOTE::
|
|
266
|
+
|
|
267
|
+
Depending on the backend used, it may occur that different methods are
|
|
268
|
+
available or not.
|
|
269
|
+
|
|
270
|
+
Appendix
|
|
271
|
+
--------
|
|
272
|
+
|
|
273
|
+
REFERENCES:
|
|
274
|
+
|
|
275
|
+
Komei Fukuda's `FAQ in Polyhedral Computation
|
|
276
|
+
<https://cddlib.github.io/polyhedral_faq/>`_
|
|
277
|
+
|
|
278
|
+
AUTHORS:
|
|
279
|
+
|
|
280
|
+
- Marshall Hampton: first version, bug fixes, and various improvements, 2008 and 2009
|
|
281
|
+
- Arnaud Bergeron: improvements to triangulation and rendering, 2008
|
|
282
|
+
- Sebastien Barthelemy: documentation improvements, 2008
|
|
283
|
+
- Volker Braun: refactoring, handle non-compact case, 2009 and 2010
|
|
284
|
+
- Andrey Novoseltsev: added lattice_from_incidences, 2010
|
|
285
|
+
- Volker Braun: rewrite to use PPL instead of cddlib, 2011
|
|
286
|
+
- Volker Braun: Add support for arbitrary subfields of the reals
|
|
287
|
+
"""
|
|
288
|
+
|
|
289
|
+
########################################################################
|
|
290
|
+
# Copyright (C) 2008 Marshall Hampton <hamptonio@gmail.com>
|
|
291
|
+
# Copyright (C) 2014 Volker Braun <vbraun.name@gmail.com>
|
|
292
|
+
#
|
|
293
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
294
|
+
#
|
|
295
|
+
# https://www.gnu.org/licenses/
|
|
296
|
+
########################################################################
|
|
297
|
+
|
|
298
|
+
import sage.geometry.abc
|
|
299
|
+
|
|
300
|
+
from sage.rings.integer_ring import ZZ
|
|
301
|
+
|
|
302
|
+
from .misc import _make_listlist, _common_length_of
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
#########################################################################
|
|
306
|
+
def Polyhedron(vertices=None, rays=None, lines=None,
|
|
307
|
+
ieqs=None, eqns=None,
|
|
308
|
+
ambient_dim=None, base_ring=None, minimize=True, verbose=False,
|
|
309
|
+
backend=None, mutable=False):
|
|
310
|
+
r"""
|
|
311
|
+
Construct a polyhedron object.
|
|
312
|
+
|
|
313
|
+
You may either define it with vertex/ray/line or
|
|
314
|
+
inequalities/equations data, but not both. Redundant data will
|
|
315
|
+
automatically be removed (unless ``minimize=False``), and the
|
|
316
|
+
complementary representation will be computed.
|
|
317
|
+
|
|
318
|
+
INPUT:
|
|
319
|
+
|
|
320
|
+
- ``vertices`` -- iterable of points. Each point can be specified as
|
|
321
|
+
any iterable container of ``base_ring`` elements. If ``rays`` or
|
|
322
|
+
``lines`` are specified but no ``vertices``, the origin is
|
|
323
|
+
taken to be the single vertex.
|
|
324
|
+
|
|
325
|
+
Instead of vertices, the first argument can also be an object
|
|
326
|
+
that can be converted to a :func:`Polyhedron` via an :meth:`as_polyhedron`
|
|
327
|
+
or :meth:`polyhedron` method. In this case, the following 5 arguments
|
|
328
|
+
cannot be provided.
|
|
329
|
+
|
|
330
|
+
- ``rays`` -- list of rays; each ray can be specified as any
|
|
331
|
+
iterable container of ``base_ring`` elements
|
|
332
|
+
|
|
333
|
+
- ``lines`` -- list of lines; each line can be specified as any
|
|
334
|
+
iterable container of ``base_ring`` elements
|
|
335
|
+
|
|
336
|
+
- ``ieqs`` -- list of inequalities; each line can be specified as any
|
|
337
|
+
iterable container of ``base_ring`` elements. An entry equal to
|
|
338
|
+
``[-1,7,3,4]`` represents the inequality `7x_1+3x_2+4x_3\geq 1`.
|
|
339
|
+
|
|
340
|
+
- ``eqns`` -- list of equalities; each line can be specified as
|
|
341
|
+
any iterable container of ``base_ring`` elements. An entry equal to
|
|
342
|
+
``[-1,7,3,4]`` represents the equality `7x_1+3x_2+4x_3= 1`.
|
|
343
|
+
|
|
344
|
+
- ``ambient_dim`` -- integer; the ambient space dimension. Usually
|
|
345
|
+
can be figured out automatically from the H/Vrepresentation
|
|
346
|
+
dimensions.
|
|
347
|
+
|
|
348
|
+
- ``base_ring`` -- a sub-field of the reals implemented in
|
|
349
|
+
Sage. The field over which the polyhedron will be defined. For
|
|
350
|
+
``QQ`` and algebraic extensions, exact arithmetic will be
|
|
351
|
+
used. For ``RDF``, floating point numbers will be used. Floating
|
|
352
|
+
point arithmetic is faster but might give the wrong result for
|
|
353
|
+
degenerate input.
|
|
354
|
+
|
|
355
|
+
- ``backend`` -- string or ``None`` (default). The backend to use. Valid choices are
|
|
356
|
+
|
|
357
|
+
* ``'cdd'``: use cdd
|
|
358
|
+
(:mod:`~sage.geometry.polyhedron.backend_cdd`) with `\QQ` or
|
|
359
|
+
`\RDF` coefficients depending on ``base_ring``
|
|
360
|
+
|
|
361
|
+
* ``'normaliz'``: use normaliz
|
|
362
|
+
(:mod:`~sage.geometry.polyhedron.backend_normaliz`) with `\ZZ` or
|
|
363
|
+
`\QQ` coefficients depending on ``base_ring``
|
|
364
|
+
|
|
365
|
+
* ``'polymake'``: use polymake
|
|
366
|
+
(:mod:`~sage.geometry.polyhedron.backend_polymake`) with `\QQ`, `\RDF` or
|
|
367
|
+
``QuadraticField`` coefficients depending on ``base_ring``
|
|
368
|
+
|
|
369
|
+
* ``'ppl'``: use ppl
|
|
370
|
+
(:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\ZZ` or
|
|
371
|
+
`\QQ` coefficients depending on ``base_ring``
|
|
372
|
+
|
|
373
|
+
* ``'field'``: use python implementation
|
|
374
|
+
(:mod:`~sage.geometry.polyhedron.backend_field`) for any field
|
|
375
|
+
|
|
376
|
+
Some backends support further optional arguments:
|
|
377
|
+
|
|
378
|
+
- ``minimize`` -- boolean (default: ``True``); whether to
|
|
379
|
+
immediately remove redundant H/V-representation data; currently
|
|
380
|
+
not used.
|
|
381
|
+
|
|
382
|
+
- ``verbose`` -- boolean (default: ``False``); whether to print
|
|
383
|
+
verbose output for debugging purposes; only supported by the cdd and
|
|
384
|
+
normaliz backends
|
|
385
|
+
|
|
386
|
+
- ``mutable`` -- boolean (default: ``False``); whether the polyhedron
|
|
387
|
+
is mutable
|
|
388
|
+
|
|
389
|
+
OUTPUT: the polyhedron defined by the input data
|
|
390
|
+
|
|
391
|
+
EXAMPLES:
|
|
392
|
+
|
|
393
|
+
Construct some polyhedra::
|
|
394
|
+
|
|
395
|
+
sage: square_from_vertices = Polyhedron(vertices=[[1, 1], [1, -1], [-1, 1], [-1, -1]])
|
|
396
|
+
sage: square_from_ieqs = Polyhedron(ieqs=[[1, 0, 1], [1, 1, 0], [1, 0, -1], [1, -1, 0]])
|
|
397
|
+
sage: list(square_from_ieqs.vertex_generator())
|
|
398
|
+
[A vertex at (1, -1),
|
|
399
|
+
A vertex at (1, 1),
|
|
400
|
+
A vertex at (-1, 1),
|
|
401
|
+
A vertex at (-1, -1)]
|
|
402
|
+
sage: list(square_from_vertices.inequality_generator())
|
|
403
|
+
[An inequality (1, 0) x + 1 >= 0,
|
|
404
|
+
An inequality (0, 1) x + 1 >= 0,
|
|
405
|
+
An inequality (-1, 0) x + 1 >= 0,
|
|
406
|
+
An inequality (0, -1) x + 1 >= 0]
|
|
407
|
+
sage: p = Polyhedron(vertices=[[1.1, 2.2], [3.3, 4.4]], base_ring=RDF) # needs cddexec
|
|
408
|
+
sage: p.n_inequalities() # needs cddexec
|
|
409
|
+
2
|
|
410
|
+
|
|
411
|
+
The same polyhedron given in two ways::
|
|
412
|
+
|
|
413
|
+
sage: p = Polyhedron(ieqs=[[0,1,0,0],[0,0,1,0]])
|
|
414
|
+
sage: p.Vrepresentation()
|
|
415
|
+
(A line in the direction (0, 0, 1),
|
|
416
|
+
A ray in the direction (1, 0, 0),
|
|
417
|
+
A ray in the direction (0, 1, 0),
|
|
418
|
+
A vertex at (0, 0, 0))
|
|
419
|
+
sage: q = Polyhedron(vertices=[[0,0,0]], rays=[[1,0,0],[0,1,0]], lines=[[0,0,1]])
|
|
420
|
+
sage: q.Hrepresentation()
|
|
421
|
+
(An inequality (1, 0, 0) x + 0 >= 0,
|
|
422
|
+
An inequality (0, 1, 0) x + 0 >= 0)
|
|
423
|
+
|
|
424
|
+
Finally, a more complicated example. Take `\mathbb{R}_{\geq 0}^6` with
|
|
425
|
+
coordinates `a, b, \dots, f` and
|
|
426
|
+
|
|
427
|
+
* The inequality `e+b \geq c+d`
|
|
428
|
+
* The inequality `e+c \geq b+d`
|
|
429
|
+
* The equation `a+b+c+d+e+f = 31`
|
|
430
|
+
|
|
431
|
+
::
|
|
432
|
+
|
|
433
|
+
sage: positive_coords = Polyhedron(ieqs=[
|
|
434
|
+
....: [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0],
|
|
435
|
+
....: [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1]])
|
|
436
|
+
sage: P = Polyhedron(ieqs=positive_coords.inequalities() + (
|
|
437
|
+
....: [0,0,1,-1,-1,1,0], [0,0,-1,1,-1,1,0]), eqns=[[-31,1,1,1,1,1,1]])
|
|
438
|
+
sage: P
|
|
439
|
+
A 5-dimensional polyhedron in QQ^6 defined as the convex hull of 7 vertices
|
|
440
|
+
sage: P.dim()
|
|
441
|
+
5
|
|
442
|
+
sage: P.Vrepresentation()
|
|
443
|
+
(A vertex at (31, 0, 0, 0, 0, 0), A vertex at (0, 0, 0, 0, 0, 31),
|
|
444
|
+
A vertex at (0, 0, 0, 0, 31, 0), A vertex at (0, 0, 31/2, 0, 31/2, 0),
|
|
445
|
+
A vertex at (0, 31/2, 31/2, 0, 0, 0), A vertex at (0, 31/2, 0, 0, 31/2, 0),
|
|
446
|
+
A vertex at (0, 0, 0, 31/2, 31/2, 0))
|
|
447
|
+
|
|
448
|
+
Regular icosahedron, centered at `0` with edge length `2`, with vertices given
|
|
449
|
+
by the cyclic shifts of `(0, \pm 1, \pm (1+\sqrt(5))/2)`, cf.
|
|
450
|
+
:wikipedia:`Regular_icosahedron`. It needs a number field::
|
|
451
|
+
|
|
452
|
+
sage: # needs sage.rings.number_field
|
|
453
|
+
sage: R0.<r0> = QQ[]
|
|
454
|
+
sage: R1.<r1> = NumberField(r0^2-5, embedding=AA(5)**(1/2))
|
|
455
|
+
sage: gold = (1+r1)/2
|
|
456
|
+
sage: v = [[0, 1, gold], [0, 1, -gold], [0, -1, gold], [0, -1, -gold]]
|
|
457
|
+
sage: pp = Permutation((1, 2, 3))
|
|
458
|
+
sage: icosah = Polyhedron( # needs sage.combinat
|
|
459
|
+
....: [(pp^2).action(w) for w in v] + [pp.action(w) for w in v] + v,
|
|
460
|
+
....: base_ring=R1)
|
|
461
|
+
sage: len(icosah.faces(2)) # needs sage.combinat
|
|
462
|
+
20
|
|
463
|
+
|
|
464
|
+
When the input contains elements of a Number Field, they require an
|
|
465
|
+
embedding::
|
|
466
|
+
|
|
467
|
+
sage: # needs sage.rings.number_field
|
|
468
|
+
sage: x = polygen(ZZ, 'x')
|
|
469
|
+
sage: K = NumberField(x^2 - 2,'s')
|
|
470
|
+
sage: s = K.0
|
|
471
|
+
sage: L = NumberField(x^3 - 2,'t')
|
|
472
|
+
sage: t = L.0
|
|
473
|
+
sage: P = Polyhedron(vertices=[[0,s], [t,0]])
|
|
474
|
+
Traceback (most recent call last):
|
|
475
|
+
...
|
|
476
|
+
ValueError: invalid base ring
|
|
477
|
+
|
|
478
|
+
Converting from a given polyhedron::
|
|
479
|
+
|
|
480
|
+
sage: cb = polytopes.cube(); cb
|
|
481
|
+
A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices
|
|
482
|
+
sage: Polyhedron(cb, base_ring=QQ)
|
|
483
|
+
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 8 vertices
|
|
484
|
+
|
|
485
|
+
Converting from other objects to a polyhedron::
|
|
486
|
+
|
|
487
|
+
sage: quadrant = Cone([(1,0), (0,1)])
|
|
488
|
+
sage: Polyhedron(quadrant)
|
|
489
|
+
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex and 2 rays
|
|
490
|
+
sage: Polyhedron(quadrant, base_ring=QQ)
|
|
491
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays
|
|
492
|
+
|
|
493
|
+
sage: o = lattice_polytope.cross_polytope(2)
|
|
494
|
+
sage: Polyhedron(o)
|
|
495
|
+
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices
|
|
496
|
+
sage: Polyhedron(o, base_ring=QQ)
|
|
497
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
|
|
498
|
+
|
|
499
|
+
sage: p = MixedIntegerLinearProgram(solver='PPL')
|
|
500
|
+
sage: x, y = p['x'], p['y']
|
|
501
|
+
sage: p.add_constraint(x <= 1)
|
|
502
|
+
sage: p.add_constraint(x >= -1)
|
|
503
|
+
sage: p.add_constraint(y <= 1)
|
|
504
|
+
sage: p.add_constraint(y >= -1)
|
|
505
|
+
sage: Polyhedron(p, base_ring=ZZ)
|
|
506
|
+
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices
|
|
507
|
+
sage: Polyhedron(p)
|
|
508
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
|
|
509
|
+
|
|
510
|
+
sage: # needs sage.combinat
|
|
511
|
+
sage: H.<x,y> = HyperplaneArrangements(QQ)
|
|
512
|
+
sage: h = x + y - 1; h
|
|
513
|
+
Hyperplane x + y - 1
|
|
514
|
+
sage: Polyhedron(h, base_ring=ZZ)
|
|
515
|
+
A 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex and 1 line
|
|
516
|
+
sage: Polyhedron(h)
|
|
517
|
+
A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line
|
|
518
|
+
|
|
519
|
+
.. NOTE::
|
|
520
|
+
|
|
521
|
+
* Once constructed, a ``Polyhedron`` object is immutable.
|
|
522
|
+
|
|
523
|
+
* Although the option ``base_ring=RDF`` allows numerical data to
|
|
524
|
+
be used, it might not give the right answer for degenerate
|
|
525
|
+
input data - the results can depend upon the tolerance
|
|
526
|
+
setting of cdd.
|
|
527
|
+
|
|
528
|
+
TESTS:
|
|
529
|
+
|
|
530
|
+
Check that giving ``float`` input gets converted to ``RDF`` (see :issue:`22605`)::
|
|
531
|
+
|
|
532
|
+
sage: f = float(1.1)
|
|
533
|
+
sage: Polyhedron(vertices=[[f]]) # needs cddexec
|
|
534
|
+
A 0-dimensional polyhedron in RDF^1 defined as the convex hull of 1 vertex
|
|
535
|
+
|
|
536
|
+
Check that giving ``int`` input gets converted to ``ZZ`` (see :issue:`22605`)::
|
|
537
|
+
|
|
538
|
+
sage: Polyhedron(vertices=[[int(42)]])
|
|
539
|
+
A 0-dimensional polyhedron in ZZ^1 defined as the convex hull of 1 vertex
|
|
540
|
+
|
|
541
|
+
Check that giving ``Fraction`` input gets converted to ``QQ`` (see :issue:`22605`)::
|
|
542
|
+
|
|
543
|
+
sage: from fractions import Fraction
|
|
544
|
+
sage: f = Fraction(int(6), int(8))
|
|
545
|
+
sage: Polyhedron(vertices=[[f]])
|
|
546
|
+
A 0-dimensional polyhedron in QQ^1 defined as the convex hull of 1 vertex
|
|
547
|
+
|
|
548
|
+
Check that non-compact polyhedra given by V-representation have base ring ``QQ``,
|
|
549
|
+
not ``ZZ`` (see :issue:`27840`)::
|
|
550
|
+
|
|
551
|
+
sage: Q = Polyhedron(vertices=[(1, 2, 3), (1, 3, 2), (2, 1, 3),
|
|
552
|
+
....: (2, 3, 1), (3, 1, 2), (3, 2, 1)],
|
|
553
|
+
....: rays=[[1, 1, 1]], lines=[[1, 2, 3]], backend='ppl')
|
|
554
|
+
sage: Q.base_ring()
|
|
555
|
+
Rational Field
|
|
556
|
+
|
|
557
|
+
Check that enforcing base ring `ZZ` for this example gives an error::
|
|
558
|
+
|
|
559
|
+
sage: Q = Polyhedron(vertices=[(1, 2, 3), (1, 3, 2), (2, 1, 3),
|
|
560
|
+
....: (2, 3, 1), (3, 1, 2), (3, 2, 1)],
|
|
561
|
+
....: rays=[[1, 1, 1]], lines=[[1, 2, 3]], backend='ppl',
|
|
562
|
+
....: base_ring=ZZ)
|
|
563
|
+
Traceback (most recent call last):
|
|
564
|
+
...
|
|
565
|
+
TypeError: no conversion of this rational to integer
|
|
566
|
+
|
|
567
|
+
Check that input with too many bits of precision returns an error (see
|
|
568
|
+
:issue:`22552`)::
|
|
569
|
+
|
|
570
|
+
sage: Polyhedron(vertices=[(8.3319544851638732, 7.0567045956967727), # needs sage.rings.real_mpfr
|
|
571
|
+
....: (6.4876921900819049, 4.8435898415984129)])
|
|
572
|
+
Traceback (most recent call last):
|
|
573
|
+
...
|
|
574
|
+
ValueError: the only allowed inexact ring is 'RDF' with backend 'cdd'
|
|
575
|
+
|
|
576
|
+
Check that setting ``base_ring`` to a ``RealField`` returns an error (see :issue:`22552`)::
|
|
577
|
+
|
|
578
|
+
sage: Polyhedron(vertices=[(8.3, 7.0), (6.4, 4.8)], base_ring=RealField(40)) # needs sage.rings.real_mpfr
|
|
579
|
+
Traceback (most recent call last):
|
|
580
|
+
...
|
|
581
|
+
ValueError: no default backend for computations with Real Field with 40 bits of precision
|
|
582
|
+
sage: Polyhedron(vertices=[(8.3, 7.0), (6.4, 4.8)], base_ring=RealField(53)) # needs sage.rings.real_mpfr
|
|
583
|
+
Traceback (most recent call last):
|
|
584
|
+
...
|
|
585
|
+
ValueError: no default backend for computations with Real Field with 53 bits of precision
|
|
586
|
+
|
|
587
|
+
Check that :issue:`17339` is fixed::
|
|
588
|
+
|
|
589
|
+
sage: Polyhedron(ambient_dim=0, ieqs=[], eqns=[[1]], base_ring=QQ)
|
|
590
|
+
The empty polyhedron in QQ^0
|
|
591
|
+
sage: P = Polyhedron(ambient_dim=0, ieqs=[], eqns=[], base_ring=QQ); P
|
|
592
|
+
A 0-dimensional polyhedron in QQ^0 defined as the convex hull of 1 vertex
|
|
593
|
+
sage: P.Vrepresentation()
|
|
594
|
+
(A vertex at (),)
|
|
595
|
+
sage: Polyhedron(ambient_dim=2, ieqs=[], eqns=[], base_ring=QQ)
|
|
596
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull
|
|
597
|
+
of 1 vertex and 2 lines
|
|
598
|
+
sage: Polyhedron(ambient_dim=2, ieqs=[], eqns=[], base_ring=QQ, backend='field')
|
|
599
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull
|
|
600
|
+
of 1 vertex and 2 lines
|
|
601
|
+
sage: Polyhedron(ambient_dim=0, ieqs=[], eqns=[[1]], base_ring=QQ, backend='cdd') # needs cddexec_gmp
|
|
602
|
+
The empty polyhedron in QQ^0
|
|
603
|
+
sage: Polyhedron(ambient_dim=0, ieqs=[], eqns=[[1]], base_ring=QQ, backend='ppl')
|
|
604
|
+
The empty polyhedron in QQ^0
|
|
605
|
+
sage: Polyhedron(ambient_dim=0, ieqs=[], eqns=[[1]], base_ring=QQ, backend='field')
|
|
606
|
+
The empty polyhedron in QQ^0
|
|
607
|
+
|
|
608
|
+
sage: Polyhedron(ambient_dim=2, vertices=[], rays=[], lines=[], base_ring=QQ)
|
|
609
|
+
The empty polyhedron in QQ^2
|
|
610
|
+
|
|
611
|
+
Create a mutable polyhedron::
|
|
612
|
+
|
|
613
|
+
sage: P = Polyhedron(vertices=[[0, 1], [1, 0]], mutable=True)
|
|
614
|
+
sage: P.is_mutable()
|
|
615
|
+
True
|
|
616
|
+
sage: hasattr(P, "_Vrepresentation")
|
|
617
|
+
False
|
|
618
|
+
sage: P.Vrepresentation()
|
|
619
|
+
(A vertex at (0, 1), A vertex at (1, 0))
|
|
620
|
+
sage: hasattr(P, "_Vrepresentation")
|
|
621
|
+
True
|
|
622
|
+
|
|
623
|
+
.. SEEALSO::
|
|
624
|
+
|
|
625
|
+
:mod:`Library of polytopes <sage.geometry.polyhedron.library>`
|
|
626
|
+
"""
|
|
627
|
+
# Special handling for first argument, for coercion-like uses
|
|
628
|
+
constructor = None
|
|
629
|
+
first_arg = vertices
|
|
630
|
+
if isinstance(first_arg, sage.geometry.abc.Polyhedron):
|
|
631
|
+
constructor = first_arg.change_ring
|
|
632
|
+
try:
|
|
633
|
+
# PolyhedronFace.as_polyhedron (it also has a "polyhedron" method with a different purpose)
|
|
634
|
+
constructor = first_arg.as_polyhedron
|
|
635
|
+
except AttributeError:
|
|
636
|
+
try:
|
|
637
|
+
# ConvexRationalPolyhedralCone, LatticePolytopeClass, MixedIntegerLinearProgram, Hyperplane
|
|
638
|
+
constructor = first_arg.polyhedron
|
|
639
|
+
except AttributeError:
|
|
640
|
+
pass
|
|
641
|
+
if constructor:
|
|
642
|
+
if not all(x is None for x in (rays, lines, ieqs, eqns, ambient_dim)):
|
|
643
|
+
raise ValueError('if a polyhedron is given, cannot provide H- and V-representations objects')
|
|
644
|
+
# Only pass non-default arguments
|
|
645
|
+
kwds = {}
|
|
646
|
+
if base_ring is not None:
|
|
647
|
+
kwds['base_ring'] = base_ring
|
|
648
|
+
if verbose is not False:
|
|
649
|
+
kwds['verbose'] = verbose
|
|
650
|
+
if backend is not None:
|
|
651
|
+
kwds['backend'] = backend
|
|
652
|
+
if minimize is not True:
|
|
653
|
+
kwds['minimize'] = minimize
|
|
654
|
+
if mutable is not False:
|
|
655
|
+
kwds['mutable'] = mutable
|
|
656
|
+
return constructor(**kwds)
|
|
657
|
+
|
|
658
|
+
got_Vrep = not ((vertices is None) and (rays is None) and (lines is None))
|
|
659
|
+
got_Hrep = not ((ieqs is None) and (eqns is None))
|
|
660
|
+
|
|
661
|
+
# Clean up the arguments
|
|
662
|
+
vertices = _make_listlist(vertices)
|
|
663
|
+
rays = _make_listlist(rays)
|
|
664
|
+
lines = _make_listlist(lines)
|
|
665
|
+
ieqs = _make_listlist(ieqs)
|
|
666
|
+
eqns = _make_listlist(eqns)
|
|
667
|
+
|
|
668
|
+
if got_Vrep and got_Hrep:
|
|
669
|
+
raise ValueError('cannot specify both H- and V-representation.')
|
|
670
|
+
elif got_Vrep:
|
|
671
|
+
deduced_ambient_dim = _common_length_of(vertices, rays, lines)[1]
|
|
672
|
+
if deduced_ambient_dim is None:
|
|
673
|
+
if ambient_dim is not None:
|
|
674
|
+
deduced_ambient_dim = ambient_dim
|
|
675
|
+
else:
|
|
676
|
+
deduced_ambient_dim = 0
|
|
677
|
+
elif got_Hrep:
|
|
678
|
+
deduced_ambient_dim = _common_length_of(ieqs, eqns)[1]
|
|
679
|
+
if deduced_ambient_dim is None:
|
|
680
|
+
if ambient_dim is not None:
|
|
681
|
+
deduced_ambient_dim = ambient_dim
|
|
682
|
+
else:
|
|
683
|
+
deduced_ambient_dim = 0
|
|
684
|
+
else:
|
|
685
|
+
deduced_ambient_dim -= 1
|
|
686
|
+
else:
|
|
687
|
+
if ambient_dim is None:
|
|
688
|
+
deduced_ambient_dim = 0
|
|
689
|
+
else:
|
|
690
|
+
deduced_ambient_dim = ambient_dim
|
|
691
|
+
if base_ring is None:
|
|
692
|
+
base_ring = ZZ
|
|
693
|
+
|
|
694
|
+
# set ambient_dim
|
|
695
|
+
if ambient_dim is not None and deduced_ambient_dim != ambient_dim:
|
|
696
|
+
raise ValueError('ambient space dimension mismatch. Try removing the "ambient_dim" parameter.')
|
|
697
|
+
ambient_dim = deduced_ambient_dim
|
|
698
|
+
|
|
699
|
+
# figure out base_ring
|
|
700
|
+
from sage.misc.flatten import flatten
|
|
701
|
+
from sage.structure.element import parent
|
|
702
|
+
from sage.categories.fields import Fields
|
|
703
|
+
from sage.categories.rings import Rings
|
|
704
|
+
|
|
705
|
+
values = flatten(vertices + rays + lines + ieqs + eqns)
|
|
706
|
+
if base_ring is not None:
|
|
707
|
+
convert = any(parent(x) is not base_ring for x in values)
|
|
708
|
+
elif not values:
|
|
709
|
+
base_ring = ZZ
|
|
710
|
+
convert = False
|
|
711
|
+
else:
|
|
712
|
+
P = parent(values[0])
|
|
713
|
+
if any(parent(x) is not P for x in values):
|
|
714
|
+
from sage.structure.sequence import Sequence
|
|
715
|
+
P = Sequence(values).universe()
|
|
716
|
+
convert = True
|
|
717
|
+
else:
|
|
718
|
+
convert = False
|
|
719
|
+
|
|
720
|
+
from sage.structure.coerce import py_scalar_parent
|
|
721
|
+
if isinstance(P, type):
|
|
722
|
+
base_ring = py_scalar_parent(P)
|
|
723
|
+
convert = convert or P is not base_ring
|
|
724
|
+
else:
|
|
725
|
+
base_ring = P
|
|
726
|
+
|
|
727
|
+
if base_ring not in Fields():
|
|
728
|
+
got_compact_Vrep = got_Vrep and not rays and not lines
|
|
729
|
+
got_cone_Vrep = got_Vrep and all(x == 0
|
|
730
|
+
for v in vertices for x in v)
|
|
731
|
+
if not got_compact_Vrep and not got_cone_Vrep:
|
|
732
|
+
base_ring = base_ring.fraction_field()
|
|
733
|
+
convert = True
|
|
734
|
+
|
|
735
|
+
if base_ring not in Rings():
|
|
736
|
+
raise ValueError('invalid base ring')
|
|
737
|
+
|
|
738
|
+
try:
|
|
739
|
+
from sage.symbolic.ring import SR
|
|
740
|
+
except ImportError:
|
|
741
|
+
SR = None
|
|
742
|
+
if base_ring is not SR and not base_ring.is_exact():
|
|
743
|
+
try:
|
|
744
|
+
from sage.rings.real_double import RDF
|
|
745
|
+
except ImportError:
|
|
746
|
+
RDF = None
|
|
747
|
+
try:
|
|
748
|
+
from sage.rings.real_mpfr import RR
|
|
749
|
+
except ImportError:
|
|
750
|
+
RR = None
|
|
751
|
+
# TODO: remove this hack?
|
|
752
|
+
if base_ring is RR:
|
|
753
|
+
base_ring = RDF
|
|
754
|
+
convert = True
|
|
755
|
+
elif base_ring is not RDF:
|
|
756
|
+
raise ValueError("the only allowed inexact ring is 'RDF' with backend 'cdd'")
|
|
757
|
+
|
|
758
|
+
# Add the origin if necessary
|
|
759
|
+
if got_Vrep and len(vertices) == 0 and bool(rays + lines):
|
|
760
|
+
vertices = [[0] * ambient_dim]
|
|
761
|
+
|
|
762
|
+
# Specific backends can override the base_ring
|
|
763
|
+
from sage.geometry.polyhedron.parent import Polyhedra
|
|
764
|
+
parent = Polyhedra(base_ring, ambient_dim, backend=backend)
|
|
765
|
+
base_ring = parent.base_ring()
|
|
766
|
+
|
|
767
|
+
# finally, construct the Polyhedron
|
|
768
|
+
Hrep = Vrep = None
|
|
769
|
+
if got_Hrep:
|
|
770
|
+
Hrep = [ieqs, eqns]
|
|
771
|
+
if got_Vrep:
|
|
772
|
+
Vrep = [vertices, rays, lines]
|
|
773
|
+
return parent(Vrep, Hrep, convert=convert, verbose=verbose, mutable=mutable)
|