passagemath-polyhedra 10.6.31rc3__cp314-cp314-musllinux_1_2_aarch64.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 +208 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +5 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_polyhedra.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_polyhedra.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_polyhedra.libs/libgomp-1ede7ee7.so.1.0.0 +0 -0
- passagemath_polyhedra.libs/libstdc++-85f2cd6d.so.6.0.33 +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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
- sage/numerical/backends/cvxpy_backend.cpython-314-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.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-aarch64-linux-musl.so +0 -0
- sage/numerical/linear_tensor_element.pxd +6 -0
- sage/numerical/linear_tensor_element.pyx +459 -0
- sage/numerical/mip.cpython-314-aarch64-linux-musl.so +0 -0
- sage/numerical/mip.pxd +40 -0
- sage/numerical/mip.pyx +3667 -0
- sage/numerical/sdp.cpython-314-aarch64-linux-musl.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-aarch64-linux-musl.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,1723 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-polyhedra
|
|
2
|
+
"""
|
|
3
|
+
H(yperplane) and V(ertex) representation objects for polyhedra
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# ****************************************************************************
|
|
7
|
+
# Copyright (C) 2008 Marshall Hampton <hamptonio@gmail.com>
|
|
8
|
+
# Copyright (C) 2011 Volker Braun <vbraun.name@gmail.com>
|
|
9
|
+
#
|
|
10
|
+
# This program is free software: you can redistribute it and/or modify
|
|
11
|
+
# it under the terms of the GNU General Public License as published by
|
|
12
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
13
|
+
# (at your option) any later version.
|
|
14
|
+
# https://www.gnu.org/licenses/
|
|
15
|
+
# ****************************************************************************
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
from sage.structure.sage_object import SageObject
|
|
19
|
+
from sage.structure.element import Vector
|
|
20
|
+
from sage.structure.richcmp import richcmp_method, richcmp
|
|
21
|
+
from sage.rings.integer_ring import ZZ
|
|
22
|
+
from sage.modules.free_module_element import vector
|
|
23
|
+
from copy import copy
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# Numeric values to distinguish representation types
|
|
27
|
+
INEQUALITY = 0
|
|
28
|
+
EQUATION = 1
|
|
29
|
+
VERTEX = 2
|
|
30
|
+
RAY = 3
|
|
31
|
+
LINE = 4
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
#########################################################################
|
|
35
|
+
# PolyhedronRepresentation
|
|
36
|
+
# / \
|
|
37
|
+
# / \
|
|
38
|
+
# Hrepresentation Vrepresentation
|
|
39
|
+
# / \ / | \
|
|
40
|
+
# / \ / | \
|
|
41
|
+
# Inequality Equation Vertex Ray Line
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@richcmp_method
|
|
45
|
+
class PolyhedronRepresentation(SageObject):
|
|
46
|
+
"""
|
|
47
|
+
The internal base class for all representation objects of
|
|
48
|
+
``Polyhedron`` (vertices/rays/lines and inequalities/equations)
|
|
49
|
+
|
|
50
|
+
.. NOTE::
|
|
51
|
+
|
|
52
|
+
You should not (and cannot) instantiate it yourself. You can
|
|
53
|
+
only obtain them from a Polyhedron() class.
|
|
54
|
+
|
|
55
|
+
TESTS::
|
|
56
|
+
|
|
57
|
+
sage: import sage.geometry.polyhedron.representation as P
|
|
58
|
+
sage: P.PolyhedronRepresentation()
|
|
59
|
+
<sage.geometry.polyhedron.representation.PolyhedronRepresentation object at ...>
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
# Numeric values for the output of the type() method
|
|
63
|
+
INEQUALITY = INEQUALITY
|
|
64
|
+
EQUATION = EQUATION
|
|
65
|
+
VERTEX = VERTEX
|
|
66
|
+
RAY = RAY
|
|
67
|
+
LINE = LINE
|
|
68
|
+
|
|
69
|
+
def __len__(self):
|
|
70
|
+
"""
|
|
71
|
+
Return the length of the representation data.
|
|
72
|
+
|
|
73
|
+
TESTS::
|
|
74
|
+
|
|
75
|
+
sage: p = Polyhedron(vertices=[[1,2,3]])
|
|
76
|
+
sage: v = p.Vrepresentation(0)
|
|
77
|
+
sage: v.__len__()
|
|
78
|
+
3
|
|
79
|
+
"""
|
|
80
|
+
return self._vector.degree()
|
|
81
|
+
|
|
82
|
+
def __getitem__(self, i):
|
|
83
|
+
"""
|
|
84
|
+
Supports indexing.
|
|
85
|
+
|
|
86
|
+
TESTS::
|
|
87
|
+
|
|
88
|
+
sage: p = Polyhedron(vertices=[[1,2,3]])
|
|
89
|
+
sage: v = p.Vrepresentation(0)
|
|
90
|
+
sage: v.__getitem__(1)
|
|
91
|
+
2
|
|
92
|
+
"""
|
|
93
|
+
return self._vector[i]
|
|
94
|
+
|
|
95
|
+
def __hash__(self):
|
|
96
|
+
r"""
|
|
97
|
+
TESTS::
|
|
98
|
+
|
|
99
|
+
sage: from sage.geometry.polyhedron.representation import Hrepresentation
|
|
100
|
+
sage: pr = Hrepresentation(Polyhedron(vertices = [[1,2,3]]).parent())
|
|
101
|
+
sage: hash(pr) == hash(tuple([0,0,0,0]))
|
|
102
|
+
True
|
|
103
|
+
"""
|
|
104
|
+
# TODO: ideally the argument self._vector of self should be immutable.
|
|
105
|
+
# So that we could change the line below by hash(self._vector). The
|
|
106
|
+
# mutability is kept because this argument might be reused (see e.g.
|
|
107
|
+
# Hrepresentation._set_data below).
|
|
108
|
+
return hash(tuple(self._vector))
|
|
109
|
+
|
|
110
|
+
def __richcmp__(self, other, op):
|
|
111
|
+
"""
|
|
112
|
+
Compare two representation objects.
|
|
113
|
+
|
|
114
|
+
This method defines a linear order on the H/V-representation objects.
|
|
115
|
+
The order is first determined by the types of the objects,
|
|
116
|
+
such that inequality < equation < vertex < ray < line.
|
|
117
|
+
Then, representation objects with the same type are ordered
|
|
118
|
+
lexicographically according to their canonical vectors.
|
|
119
|
+
|
|
120
|
+
Thus, two representation objects are equal if and only if they define
|
|
121
|
+
the same vertex/ray/line or inequality/equation in the ambient space,
|
|
122
|
+
regardless of the polyhedron that they belong to.
|
|
123
|
+
|
|
124
|
+
INPUT:
|
|
125
|
+
|
|
126
|
+
- ``other`` -- anything
|
|
127
|
+
|
|
128
|
+
OUTPUT: boolean
|
|
129
|
+
|
|
130
|
+
EXAMPLES::
|
|
131
|
+
|
|
132
|
+
sage: triangle = Polyhedron([(0,0), (1,0), (0,1)])
|
|
133
|
+
sage: ieq = next(triangle.inequality_generator()); ieq
|
|
134
|
+
An inequality (1, 0) x + 0 >= 0
|
|
135
|
+
sage: ieq == copy(ieq)
|
|
136
|
+
True
|
|
137
|
+
|
|
138
|
+
sage: square = Polyhedron([(0,0), (1,0), (0,1), (1,1)], base_ring=QQ)
|
|
139
|
+
sage: square.Vrepresentation(0) == triangle.Vrepresentation(0)
|
|
140
|
+
True
|
|
141
|
+
|
|
142
|
+
sage: ieq = square.Hrepresentation(0); ieq.vector()
|
|
143
|
+
(0, 1, 0)
|
|
144
|
+
sage: ieq != Polyhedron([(0,1,0)]).Vrepresentation(0)
|
|
145
|
+
True
|
|
146
|
+
|
|
147
|
+
sage: H = Polyhedron(vertices=[(4,0)], rays=[(1,1)], lines=[(-1,1)])
|
|
148
|
+
sage: H.vertices()[0] < H.rays()[0] < H.lines()[0]
|
|
149
|
+
True
|
|
150
|
+
|
|
151
|
+
TESTS:
|
|
152
|
+
|
|
153
|
+
Check :issue:`30954`::
|
|
154
|
+
|
|
155
|
+
sage: P = (1/2)*polytopes.cube()
|
|
156
|
+
sage: Q = (1/2)*polytopes.cube(backend='field')
|
|
157
|
+
sage: for p in P.inequalities():
|
|
158
|
+
....: assert p in Q.inequalities()
|
|
159
|
+
"""
|
|
160
|
+
if not isinstance(other, PolyhedronRepresentation):
|
|
161
|
+
return NotImplemented
|
|
162
|
+
return richcmp((self.type(), self._vector*self._comparison_scalar()),
|
|
163
|
+
(other.type(), other._vector*other._comparison_scalar()), op)
|
|
164
|
+
|
|
165
|
+
def _comparison_scalar(self):
|
|
166
|
+
r"""
|
|
167
|
+
Return a number ``a`` such that ``a*self._vector`` is canonical.
|
|
168
|
+
|
|
169
|
+
Except for vertices, ``self._vector`` is only unique up to a positive scalar.
|
|
170
|
+
|
|
171
|
+
This is overwritten for the vertex class.
|
|
172
|
+
|
|
173
|
+
EXAMPLES::
|
|
174
|
+
|
|
175
|
+
sage: P = Polyhedron(vertices=[[0,0],[1,5]], rays=[[3,4]])
|
|
176
|
+
sage: P.Vrepresentation()
|
|
177
|
+
(A vertex at (0, 0), A vertex at (1, 5), A ray in the direction (3, 4))
|
|
178
|
+
sage: P.Vrepresentation()[0]._comparison_scalar()
|
|
179
|
+
1
|
|
180
|
+
sage: P.Vrepresentation()[1]._comparison_scalar()
|
|
181
|
+
1
|
|
182
|
+
sage: P.Vrepresentation()[2]._comparison_scalar()
|
|
183
|
+
1/4
|
|
184
|
+
sage: P.Hrepresentation()
|
|
185
|
+
(An inequality (5, -1) x + 0 >= 0,
|
|
186
|
+
An inequality (-4, 3) x + 0 >= 0,
|
|
187
|
+
An inequality (4, -3) x + 11 >= 0)
|
|
188
|
+
sage: P.Hrepresentation()[0]._comparison_scalar()
|
|
189
|
+
1
|
|
190
|
+
sage: P.Hrepresentation()[1]._comparison_scalar()
|
|
191
|
+
1/3
|
|
192
|
+
sage: P.Hrepresentation()[2]._comparison_scalar()
|
|
193
|
+
1/3
|
|
194
|
+
|
|
195
|
+
::
|
|
196
|
+
|
|
197
|
+
sage: P = Polyhedron(vertices=[[1,3]], lines=[[-1,3]])
|
|
198
|
+
sage: P.Vrepresentation()
|
|
199
|
+
(A line in the direction (1, -3), A vertex at (2, 0))
|
|
200
|
+
sage: P.Vrepresentation()[0]._comparison_scalar()
|
|
201
|
+
-1/3
|
|
202
|
+
sage: P.Vrepresentation()[1]._comparison_scalar()
|
|
203
|
+
1
|
|
204
|
+
"""
|
|
205
|
+
if self.type() == self.VERTEX:
|
|
206
|
+
return 1
|
|
207
|
+
|
|
208
|
+
lcf = self._vector.leading_coefficient()
|
|
209
|
+
if self.type() == self.EQUATION or self.type() == self.LINE:
|
|
210
|
+
return 1/lcf
|
|
211
|
+
else:
|
|
212
|
+
return 1/lcf.abs()
|
|
213
|
+
|
|
214
|
+
def vector(self, base_ring=None):
|
|
215
|
+
"""
|
|
216
|
+
Return the vector representation of the H/V-representation object.
|
|
217
|
+
|
|
218
|
+
INPUT:
|
|
219
|
+
|
|
220
|
+
- ``base_ring`` -- the base ring of the vector
|
|
221
|
+
|
|
222
|
+
OUTPUT:
|
|
223
|
+
|
|
224
|
+
For a V-representation object, a vector of length
|
|
225
|
+
:meth:`~sage.geometry.polyhedron.base.Polyhedron_base.ambient_dim`. For
|
|
226
|
+
a H-representation object, a vector of length
|
|
227
|
+
:meth:`~sage.geometry.polyhedron.base.Polyhedron_base.ambient_dim`
|
|
228
|
+
+ 1.
|
|
229
|
+
|
|
230
|
+
EXAMPLES::
|
|
231
|
+
|
|
232
|
+
sage: s = polytopes.cuboctahedron()
|
|
233
|
+
sage: v = next(s.vertex_generator())
|
|
234
|
+
sage: v
|
|
235
|
+
A vertex at (-1, -1, 0)
|
|
236
|
+
sage: v.vector()
|
|
237
|
+
(-1, -1, 0)
|
|
238
|
+
sage: v()
|
|
239
|
+
(-1, -1, 0)
|
|
240
|
+
sage: type(v())
|
|
241
|
+
<class 'sage.modules.vector_integer_dense.Vector_integer_dense'>
|
|
242
|
+
|
|
243
|
+
Conversion to a different base ring can be forced with the optional argument::
|
|
244
|
+
|
|
245
|
+
sage: v.vector(RDF)
|
|
246
|
+
(-1.0, -1.0, 0.0)
|
|
247
|
+
sage: vector(RDF, v)
|
|
248
|
+
(-1.0, -1.0, 0.0)
|
|
249
|
+
|
|
250
|
+
TESTS:
|
|
251
|
+
|
|
252
|
+
Checks that :issue:`27709` is fixed::
|
|
253
|
+
|
|
254
|
+
sage: C = polytopes.cube()
|
|
255
|
+
sage: C.vertices()[0].vector()[0] = 3
|
|
256
|
+
sage: C.vertices()[0]
|
|
257
|
+
A vertex at (1, -1, -1)
|
|
258
|
+
"""
|
|
259
|
+
if (base_ring is None) or (base_ring is self._base_ring):
|
|
260
|
+
return copy(self._vector)
|
|
261
|
+
else:
|
|
262
|
+
return vector(base_ring, self._vector)
|
|
263
|
+
|
|
264
|
+
_vector_ = vector
|
|
265
|
+
|
|
266
|
+
def polyhedron(self):
|
|
267
|
+
"""
|
|
268
|
+
Return the underlying polyhedron.
|
|
269
|
+
|
|
270
|
+
TESTS::
|
|
271
|
+
|
|
272
|
+
sage: p = Polyhedron(vertices=[[1,2,3]])
|
|
273
|
+
sage: v = p.Vrepresentation(0)
|
|
274
|
+
sage: v.polyhedron()
|
|
275
|
+
A 0-dimensional polyhedron in ZZ^3 defined as the convex hull of 1 vertex
|
|
276
|
+
"""
|
|
277
|
+
return self._polyhedron
|
|
278
|
+
|
|
279
|
+
def __call__(self):
|
|
280
|
+
"""
|
|
281
|
+
Return the vector representation of the representation
|
|
282
|
+
object. Shorthand for the vector() method.
|
|
283
|
+
|
|
284
|
+
TESTS::
|
|
285
|
+
|
|
286
|
+
sage: p = Polyhedron(vertices=[[1,2,3]])
|
|
287
|
+
sage: v = p.Vrepresentation(0)
|
|
288
|
+
sage: v.__call__()
|
|
289
|
+
(1, 2, 3)
|
|
290
|
+
"""
|
|
291
|
+
return copy(self._vector)
|
|
292
|
+
|
|
293
|
+
def index(self):
|
|
294
|
+
"""
|
|
295
|
+
Return an arbitrary but fixed number according to the internal
|
|
296
|
+
storage order.
|
|
297
|
+
|
|
298
|
+
.. NOTE::
|
|
299
|
+
|
|
300
|
+
H-representation and V-representation objects are enumerated
|
|
301
|
+
independently. That is, amongst all vertices/rays/lines there
|
|
302
|
+
will be one with ``index()==0``, and amongst all
|
|
303
|
+
inequalities/equations there will be one with ``index()==0``,
|
|
304
|
+
unless the polyhedron is empty or spans the whole space.
|
|
305
|
+
|
|
306
|
+
EXAMPLES::
|
|
307
|
+
|
|
308
|
+
sage: s = Polyhedron(vertices=[[1],[-1]])
|
|
309
|
+
sage: first_vertex = next(s.vertex_generator())
|
|
310
|
+
sage: first_vertex.index()
|
|
311
|
+
0
|
|
312
|
+
sage: first_vertex == s.Vrepresentation(0)
|
|
313
|
+
True
|
|
314
|
+
"""
|
|
315
|
+
return self._index
|
|
316
|
+
|
|
317
|
+
def __add__(self, coordinate_list):
|
|
318
|
+
"""
|
|
319
|
+
Return the coordinates concatenated with ``coordinate_list``.
|
|
320
|
+
|
|
321
|
+
INPUT:
|
|
322
|
+
|
|
323
|
+
- ``coordinate_list`` -- list
|
|
324
|
+
|
|
325
|
+
OUTPUT: the coordinates of ``self`` concatenated with ``coordinate_list``
|
|
326
|
+
|
|
327
|
+
EXAMPLES::
|
|
328
|
+
|
|
329
|
+
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
|
|
330
|
+
sage: v = p.Vrepresentation(0); v
|
|
331
|
+
A vertex at (1, 0)
|
|
332
|
+
sage: v + [4,5]
|
|
333
|
+
[1, 0, 4, 5]
|
|
334
|
+
"""
|
|
335
|
+
if not isinstance(coordinate_list, list):
|
|
336
|
+
raise TypeError('Can only concatenate with a list of coordinates')
|
|
337
|
+
return list(self) + coordinate_list
|
|
338
|
+
|
|
339
|
+
def __radd__(self, coordinate_list):
|
|
340
|
+
"""
|
|
341
|
+
Return ``coordinate_list`` concatenated with the coordinates.
|
|
342
|
+
|
|
343
|
+
INPUT:
|
|
344
|
+
|
|
345
|
+
- ``coordinate_list`` -- list
|
|
346
|
+
|
|
347
|
+
OUTPUT: ``coordinate_list`` concatenated with the coordinates of ``self``
|
|
348
|
+
|
|
349
|
+
EXAMPLES::
|
|
350
|
+
|
|
351
|
+
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
|
|
352
|
+
sage: v = p.Vrepresentation(0); v
|
|
353
|
+
A vertex at (1, 0)
|
|
354
|
+
sage: [4,5] + v
|
|
355
|
+
[4, 5, 1, 0]
|
|
356
|
+
"""
|
|
357
|
+
if not isinstance(coordinate_list, list):
|
|
358
|
+
raise TypeError('Can only concatenate with a list of coordinates')
|
|
359
|
+
return coordinate_list + list(self)
|
|
360
|
+
|
|
361
|
+
def count(self, i):
|
|
362
|
+
"""
|
|
363
|
+
Count the number of occurrences of ``i`` in the coordinates.
|
|
364
|
+
|
|
365
|
+
INPUT:
|
|
366
|
+
|
|
367
|
+
- ``i`` -- anything
|
|
368
|
+
|
|
369
|
+
OUTPUT: integer; the number of occurrences of ``i`` in the coordinates
|
|
370
|
+
|
|
371
|
+
EXAMPLES::
|
|
372
|
+
|
|
373
|
+
sage: p = Polyhedron(vertices=[(0,1,1,2,1)])
|
|
374
|
+
sage: v = p.Vrepresentation(0); v
|
|
375
|
+
A vertex at (0, 1, 1, 2, 1)
|
|
376
|
+
sage: v.count(1)
|
|
377
|
+
3
|
|
378
|
+
"""
|
|
379
|
+
return sum([1 for j in self if i == j])
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
class Hrepresentation(PolyhedronRepresentation):
|
|
383
|
+
"""
|
|
384
|
+
The internal base class for H-representation objects of
|
|
385
|
+
a polyhedron. Inherits from ``PolyhedronRepresentation``.
|
|
386
|
+
"""
|
|
387
|
+
|
|
388
|
+
def __init__(self, polyhedron_parent):
|
|
389
|
+
"""
|
|
390
|
+
Initialize the PolyhedronRepresentation object.
|
|
391
|
+
|
|
392
|
+
TESTS::
|
|
393
|
+
|
|
394
|
+
sage: from sage.geometry.polyhedron.representation import Hrepresentation
|
|
395
|
+
sage: pr = Hrepresentation(Polyhedron(vertices = [[1,2,3]]).parent())
|
|
396
|
+
sage: tuple(pr)
|
|
397
|
+
(0, 0, 0, 0)
|
|
398
|
+
sage: TestSuite(pr).run(skip='_test_pickling')
|
|
399
|
+
"""
|
|
400
|
+
self._polyhedron_parent = polyhedron_parent
|
|
401
|
+
self._base_ring = polyhedron_parent.base_ring()
|
|
402
|
+
self._vector = polyhedron_parent.Hrepresentation_space()(0)
|
|
403
|
+
self._A = polyhedron_parent.ambient_space()(0)
|
|
404
|
+
self._b = polyhedron_parent.base_ring()(0)
|
|
405
|
+
self._index = 0
|
|
406
|
+
|
|
407
|
+
def _set_data(self, polyhedron, data):
|
|
408
|
+
"""
|
|
409
|
+
Initialization function.
|
|
410
|
+
|
|
411
|
+
The H/V-representation objects are kept in a pool, and this
|
|
412
|
+
function is used to reassign new values to already existing
|
|
413
|
+
(but unused) objects. You must not call this function on
|
|
414
|
+
objects that are in normal use.
|
|
415
|
+
|
|
416
|
+
INPUT:
|
|
417
|
+
|
|
418
|
+
- ``polyhedron`` -- the new polyhedron
|
|
419
|
+
|
|
420
|
+
- ``data`` -- the H-representation data
|
|
421
|
+
|
|
422
|
+
TESTS::
|
|
423
|
+
|
|
424
|
+
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
|
|
425
|
+
sage: pH = p.Hrepresentation(0) # indirect doctest
|
|
426
|
+
sage: TestSuite(pH).run(skip='_test_pickling')
|
|
427
|
+
"""
|
|
428
|
+
assert polyhedron.parent() is self._polyhedron_parent
|
|
429
|
+
if len(data) != self._vector.degree():
|
|
430
|
+
raise ValueError('H-representation data requires a list of length ambient_dim+1')
|
|
431
|
+
|
|
432
|
+
self._vector[:] = data
|
|
433
|
+
self._A[:] = data[1:]
|
|
434
|
+
self._b = self._base_ring(data[0])
|
|
435
|
+
|
|
436
|
+
self._index = len(polyhedron._Hrepresentation)
|
|
437
|
+
polyhedron._Hrepresentation.append(self)
|
|
438
|
+
self._polyhedron = polyhedron
|
|
439
|
+
if polyhedron.is_mutable():
|
|
440
|
+
polyhedron._add_dependent_object(self)
|
|
441
|
+
|
|
442
|
+
def is_H(self):
|
|
443
|
+
"""
|
|
444
|
+
Return ``True`` if the object is part of a H-representation
|
|
445
|
+
(inequality or equation).
|
|
446
|
+
|
|
447
|
+
EXAMPLES::
|
|
448
|
+
|
|
449
|
+
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
|
|
450
|
+
sage: pH = p.Hrepresentation(0)
|
|
451
|
+
sage: pH.is_H()
|
|
452
|
+
True
|
|
453
|
+
"""
|
|
454
|
+
return True
|
|
455
|
+
|
|
456
|
+
def is_inequality(self):
|
|
457
|
+
"""
|
|
458
|
+
Return ``True`` if the object is an inequality of the H-representation.
|
|
459
|
+
|
|
460
|
+
EXAMPLES::
|
|
461
|
+
|
|
462
|
+
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
|
|
463
|
+
sage: pH = p.Hrepresentation(0)
|
|
464
|
+
sage: pH.is_inequality()
|
|
465
|
+
True
|
|
466
|
+
"""
|
|
467
|
+
return False
|
|
468
|
+
|
|
469
|
+
def is_equation(self):
|
|
470
|
+
"""
|
|
471
|
+
Return ``True`` if the object is an equation of the H-representation.
|
|
472
|
+
|
|
473
|
+
EXAMPLES::
|
|
474
|
+
|
|
475
|
+
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]], eqns = [[1,1,-1]])
|
|
476
|
+
sage: pH = p.Hrepresentation(0)
|
|
477
|
+
sage: pH.is_equation()
|
|
478
|
+
True
|
|
479
|
+
"""
|
|
480
|
+
return False
|
|
481
|
+
|
|
482
|
+
def A(self):
|
|
483
|
+
r"""
|
|
484
|
+
Return the coefficient vector `A` in `A\vec{x}+b`.
|
|
485
|
+
|
|
486
|
+
EXAMPLES::
|
|
487
|
+
|
|
488
|
+
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
|
|
489
|
+
sage: pH = p.Hrepresentation(2)
|
|
490
|
+
sage: pH.A()
|
|
491
|
+
(1, 0)
|
|
492
|
+
|
|
493
|
+
TESTS:
|
|
494
|
+
|
|
495
|
+
Checks that :issue:`27709` is fixed::
|
|
496
|
+
|
|
497
|
+
sage: C = polytopes.cube()
|
|
498
|
+
sage: C.inequalities()[0].A()[2] = 5
|
|
499
|
+
sage: C.inequalities()[0]
|
|
500
|
+
An inequality (-1, 0, 0) x + 1 >= 0
|
|
501
|
+
"""
|
|
502
|
+
return copy(self._A)
|
|
503
|
+
|
|
504
|
+
def b(self):
|
|
505
|
+
r"""
|
|
506
|
+
Return the constant `b` in `A\vec{x}+b`.
|
|
507
|
+
|
|
508
|
+
EXAMPLES::
|
|
509
|
+
|
|
510
|
+
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
|
|
511
|
+
sage: pH = p.Hrepresentation(2)
|
|
512
|
+
sage: pH.b()
|
|
513
|
+
0
|
|
514
|
+
"""
|
|
515
|
+
return self._b
|
|
516
|
+
|
|
517
|
+
def neighbors(self):
|
|
518
|
+
"""
|
|
519
|
+
Iterate over the adjacent facets (i.e. inequalities).
|
|
520
|
+
|
|
521
|
+
Only defined for inequalities.
|
|
522
|
+
|
|
523
|
+
EXAMPLES::
|
|
524
|
+
|
|
525
|
+
sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0,],[0,1,0,0],
|
|
526
|
+
....: [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])
|
|
527
|
+
sage: pH = p.Hrepresentation(0)
|
|
528
|
+
sage: a = list(pH.neighbors())
|
|
529
|
+
sage: a[0]
|
|
530
|
+
An inequality (0, -1, 0) x + 1 >= 0
|
|
531
|
+
sage: list(a[0])
|
|
532
|
+
[1, 0, -1, 0]
|
|
533
|
+
|
|
534
|
+
TESTS:
|
|
535
|
+
|
|
536
|
+
Checking that :issue:`28463` is fixed::
|
|
537
|
+
|
|
538
|
+
sage: P = polytopes.simplex()
|
|
539
|
+
sage: F1 = P.Hrepresentation()[1]
|
|
540
|
+
sage: list(F1.neighbors())
|
|
541
|
+
[An inequality (0, 1, 0, 0) x + 0 >= 0,
|
|
542
|
+
An inequality (0, 0, 1, 0) x + 0 >= 0,
|
|
543
|
+
An inequality (0, 0, 0, 1) x + 0 >= 0]
|
|
544
|
+
|
|
545
|
+
Does not work for equalities::
|
|
546
|
+
|
|
547
|
+
sage: F0 = P.Hrepresentation()[0]
|
|
548
|
+
sage: list(F0.neighbors())
|
|
549
|
+
Traceback (most recent call last):
|
|
550
|
+
...
|
|
551
|
+
TypeError: must be inequality
|
|
552
|
+
"""
|
|
553
|
+
# The adjacency matrix does not include equations.
|
|
554
|
+
n_eqs = self.polyhedron().n_equations()
|
|
555
|
+
if not self.is_inequality():
|
|
556
|
+
raise TypeError("must be inequality")
|
|
557
|
+
|
|
558
|
+
adjacency_matrix = self.polyhedron().facet_adjacency_matrix()
|
|
559
|
+
for x in self.polyhedron().Hrep_generator():
|
|
560
|
+
if not x.is_equation():
|
|
561
|
+
if adjacency_matrix[self.index()-n_eqs, x.index()-n_eqs] == 1:
|
|
562
|
+
yield x
|
|
563
|
+
|
|
564
|
+
def adjacent(self):
|
|
565
|
+
"""
|
|
566
|
+
Alias for neighbors().
|
|
567
|
+
|
|
568
|
+
TESTS::
|
|
569
|
+
|
|
570
|
+
sage: p = Polyhedron(ieqs = [[0,0,0,2],[0,0,1,0,],[0,10,0,0],
|
|
571
|
+
....: [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])
|
|
572
|
+
sage: pH = p.Hrepresentation(0)
|
|
573
|
+
sage: a = list(pH.neighbors())
|
|
574
|
+
sage: b = list(pH.adjacent())
|
|
575
|
+
sage: a==b
|
|
576
|
+
True
|
|
577
|
+
"""
|
|
578
|
+
return self.neighbors()
|
|
579
|
+
|
|
580
|
+
def is_incident(self, Vobj):
|
|
581
|
+
"""
|
|
582
|
+
Return whether the incidence matrix element (Vobj,self) == 1.
|
|
583
|
+
|
|
584
|
+
EXAMPLES::
|
|
585
|
+
|
|
586
|
+
sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0,],[0,1,0,0],
|
|
587
|
+
....: [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])
|
|
588
|
+
sage: pH = p.Hrepresentation(0)
|
|
589
|
+
sage: pH.is_incident(p.Vrepresentation(1))
|
|
590
|
+
True
|
|
591
|
+
sage: pH.is_incident(p.Vrepresentation(5))
|
|
592
|
+
False
|
|
593
|
+
"""
|
|
594
|
+
return self.polyhedron().incidence_matrix()[Vobj.index(), self.index()] == 1
|
|
595
|
+
|
|
596
|
+
def __mul__(self, Vobj):
|
|
597
|
+
"""
|
|
598
|
+
Shorthand for ``self.eval(x)``.
|
|
599
|
+
|
|
600
|
+
EXAMPLES::
|
|
601
|
+
|
|
602
|
+
sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0,],[0,1,0,0],
|
|
603
|
+
....: [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])
|
|
604
|
+
sage: pH = p.Hrepresentation(0)
|
|
605
|
+
sage: pH*p.Vrepresentation(5)
|
|
606
|
+
1
|
|
607
|
+
"""
|
|
608
|
+
return self.eval(Vobj)
|
|
609
|
+
|
|
610
|
+
def eval(self, Vobj):
|
|
611
|
+
r"""
|
|
612
|
+
Evaluate the left hand side `A\vec{x}+b` on the given
|
|
613
|
+
vertex/ray/line.
|
|
614
|
+
|
|
615
|
+
.. NOTE::
|
|
616
|
+
|
|
617
|
+
* Evaluating on a vertex returns `A\vec{x}+b`
|
|
618
|
+
|
|
619
|
+
* Evaluating on a ray returns `A\vec{r}`. Only the sign or
|
|
620
|
+
whether it is zero is meaningful.
|
|
621
|
+
|
|
622
|
+
* Evaluating on a line returns `A\vec{l}`. Only whether it
|
|
623
|
+
is zero or not is meaningful.
|
|
624
|
+
|
|
625
|
+
EXAMPLES::
|
|
626
|
+
|
|
627
|
+
sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]])
|
|
628
|
+
sage: ineq = next(triangle.inequality_generator())
|
|
629
|
+
sage: ineq
|
|
630
|
+
An inequality (2, -1) x + 1 >= 0
|
|
631
|
+
sage: [ ineq.eval(v) for v in triangle.vertex_generator() ]
|
|
632
|
+
[0, 0, 3]
|
|
633
|
+
sage: [ ineq * v for v in triangle.vertex_generator() ]
|
|
634
|
+
[0, 0, 3]
|
|
635
|
+
|
|
636
|
+
If you pass a vector, it is assumed to be the coordinate vector of a point::
|
|
637
|
+
|
|
638
|
+
sage: ineq.eval( vector(ZZ, [3,2]) )
|
|
639
|
+
5
|
|
640
|
+
"""
|
|
641
|
+
if isinstance(Vobj, Vector):
|
|
642
|
+
return self.A() * Vobj + self.b()
|
|
643
|
+
return Vobj.evaluated_on(self)
|
|
644
|
+
|
|
645
|
+
def incident(self):
|
|
646
|
+
"""
|
|
647
|
+
Return a generator for the incident H-representation objects,
|
|
648
|
+
that is, the vertices/rays/lines satisfying the (in)equality.
|
|
649
|
+
|
|
650
|
+
EXAMPLES::
|
|
651
|
+
|
|
652
|
+
sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]])
|
|
653
|
+
sage: ineq = next(triangle.inequality_generator())
|
|
654
|
+
sage: ineq
|
|
655
|
+
An inequality (2, -1) x + 1 >= 0
|
|
656
|
+
sage: [ v for v in ineq.incident()]
|
|
657
|
+
[A vertex at (-1, -1), A vertex at (0, 1)]
|
|
658
|
+
sage: p = Polyhedron(vertices=[[0,0,0],[0,1,0],[0,0,1]], rays=[[1,-1,-1]])
|
|
659
|
+
sage: ineq = p.Hrepresentation(2)
|
|
660
|
+
sage: ineq
|
|
661
|
+
An inequality (1, 0, 1) x + 0 >= 0
|
|
662
|
+
sage: [ x for x in ineq.incident() ]
|
|
663
|
+
[A vertex at (0, 0, 0),
|
|
664
|
+
A vertex at (0, 1, 0),
|
|
665
|
+
A ray in the direction (1, -1, -1)]
|
|
666
|
+
"""
|
|
667
|
+
incidence_matrix = self.polyhedron().incidence_matrix()
|
|
668
|
+
for V in self.polyhedron().Vrep_generator():
|
|
669
|
+
if incidence_matrix[V.index(), self.index()] == 1:
|
|
670
|
+
yield V
|
|
671
|
+
|
|
672
|
+
def repr_pretty(self, **kwds):
|
|
673
|
+
r"""
|
|
674
|
+
Return a pretty representation of this equality/inequality.
|
|
675
|
+
|
|
676
|
+
INPUT:
|
|
677
|
+
|
|
678
|
+
- ``prefix`` -- string
|
|
679
|
+
|
|
680
|
+
- ``indices`` -- tuple or other iterable
|
|
681
|
+
|
|
682
|
+
- ``latex`` -- boolean
|
|
683
|
+
|
|
684
|
+
OUTPUT: string
|
|
685
|
+
|
|
686
|
+
EXAMPLES::
|
|
687
|
+
|
|
688
|
+
sage: P = Polyhedron(ieqs=[(0, 1, 0, 0), (1, 2, 1, 0)],
|
|
689
|
+
....: eqns=[(1, -1, -1, 1)])
|
|
690
|
+
sage: for h in P.Hrepresentation():
|
|
691
|
+
....: print(h.repr_pretty())
|
|
692
|
+
x0 + x1 - x2 == 1
|
|
693
|
+
x0 >= 0
|
|
694
|
+
2*x0 + x1 >= -1
|
|
695
|
+
"""
|
|
696
|
+
return repr_pretty(self.vector(), self.type(), **kwds)
|
|
697
|
+
|
|
698
|
+
def _latex_(self):
|
|
699
|
+
r"""
|
|
700
|
+
Return a LaTeX-representation of this equality/inequality.
|
|
701
|
+
|
|
702
|
+
OUTPUT: string
|
|
703
|
+
|
|
704
|
+
EXAMPLES::
|
|
705
|
+
|
|
706
|
+
sage: P = Polyhedron(ieqs=[(0, 1, 0, 0), (1, 2, 1, 0)],
|
|
707
|
+
....: eqns=[(1, -1, -1, 1)])
|
|
708
|
+
sage: for h in P.Hrepresentation():
|
|
709
|
+
....: print(latex(h))
|
|
710
|
+
x_{0} + x_{1} - x_{2} = 1
|
|
711
|
+
x_{0} \geq 0
|
|
712
|
+
2 x_{0} + x_{1} \geq -1
|
|
713
|
+
"""
|
|
714
|
+
return self.repr_pretty(latex=True)
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
class Inequality(Hrepresentation):
|
|
718
|
+
"""
|
|
719
|
+
A linear inequality (supporting hyperplane) of the
|
|
720
|
+
polyhedron. Inherits from ``Hrepresentation``.
|
|
721
|
+
"""
|
|
722
|
+
|
|
723
|
+
def type(self):
|
|
724
|
+
r"""
|
|
725
|
+
Return the type (equation/inequality/vertex/ray/line) as an
|
|
726
|
+
integer.
|
|
727
|
+
|
|
728
|
+
OUTPUT:
|
|
729
|
+
|
|
730
|
+
Integer. One of ``PolyhedronRepresentation.INEQUALITY``,
|
|
731
|
+
``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.
|
|
732
|
+
|
|
733
|
+
EXAMPLES::
|
|
734
|
+
|
|
735
|
+
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
|
|
736
|
+
sage: repr_obj = next(p.inequality_generator())
|
|
737
|
+
sage: repr_obj.type()
|
|
738
|
+
0
|
|
739
|
+
sage: repr_obj.type() == repr_obj.INEQUALITY
|
|
740
|
+
True
|
|
741
|
+
sage: repr_obj.type() == repr_obj.EQUATION
|
|
742
|
+
False
|
|
743
|
+
sage: repr_obj.type() == repr_obj.VERTEX
|
|
744
|
+
False
|
|
745
|
+
sage: repr_obj.type() == repr_obj.RAY
|
|
746
|
+
False
|
|
747
|
+
sage: repr_obj.type() == repr_obj.LINE
|
|
748
|
+
False
|
|
749
|
+
"""
|
|
750
|
+
return self.INEQUALITY
|
|
751
|
+
|
|
752
|
+
def is_inequality(self):
|
|
753
|
+
"""
|
|
754
|
+
Return ``True`` since this is, by construction, an inequality.
|
|
755
|
+
|
|
756
|
+
EXAMPLES::
|
|
757
|
+
|
|
758
|
+
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
|
|
759
|
+
sage: a = next(p.inequality_generator())
|
|
760
|
+
sage: a.is_inequality()
|
|
761
|
+
True
|
|
762
|
+
"""
|
|
763
|
+
return True
|
|
764
|
+
|
|
765
|
+
def is_facet_defining_inequality(self, other):
|
|
766
|
+
r"""
|
|
767
|
+
Check if ``self`` defines a facet of ``other``.
|
|
768
|
+
|
|
769
|
+
INPUT:
|
|
770
|
+
|
|
771
|
+
- ``other`` -- a polyhedron
|
|
772
|
+
|
|
773
|
+
.. SEEALSO::
|
|
774
|
+
|
|
775
|
+
:meth:`~sage.geometry.polyhedron.base.Polyhedron_base.slack_matrix`
|
|
776
|
+
:meth:`~sage.geometry.polyhedron.base.Polyhedron_base.incidence_matrix`
|
|
777
|
+
|
|
778
|
+
EXAMPLES::
|
|
779
|
+
|
|
780
|
+
sage: P = Polyhedron(vertices=[[0,0,0],[0,1,0]], rays=[[1,0,0]])
|
|
781
|
+
sage: P.inequalities()
|
|
782
|
+
(An inequality (1, 0, 0) x + 0 >= 0,
|
|
783
|
+
An inequality (0, 1, 0) x + 0 >= 0,
|
|
784
|
+
An inequality (0, -1, 0) x + 1 >= 0)
|
|
785
|
+
sage: Q = Polyhedron(ieqs=[[0,1,0,0]])
|
|
786
|
+
sage: Q.inequalities()[0].is_facet_defining_inequality(P)
|
|
787
|
+
True
|
|
788
|
+
sage: Q = Polyhedron(ieqs=[[0,2,0,3]])
|
|
789
|
+
sage: Q.inequalities()[0].is_facet_defining_inequality(P)
|
|
790
|
+
True
|
|
791
|
+
sage: Q = Polyhedron(ieqs=[[0,AA(2).sqrt(),0,3]]) # needs sage.rings.number_field
|
|
792
|
+
sage: Q.inequalities()[0].is_facet_defining_inequality(P)
|
|
793
|
+
True
|
|
794
|
+
sage: Q = Polyhedron(ieqs=[[1,1,0,0]])
|
|
795
|
+
sage: Q.inequalities()[0].is_facet_defining_inequality(P)
|
|
796
|
+
False
|
|
797
|
+
|
|
798
|
+
::
|
|
799
|
+
|
|
800
|
+
sage: P = Polyhedron(vertices=[[0,0,0],[0,1,0]], lines=[[1,0,0]])
|
|
801
|
+
sage: P.inequalities()
|
|
802
|
+
(An inequality (0, 1, 0) x + 0 >= 0, An inequality (0, -1, 0) x + 1 >= 0)
|
|
803
|
+
sage: Q = Polyhedron(ieqs=[[0,1,0,0]])
|
|
804
|
+
sage: Q.inequalities()[0].is_facet_defining_inequality(P)
|
|
805
|
+
False
|
|
806
|
+
sage: Q = Polyhedron(ieqs=[[0,-1,0,0]])
|
|
807
|
+
sage: Q.inequalities()[0].is_facet_defining_inequality(P)
|
|
808
|
+
False
|
|
809
|
+
sage: Q = Polyhedron(ieqs=[[0,0,1,3]])
|
|
810
|
+
sage: Q.inequalities()[0].is_facet_defining_inequality(P)
|
|
811
|
+
True
|
|
812
|
+
|
|
813
|
+
TESTS::
|
|
814
|
+
|
|
815
|
+
sage: p1 = Polyhedron(backend='normaliz', base_ring=QQ, vertices=[ # optional - pynormaliz
|
|
816
|
+
....: (2/3, 2/3, 2/3, 2/3, 2/3, 2/3, 2/3, 2/3, 2/3),
|
|
817
|
+
....: (1, 1, 1, 9/10, 4/5, 7/10, 3/5, 0, 0),
|
|
818
|
+
....: (1, 1, 1, 1, 4/5, 3/5, 1/2, 1/10, 0),
|
|
819
|
+
....: (1, 1, 1, 1, 9/10, 1/2, 2/5, 1/5, 0),
|
|
820
|
+
....: (1, 1, 1, 1, 1, 2/5, 3/10, 1/5, 1/10)])
|
|
821
|
+
sage: p2 = Polyhedron(backend='ppl', base_ring=QQ, vertices=[
|
|
822
|
+
....: (2/3, 2/3, 2/3, 2/3, 2/3, 2/3, 2/3, 2/3, 2/3),
|
|
823
|
+
....: (1, 1, 1, 9/10, 4/5, 7/10, 3/5, 0, 0),
|
|
824
|
+
....: (1, 1, 1, 1, 4/5, 3/5, 1/2, 1/10, 0),
|
|
825
|
+
....: (1, 1, 1, 1, 9/10, 1/2, 2/5, 1/5, 0),
|
|
826
|
+
....: (1, 1, 1, 1, 1, 2/5, 3/10, 1/5, 1/10)])
|
|
827
|
+
sage: p2 == p1 # optional - pynormaliz
|
|
828
|
+
True
|
|
829
|
+
sage: for ieq in p1.inequalities(): # optional - pynormaliz
|
|
830
|
+
....: assert ieq.is_facet_defining_inequality(p2)
|
|
831
|
+
sage: for ieq in p2.inequalities(): # optional - pynormaliz
|
|
832
|
+
....: assert ieq.is_facet_defining_inequality(p1)
|
|
833
|
+
"""
|
|
834
|
+
from sage.geometry.polyhedron.base import Polyhedron_base
|
|
835
|
+
if not isinstance(other, Polyhedron_base):
|
|
836
|
+
raise ValueError("other must be a polyhedron")
|
|
837
|
+
|
|
838
|
+
if not other.n_Vrepresentation():
|
|
839
|
+
# An empty polytope does not have facets.
|
|
840
|
+
return False
|
|
841
|
+
|
|
842
|
+
# We evaluate ``self`` on the Vrepresentation of other.
|
|
843
|
+
|
|
844
|
+
from sage.matrix.constructor import matrix
|
|
845
|
+
Vrep_matrix = matrix(other.base_ring(), other.Vrepresentation())
|
|
846
|
+
|
|
847
|
+
# Getting homogeneous coordinates of the Vrepresentation.
|
|
848
|
+
hom_helper = matrix(other.base_ring(), [1 if v.is_vertex() else 0 for v in other.Vrepresentation()])
|
|
849
|
+
hom_Vrep = hom_helper.stack(Vrep_matrix.transpose())
|
|
850
|
+
|
|
851
|
+
self_matrix = matrix(self.vector())
|
|
852
|
+
|
|
853
|
+
cross_slack_matrix = self_matrix * hom_Vrep
|
|
854
|
+
|
|
855
|
+
# First of all ``self`` should not evaluate negative on anything.
|
|
856
|
+
# If it has the same incidences as an inequality of ``other``,
|
|
857
|
+
# all ``Vrepresentatives`` lie on the same (closed) side.
|
|
858
|
+
if not any(x > 0 for x in cross_slack_matrix):
|
|
859
|
+
return False
|
|
860
|
+
|
|
861
|
+
# Also it should evaluate ``0`` on all lines.
|
|
862
|
+
if any(self.A() * line.vector() for line in other.lines()):
|
|
863
|
+
return False
|
|
864
|
+
|
|
865
|
+
incidences = cross_slack_matrix.zero_pattern_matrix(ZZ)
|
|
866
|
+
|
|
867
|
+
# See if ``self`` has the same incidences as an inequality of ``other``.
|
|
868
|
+
# If this is the case, then the above check suffices to guarantee that all
|
|
869
|
+
# entries of ``cross_slack_matrix`` are nonnegative.
|
|
870
|
+
return incidences.row(0) in other.incidence_matrix().columns()
|
|
871
|
+
|
|
872
|
+
def _repr_(self):
|
|
873
|
+
"""
|
|
874
|
+
The string representation of the inequality.
|
|
875
|
+
|
|
876
|
+
EXAMPLES::
|
|
877
|
+
|
|
878
|
+
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
|
|
879
|
+
sage: a = next(p.inequality_generator())
|
|
880
|
+
sage: a._repr_()
|
|
881
|
+
'An inequality (-1, 1, 0) x + 0 >= 0'
|
|
882
|
+
sage: Polyhedron(ieqs=[(1,-1),(-1,2)]).Hrepresentation()
|
|
883
|
+
(An inequality (-1) x + 1 >= 0, An inequality (2) x - 1 >= 0)
|
|
884
|
+
sage: Polyhedron(eqns=[(1,0)]).Hrepresentation()
|
|
885
|
+
(An equation -1 == 0,)
|
|
886
|
+
sage: Polyhedron(eqns=[(-1,0)]).Hrepresentation()
|
|
887
|
+
(An equation -1 == 0,)
|
|
888
|
+
|
|
889
|
+
TESTS:
|
|
890
|
+
|
|
891
|
+
Test that :issue:`21105` has been fixed::
|
|
892
|
+
|
|
893
|
+
sage: x = polygen(ZZ, 'x')
|
|
894
|
+
sage: K.<cbrt2> = NumberField(x^3 - 2, 'a', embedding=1.26) # needs sage.rings.number_field
|
|
895
|
+
sage: P = Polyhedron(vertices=[(1,1,cbrt2),(cbrt2,1,1)]) # needs sage.rings.number_field
|
|
896
|
+
sage: P.inequalities() # needs sage.rings.number_field
|
|
897
|
+
(An inequality (-cbrt2^2 - cbrt2 - 1, 0, 0) x + cbrt2^2 + cbrt2 + 2 >= 0,
|
|
898
|
+
An inequality (cbrt2^2 + cbrt2 + 1, 0, 0) x - cbrt2^2 + cbrt2 + 1 >= 0)
|
|
899
|
+
"""
|
|
900
|
+
s = 'An inequality '
|
|
901
|
+
have_A = not self.A().is_zero()
|
|
902
|
+
if have_A:
|
|
903
|
+
s += repr(self.A()) + ' x '
|
|
904
|
+
if self.b() >= 0:
|
|
905
|
+
if have_A:
|
|
906
|
+
s += '+'
|
|
907
|
+
else:
|
|
908
|
+
s += '-'
|
|
909
|
+
if have_A:
|
|
910
|
+
s += ' '
|
|
911
|
+
s += repr(abs(self.b())) + ' >= 0'
|
|
912
|
+
return s
|
|
913
|
+
|
|
914
|
+
def contains(self, Vobj):
|
|
915
|
+
"""
|
|
916
|
+
Test whether the halfspace (including its boundary) defined
|
|
917
|
+
by the inequality contains the given vertex/ray/line.
|
|
918
|
+
|
|
919
|
+
EXAMPLES::
|
|
920
|
+
|
|
921
|
+
sage: p = polytopes.cross_polytope(3)
|
|
922
|
+
sage: i1 = next(p.inequality_generator())
|
|
923
|
+
sage: [i1.contains(q) for q in p.vertex_generator()]
|
|
924
|
+
[True, True, True, True, True, True]
|
|
925
|
+
sage: p2 = 3*polytopes.hypercube(3)
|
|
926
|
+
sage: [i1.contains(q) for q in p2.vertex_generator()]
|
|
927
|
+
[True, True, False, True, False, True, False, False]
|
|
928
|
+
"""
|
|
929
|
+
try:
|
|
930
|
+
if Vobj.is_vector(): # assume we were passed a point
|
|
931
|
+
return self.polyhedron()._is_nonneg( self.eval(Vobj) )
|
|
932
|
+
except AttributeError:
|
|
933
|
+
pass
|
|
934
|
+
|
|
935
|
+
if Vobj.is_line():
|
|
936
|
+
return self.polyhedron()._is_zero( self.eval(Vobj) )
|
|
937
|
+
else:
|
|
938
|
+
return self.polyhedron()._is_nonneg( self.eval(Vobj) )
|
|
939
|
+
|
|
940
|
+
def interior_contains(self, Vobj):
|
|
941
|
+
"""
|
|
942
|
+
Test whether the interior of the halfspace (excluding its
|
|
943
|
+
boundary) defined by the inequality contains the given
|
|
944
|
+
vertex/ray/line.
|
|
945
|
+
|
|
946
|
+
EXAMPLES::
|
|
947
|
+
|
|
948
|
+
sage: p = polytopes.cross_polytope(3)
|
|
949
|
+
sage: i1 = next(p.inequality_generator())
|
|
950
|
+
sage: [i1.interior_contains(q) for q in p.vertex_generator()]
|
|
951
|
+
[False, True, True, False, False, True]
|
|
952
|
+
sage: p2 = 3*polytopes.hypercube(3)
|
|
953
|
+
sage: [i1.interior_contains(q) for q in p2.vertex_generator()]
|
|
954
|
+
[True, True, False, True, False, True, False, False]
|
|
955
|
+
|
|
956
|
+
If you pass a vector, it is assumed to be the coordinate vector of a point::
|
|
957
|
+
|
|
958
|
+
sage: P = Polyhedron(vertices=[[1,1],[1,-1],[-1,1],[-1,-1]])
|
|
959
|
+
sage: p = vector(ZZ, [1,0] )
|
|
960
|
+
sage: [ ieq.interior_contains(p) for ieq in P.inequality_generator() ]
|
|
961
|
+
[True, True, False, True]
|
|
962
|
+
"""
|
|
963
|
+
try:
|
|
964
|
+
if Vobj.is_vector(): # assume we were passed a point
|
|
965
|
+
return self.polyhedron()._is_positive( self.eval(Vobj) )
|
|
966
|
+
except AttributeError:
|
|
967
|
+
pass
|
|
968
|
+
|
|
969
|
+
if Vobj.is_line():
|
|
970
|
+
return self.polyhedron()._is_zero( self.eval(Vobj) )
|
|
971
|
+
elif Vobj.is_vertex():
|
|
972
|
+
return self.polyhedron()._is_positive( self.eval(Vobj) )
|
|
973
|
+
else: # Vobj.is_ray()
|
|
974
|
+
return self.polyhedron()._is_nonneg( self.eval(Vobj) )
|
|
975
|
+
|
|
976
|
+
def outer_normal(self):
|
|
977
|
+
r"""
|
|
978
|
+
Return the outer normal vector of ``self``.
|
|
979
|
+
|
|
980
|
+
OUTPUT: the normal vector directed away from the interior of the polyhedron
|
|
981
|
+
|
|
982
|
+
EXAMPLES::
|
|
983
|
+
|
|
984
|
+
sage: p = Polyhedron(vertices=[[0,0,0],[1,1,0],[1,2,0]])
|
|
985
|
+
sage: a = next(p.inequality_generator())
|
|
986
|
+
sage: a.outer_normal()
|
|
987
|
+
(1, -1, 0)
|
|
988
|
+
"""
|
|
989
|
+
return -self.A()
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
class Equation(Hrepresentation):
|
|
993
|
+
"""
|
|
994
|
+
A linear equation of the polyhedron. That is, the polyhedron is
|
|
995
|
+
strictly smaller-dimensional than the ambient space, and contained
|
|
996
|
+
in this hyperplane. Inherits from ``Hrepresentation``.
|
|
997
|
+
"""
|
|
998
|
+
|
|
999
|
+
def type(self):
|
|
1000
|
+
r"""
|
|
1001
|
+
Return the type (equation/inequality/vertex/ray/line) as an
|
|
1002
|
+
integer.
|
|
1003
|
+
|
|
1004
|
+
OUTPUT:
|
|
1005
|
+
|
|
1006
|
+
Integer. One of ``PolyhedronRepresentation.INEQUALITY``,
|
|
1007
|
+
``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.
|
|
1008
|
+
|
|
1009
|
+
EXAMPLES::
|
|
1010
|
+
|
|
1011
|
+
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
|
|
1012
|
+
sage: repr_obj = next(p.equation_generator())
|
|
1013
|
+
sage: repr_obj.type()
|
|
1014
|
+
1
|
|
1015
|
+
sage: repr_obj.type() == repr_obj.INEQUALITY
|
|
1016
|
+
False
|
|
1017
|
+
sage: repr_obj.type() == repr_obj.EQUATION
|
|
1018
|
+
True
|
|
1019
|
+
sage: repr_obj.type() == repr_obj.VERTEX
|
|
1020
|
+
False
|
|
1021
|
+
sage: repr_obj.type() == repr_obj.RAY
|
|
1022
|
+
False
|
|
1023
|
+
sage: repr_obj.type() == repr_obj.LINE
|
|
1024
|
+
False
|
|
1025
|
+
"""
|
|
1026
|
+
return self.EQUATION
|
|
1027
|
+
|
|
1028
|
+
def is_equation(self):
|
|
1029
|
+
"""
|
|
1030
|
+
Test if this object is an equation. By construction, it must be.
|
|
1031
|
+
|
|
1032
|
+
TESTS::
|
|
1033
|
+
|
|
1034
|
+
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
|
|
1035
|
+
sage: a = next(p.equation_generator())
|
|
1036
|
+
sage: a.is_equation()
|
|
1037
|
+
True
|
|
1038
|
+
"""
|
|
1039
|
+
return True
|
|
1040
|
+
|
|
1041
|
+
def _repr_(self):
|
|
1042
|
+
"""
|
|
1043
|
+
A string representation of this object.
|
|
1044
|
+
|
|
1045
|
+
TESTS::
|
|
1046
|
+
|
|
1047
|
+
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
|
|
1048
|
+
sage: a = next(p.equation_generator())
|
|
1049
|
+
sage: a._repr_()
|
|
1050
|
+
'An equation (0, 0, 1) x + 0 == 0'
|
|
1051
|
+
sage: Polyhedron().Hrepresentation(0)
|
|
1052
|
+
An equation -1 == 0
|
|
1053
|
+
"""
|
|
1054
|
+
s = 'An equation '
|
|
1055
|
+
have_A = not self.A().is_zero()
|
|
1056
|
+
if have_A:
|
|
1057
|
+
s += repr(self.A()) + ' x '
|
|
1058
|
+
if self.b() >= 0:
|
|
1059
|
+
if have_A:
|
|
1060
|
+
s += '+'
|
|
1061
|
+
else:
|
|
1062
|
+
s += '-'
|
|
1063
|
+
if have_A:
|
|
1064
|
+
s += ' '
|
|
1065
|
+
s += repr(abs(self.b())) + ' == 0'
|
|
1066
|
+
return s
|
|
1067
|
+
|
|
1068
|
+
def contains(self, Vobj):
|
|
1069
|
+
"""
|
|
1070
|
+
Test whether the hyperplane defined by the equation contains
|
|
1071
|
+
the given vertex/ray/line.
|
|
1072
|
+
|
|
1073
|
+
EXAMPLES::
|
|
1074
|
+
|
|
1075
|
+
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
|
|
1076
|
+
sage: v = next(p.vertex_generator())
|
|
1077
|
+
sage: v
|
|
1078
|
+
A vertex at (0, 0, 0)
|
|
1079
|
+
sage: a = next(p.equation_generator())
|
|
1080
|
+
sage: a
|
|
1081
|
+
An equation (0, 0, 1) x + 0 == 0
|
|
1082
|
+
sage: a.contains(v)
|
|
1083
|
+
True
|
|
1084
|
+
"""
|
|
1085
|
+
return self.polyhedron()._is_zero( self.eval(Vobj) )
|
|
1086
|
+
|
|
1087
|
+
def interior_contains(self, Vobj):
|
|
1088
|
+
"""
|
|
1089
|
+
Test whether the interior of the halfspace (excluding its
|
|
1090
|
+
boundary) defined by the inequality contains the given
|
|
1091
|
+
vertex/ray/line.
|
|
1092
|
+
|
|
1093
|
+
.. NOTE::
|
|
1094
|
+
|
|
1095
|
+
Return ``False`` for any equation.
|
|
1096
|
+
|
|
1097
|
+
EXAMPLES::
|
|
1098
|
+
|
|
1099
|
+
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
|
|
1100
|
+
sage: v = next(p.vertex_generator())
|
|
1101
|
+
sage: v
|
|
1102
|
+
A vertex at (0, 0, 0)
|
|
1103
|
+
sage: a = next(p.equation_generator())
|
|
1104
|
+
sage: a
|
|
1105
|
+
An equation (0, 0, 1) x + 0 == 0
|
|
1106
|
+
sage: a.interior_contains(v)
|
|
1107
|
+
False
|
|
1108
|
+
"""
|
|
1109
|
+
return False
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
class Vrepresentation(PolyhedronRepresentation):
|
|
1113
|
+
"""
|
|
1114
|
+
The base class for V-representation objects of a
|
|
1115
|
+
polyhedron. Inherits from ``PolyhedronRepresentation``.
|
|
1116
|
+
"""
|
|
1117
|
+
|
|
1118
|
+
def __init__(self, polyhedron_parent):
|
|
1119
|
+
"""
|
|
1120
|
+
Initialize the PolyhedronRepresentation object.
|
|
1121
|
+
|
|
1122
|
+
TESTS::
|
|
1123
|
+
|
|
1124
|
+
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
|
|
1125
|
+
sage: a = next(p.inequality_generator())
|
|
1126
|
+
sage: a
|
|
1127
|
+
An inequality (-1, 1, 0) x + 0 >= 0
|
|
1128
|
+
sage: TestSuite(a).run(skip='_test_pickling')
|
|
1129
|
+
"""
|
|
1130
|
+
self._polyhedron_parent = polyhedron_parent
|
|
1131
|
+
self._base_ring = polyhedron_parent.base_ring()
|
|
1132
|
+
self._vector = polyhedron_parent.Vrepresentation_space()(0)
|
|
1133
|
+
self._index = 0
|
|
1134
|
+
|
|
1135
|
+
def _set_data(self, polyhedron, data):
|
|
1136
|
+
"""
|
|
1137
|
+
Initialization function.
|
|
1138
|
+
|
|
1139
|
+
The H/V-representation objects are kept in a pool, and this
|
|
1140
|
+
function is used to reassign new values to already existing
|
|
1141
|
+
(but unused) objects. You must not call this function on
|
|
1142
|
+
objects that are in normal use.
|
|
1143
|
+
|
|
1144
|
+
INPUT:
|
|
1145
|
+
|
|
1146
|
+
- ``polyhedron`` -- the new polyhedron
|
|
1147
|
+
|
|
1148
|
+
- ``data`` -- the V-representation data
|
|
1149
|
+
|
|
1150
|
+
TESTS::
|
|
1151
|
+
|
|
1152
|
+
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
|
|
1153
|
+
sage: pV = p.Vrepresentation(0) # indirect doctest
|
|
1154
|
+
sage: TestSuite(pV).run(skip='_test_pickling')
|
|
1155
|
+
"""
|
|
1156
|
+
assert polyhedron.parent() is self._polyhedron_parent
|
|
1157
|
+
data = list(data)
|
|
1158
|
+
if len(data) != self._vector.degree():
|
|
1159
|
+
raise ValueError('V-representation data requires a list of length ambient_dim')
|
|
1160
|
+
|
|
1161
|
+
self._vector[:] = data
|
|
1162
|
+
|
|
1163
|
+
self._index = len(polyhedron._Vrepresentation)
|
|
1164
|
+
polyhedron._Vrepresentation.append(self)
|
|
1165
|
+
self._polyhedron = polyhedron
|
|
1166
|
+
if polyhedron.is_mutable():
|
|
1167
|
+
polyhedron._add_dependent_object(self)
|
|
1168
|
+
|
|
1169
|
+
def is_V(self):
|
|
1170
|
+
"""
|
|
1171
|
+
Return ``True`` if the object is part of a V-representation
|
|
1172
|
+
(a vertex, ray, or line).
|
|
1173
|
+
|
|
1174
|
+
EXAMPLES::
|
|
1175
|
+
|
|
1176
|
+
sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,3]])
|
|
1177
|
+
sage: v = next(p.vertex_generator())
|
|
1178
|
+
sage: v.is_V()
|
|
1179
|
+
True
|
|
1180
|
+
"""
|
|
1181
|
+
return True
|
|
1182
|
+
|
|
1183
|
+
def is_vertex(self):
|
|
1184
|
+
"""
|
|
1185
|
+
Return ``True`` if the object is a vertex of the V-representation.
|
|
1186
|
+
This method is over-ridden by the corresponding method in the
|
|
1187
|
+
derived class Vertex.
|
|
1188
|
+
|
|
1189
|
+
EXAMPLES::
|
|
1190
|
+
|
|
1191
|
+
sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,3]])
|
|
1192
|
+
sage: v = next(p.vertex_generator())
|
|
1193
|
+
sage: v.is_vertex()
|
|
1194
|
+
True
|
|
1195
|
+
sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])
|
|
1196
|
+
sage: r1 = next(p.ray_generator())
|
|
1197
|
+
sage: r1.is_vertex()
|
|
1198
|
+
False
|
|
1199
|
+
"""
|
|
1200
|
+
return False
|
|
1201
|
+
|
|
1202
|
+
def is_ray(self):
|
|
1203
|
+
"""
|
|
1204
|
+
Return ``True`` if the object is a ray of the V-representation.
|
|
1205
|
+
This method is over-ridden by the corresponding method in the
|
|
1206
|
+
derived class Ray.
|
|
1207
|
+
|
|
1208
|
+
EXAMPLES::
|
|
1209
|
+
|
|
1210
|
+
sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])
|
|
1211
|
+
sage: r1 = next(p.ray_generator())
|
|
1212
|
+
sage: r1.is_ray()
|
|
1213
|
+
True
|
|
1214
|
+
sage: v1 = next(p.vertex_generator())
|
|
1215
|
+
sage: v1
|
|
1216
|
+
A vertex at (-1, -1, 0, -1)
|
|
1217
|
+
sage: v1.is_ray()
|
|
1218
|
+
False
|
|
1219
|
+
"""
|
|
1220
|
+
return False
|
|
1221
|
+
|
|
1222
|
+
def is_line(self):
|
|
1223
|
+
"""
|
|
1224
|
+
Return ``True`` if the object is a line of the V-representation.
|
|
1225
|
+
This method is over-ridden by the corresponding method in the
|
|
1226
|
+
derived class Line.
|
|
1227
|
+
|
|
1228
|
+
EXAMPLES::
|
|
1229
|
+
|
|
1230
|
+
sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])
|
|
1231
|
+
sage: line1 = next(p.line_generator())
|
|
1232
|
+
sage: line1.is_line()
|
|
1233
|
+
True
|
|
1234
|
+
sage: v1 = next(p.vertex_generator())
|
|
1235
|
+
sage: v1.is_line()
|
|
1236
|
+
False
|
|
1237
|
+
"""
|
|
1238
|
+
return False
|
|
1239
|
+
|
|
1240
|
+
def neighbors(self):
|
|
1241
|
+
"""
|
|
1242
|
+
Return a generator for the adjacent vertices/rays/lines.
|
|
1243
|
+
|
|
1244
|
+
EXAMPLES::
|
|
1245
|
+
|
|
1246
|
+
sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,4]])
|
|
1247
|
+
sage: v = next(p.vertex_generator())
|
|
1248
|
+
sage: next(v.neighbors())
|
|
1249
|
+
A vertex at (0, 3)
|
|
1250
|
+
"""
|
|
1251
|
+
adjacency_matrix = self.polyhedron().vertex_adjacency_matrix()
|
|
1252
|
+
for x in self.polyhedron().Vrep_generator():
|
|
1253
|
+
if adjacency_matrix[self.index(), x.index()] == 1:
|
|
1254
|
+
yield x
|
|
1255
|
+
|
|
1256
|
+
def adjacent(self):
|
|
1257
|
+
"""
|
|
1258
|
+
Alias for neighbors().
|
|
1259
|
+
|
|
1260
|
+
TESTS::
|
|
1261
|
+
|
|
1262
|
+
sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,4]])
|
|
1263
|
+
sage: v = next(p.vertex_generator())
|
|
1264
|
+
sage: a = next(v.neighbors())
|
|
1265
|
+
sage: b = next(v.adjacent())
|
|
1266
|
+
sage: a==b
|
|
1267
|
+
True
|
|
1268
|
+
"""
|
|
1269
|
+
return self.neighbors()
|
|
1270
|
+
|
|
1271
|
+
def is_incident(self, Hobj):
|
|
1272
|
+
"""
|
|
1273
|
+
Return whether the incidence matrix element (self,Hobj) == 1.
|
|
1274
|
+
|
|
1275
|
+
EXAMPLES::
|
|
1276
|
+
|
|
1277
|
+
sage: p = polytopes.hypercube(3)
|
|
1278
|
+
sage: h1 = next(p.inequality_generator())
|
|
1279
|
+
sage: h1
|
|
1280
|
+
An inequality (-1, 0, 0) x + 1 >= 0
|
|
1281
|
+
sage: v1 = next(p.vertex_generator())
|
|
1282
|
+
sage: v1
|
|
1283
|
+
A vertex at (1, -1, -1)
|
|
1284
|
+
sage: v1.is_incident(h1)
|
|
1285
|
+
True
|
|
1286
|
+
"""
|
|
1287
|
+
return self.polyhedron().incidence_matrix()[self.index(), Hobj.index()] == 1
|
|
1288
|
+
|
|
1289
|
+
def __mul__(self, Hobj):
|
|
1290
|
+
"""
|
|
1291
|
+
Shorthand for self.evaluated_on(Hobj).
|
|
1292
|
+
|
|
1293
|
+
TESTS::
|
|
1294
|
+
|
|
1295
|
+
sage: p = polytopes.hypercube(3)
|
|
1296
|
+
sage: h1 = next(p.inequality_generator())
|
|
1297
|
+
sage: v1 = next(p.vertex_generator())
|
|
1298
|
+
sage: v1.__mul__(h1)
|
|
1299
|
+
0
|
|
1300
|
+
"""
|
|
1301
|
+
return self.evaluated_on(Hobj)
|
|
1302
|
+
|
|
1303
|
+
def incident(self):
|
|
1304
|
+
"""
|
|
1305
|
+
Return a generator for the equations/inequalities that are satisfied on the given
|
|
1306
|
+
vertex/ray/line.
|
|
1307
|
+
|
|
1308
|
+
EXAMPLES::
|
|
1309
|
+
|
|
1310
|
+
sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]])
|
|
1311
|
+
sage: ineq = next(triangle.inequality_generator())
|
|
1312
|
+
sage: ineq
|
|
1313
|
+
An inequality (2, -1) x + 1 >= 0
|
|
1314
|
+
sage: [ v for v in ineq.incident()]
|
|
1315
|
+
[A vertex at (-1, -1), A vertex at (0, 1)]
|
|
1316
|
+
sage: p = Polyhedron(vertices=[[0,0,0],[0,1,0],[0,0,1]], rays=[[1,-1,-1]])
|
|
1317
|
+
sage: ineq = p.Hrepresentation(2)
|
|
1318
|
+
sage: ineq
|
|
1319
|
+
An inequality (1, 0, 1) x + 0 >= 0
|
|
1320
|
+
sage: [ x for x in ineq.incident() ]
|
|
1321
|
+
[A vertex at (0, 0, 0),
|
|
1322
|
+
A vertex at (0, 1, 0),
|
|
1323
|
+
A ray in the direction (1, -1, -1)]
|
|
1324
|
+
"""
|
|
1325
|
+
incidence_matrix = self.polyhedron().incidence_matrix()
|
|
1326
|
+
for H in self.polyhedron().Hrep_generator():
|
|
1327
|
+
if incidence_matrix[self.index(), H.index()] == 1:
|
|
1328
|
+
yield H
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
class Vertex(Vrepresentation):
|
|
1332
|
+
"""
|
|
1333
|
+
A vertex of the polyhedron. Inherits from ``Vrepresentation``.
|
|
1334
|
+
"""
|
|
1335
|
+
|
|
1336
|
+
def type(self):
|
|
1337
|
+
r"""
|
|
1338
|
+
Return the type (equation/inequality/vertex/ray/line) as an
|
|
1339
|
+
integer.
|
|
1340
|
+
|
|
1341
|
+
OUTPUT:
|
|
1342
|
+
|
|
1343
|
+
Integer. One of ``PolyhedronRepresentation.INEQUALITY``,
|
|
1344
|
+
``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.
|
|
1345
|
+
|
|
1346
|
+
EXAMPLES::
|
|
1347
|
+
|
|
1348
|
+
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
|
|
1349
|
+
sage: repr_obj = next(p.vertex_generator())
|
|
1350
|
+
sage: repr_obj.type()
|
|
1351
|
+
2
|
|
1352
|
+
sage: repr_obj.type() == repr_obj.INEQUALITY
|
|
1353
|
+
False
|
|
1354
|
+
sage: repr_obj.type() == repr_obj.EQUATION
|
|
1355
|
+
False
|
|
1356
|
+
sage: repr_obj.type() == repr_obj.VERTEX
|
|
1357
|
+
True
|
|
1358
|
+
sage: repr_obj.type() == repr_obj.RAY
|
|
1359
|
+
False
|
|
1360
|
+
sage: repr_obj.type() == repr_obj.LINE
|
|
1361
|
+
False
|
|
1362
|
+
"""
|
|
1363
|
+
return self.VERTEX
|
|
1364
|
+
|
|
1365
|
+
def is_vertex(self):
|
|
1366
|
+
"""
|
|
1367
|
+
Test if this object is a vertex. By construction it always is.
|
|
1368
|
+
|
|
1369
|
+
EXAMPLES::
|
|
1370
|
+
|
|
1371
|
+
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
|
|
1372
|
+
sage: a = next(p.vertex_generator())
|
|
1373
|
+
sage: a.is_vertex()
|
|
1374
|
+
True
|
|
1375
|
+
"""
|
|
1376
|
+
return True
|
|
1377
|
+
|
|
1378
|
+
def _repr_(self):
|
|
1379
|
+
"""
|
|
1380
|
+
Return a string representation of the vertex.
|
|
1381
|
+
|
|
1382
|
+
OUTPUT: string
|
|
1383
|
+
|
|
1384
|
+
TESTS::
|
|
1385
|
+
|
|
1386
|
+
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
|
|
1387
|
+
sage: v = next(p.vertex_generator())
|
|
1388
|
+
sage: v.__repr__()
|
|
1389
|
+
'A vertex at (1, 0)'
|
|
1390
|
+
"""
|
|
1391
|
+
return 'A vertex at ' + repr(self.vector())
|
|
1392
|
+
|
|
1393
|
+
def homogeneous_vector(self, base_ring=None):
|
|
1394
|
+
"""
|
|
1395
|
+
Return homogeneous coordinates for this vertex.
|
|
1396
|
+
|
|
1397
|
+
Since a vertex is given by an affine point, this is the vector
|
|
1398
|
+
with a 1 appended.
|
|
1399
|
+
|
|
1400
|
+
INPUT:
|
|
1401
|
+
|
|
1402
|
+
- ``base_ring`` -- the base ring of the vector
|
|
1403
|
+
|
|
1404
|
+
EXAMPLES::
|
|
1405
|
+
|
|
1406
|
+
sage: P = Polyhedron(vertices=[(2,0)], rays=[(1,0)], lines=[(3,2)])
|
|
1407
|
+
sage: P.vertices()[0].homogeneous_vector()
|
|
1408
|
+
(2, 0, 1)
|
|
1409
|
+
sage: P.vertices()[0].homogeneous_vector(RDF)
|
|
1410
|
+
(2.0, 0.0, 1.0)
|
|
1411
|
+
"""
|
|
1412
|
+
v = list(self._vector) + [1]
|
|
1413
|
+
return vector(base_ring or self._base_ring, v)
|
|
1414
|
+
|
|
1415
|
+
def evaluated_on(self, Hobj):
|
|
1416
|
+
r"""
|
|
1417
|
+
Return `A\vec{x}+b`.
|
|
1418
|
+
|
|
1419
|
+
EXAMPLES::
|
|
1420
|
+
|
|
1421
|
+
sage: p = polytopes.hypercube(3)
|
|
1422
|
+
sage: v = next(p.vertex_generator())
|
|
1423
|
+
sage: h = next(p.inequality_generator())
|
|
1424
|
+
sage: v
|
|
1425
|
+
A vertex at (1, -1, -1)
|
|
1426
|
+
sage: h
|
|
1427
|
+
An inequality (-1, 0, 0) x + 1 >= 0
|
|
1428
|
+
sage: v.evaluated_on(h)
|
|
1429
|
+
0
|
|
1430
|
+
"""
|
|
1431
|
+
return Hobj.A() * self.vector() + Hobj.b()
|
|
1432
|
+
|
|
1433
|
+
def is_integral(self):
|
|
1434
|
+
r"""
|
|
1435
|
+
Return whether the coordinates of the vertex are all integral.
|
|
1436
|
+
|
|
1437
|
+
OUTPUT: boolean
|
|
1438
|
+
|
|
1439
|
+
EXAMPLES::
|
|
1440
|
+
|
|
1441
|
+
sage: p = Polyhedron([(1/2,3,5), (0,0,0), (2,3,7)])
|
|
1442
|
+
sage: [ v.is_integral() for v in p.vertex_generator() ]
|
|
1443
|
+
[True, False, True]
|
|
1444
|
+
"""
|
|
1445
|
+
return (self._base_ring is ZZ) or all(x in ZZ for x in self)
|
|
1446
|
+
|
|
1447
|
+
|
|
1448
|
+
class Ray(Vrepresentation):
|
|
1449
|
+
"""
|
|
1450
|
+
A ray of the polyhedron. Inherits from ``Vrepresentation``.
|
|
1451
|
+
"""
|
|
1452
|
+
|
|
1453
|
+
def type(self):
|
|
1454
|
+
r"""
|
|
1455
|
+
Return the type (equation/inequality/vertex/ray/line) as an
|
|
1456
|
+
integer.
|
|
1457
|
+
|
|
1458
|
+
OUTPUT:
|
|
1459
|
+
|
|
1460
|
+
Integer. One of ``PolyhedronRepresentation.INEQUALITY``,
|
|
1461
|
+
``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.
|
|
1462
|
+
|
|
1463
|
+
EXAMPLES::
|
|
1464
|
+
|
|
1465
|
+
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
|
|
1466
|
+
sage: repr_obj = next(p.ray_generator())
|
|
1467
|
+
sage: repr_obj.type()
|
|
1468
|
+
3
|
|
1469
|
+
sage: repr_obj.type() == repr_obj.INEQUALITY
|
|
1470
|
+
False
|
|
1471
|
+
sage: repr_obj.type() == repr_obj.EQUATION
|
|
1472
|
+
False
|
|
1473
|
+
sage: repr_obj.type() == repr_obj.VERTEX
|
|
1474
|
+
False
|
|
1475
|
+
sage: repr_obj.type() == repr_obj.RAY
|
|
1476
|
+
True
|
|
1477
|
+
sage: repr_obj.type() == repr_obj.LINE
|
|
1478
|
+
False
|
|
1479
|
+
"""
|
|
1480
|
+
return self.RAY
|
|
1481
|
+
|
|
1482
|
+
def is_ray(self):
|
|
1483
|
+
"""
|
|
1484
|
+
Test if this object is a ray. Always ``True`` by construction.
|
|
1485
|
+
|
|
1486
|
+
EXAMPLES::
|
|
1487
|
+
|
|
1488
|
+
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
|
|
1489
|
+
sage: a = next(p.ray_generator())
|
|
1490
|
+
sage: a.is_ray()
|
|
1491
|
+
True
|
|
1492
|
+
"""
|
|
1493
|
+
return True
|
|
1494
|
+
|
|
1495
|
+
def _repr_(self):
|
|
1496
|
+
"""
|
|
1497
|
+
A string representation of the ray.
|
|
1498
|
+
|
|
1499
|
+
TESTS::
|
|
1500
|
+
|
|
1501
|
+
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
|
|
1502
|
+
sage: a = next(p.ray_generator())
|
|
1503
|
+
sage: a._repr_()
|
|
1504
|
+
'A ray in the direction (0, 1)'
|
|
1505
|
+
"""
|
|
1506
|
+
return 'A ray in the direction ' + repr(self.vector())
|
|
1507
|
+
|
|
1508
|
+
def homogeneous_vector(self, base_ring=None):
|
|
1509
|
+
"""
|
|
1510
|
+
Return homogeneous coordinates for this ray.
|
|
1511
|
+
|
|
1512
|
+
Since a ray is given by a direction, this is the vector with a
|
|
1513
|
+
0 appended.
|
|
1514
|
+
|
|
1515
|
+
INPUT:
|
|
1516
|
+
|
|
1517
|
+
- ``base_ring`` -- the base ring of the vector
|
|
1518
|
+
|
|
1519
|
+
EXAMPLES::
|
|
1520
|
+
|
|
1521
|
+
sage: P = Polyhedron(vertices=[(2,0)], rays=[(1,0)], lines=[(3,2)])
|
|
1522
|
+
sage: P.rays()[0].homogeneous_vector()
|
|
1523
|
+
(1, 0, 0)
|
|
1524
|
+
sage: P.rays()[0].homogeneous_vector(RDF)
|
|
1525
|
+
(1.0, 0.0, 0.0)
|
|
1526
|
+
"""
|
|
1527
|
+
v = list(self._vector) + [0]
|
|
1528
|
+
return vector(base_ring or self._base_ring, v)
|
|
1529
|
+
|
|
1530
|
+
def evaluated_on(self, Hobj):
|
|
1531
|
+
r"""
|
|
1532
|
+
Return `A\vec{r}`.
|
|
1533
|
+
|
|
1534
|
+
EXAMPLES::
|
|
1535
|
+
|
|
1536
|
+
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
|
|
1537
|
+
sage: a = next(p.ray_generator())
|
|
1538
|
+
sage: h = next(p.inequality_generator())
|
|
1539
|
+
sage: a.evaluated_on(h)
|
|
1540
|
+
0
|
|
1541
|
+
"""
|
|
1542
|
+
return Hobj.A() * self.vector()
|
|
1543
|
+
|
|
1544
|
+
|
|
1545
|
+
class Line(Vrepresentation):
|
|
1546
|
+
r"""
|
|
1547
|
+
A line (Minkowski summand `\simeq\RR`) of the
|
|
1548
|
+
polyhedron. Inherits from ``Vrepresentation``.
|
|
1549
|
+
"""
|
|
1550
|
+
|
|
1551
|
+
def type(self):
|
|
1552
|
+
r"""
|
|
1553
|
+
Return the type (equation/inequality/vertex/ray/line) as an
|
|
1554
|
+
integer.
|
|
1555
|
+
|
|
1556
|
+
OUTPUT:
|
|
1557
|
+
|
|
1558
|
+
Integer. One of ``PolyhedronRepresentation.INEQUALITY``,
|
|
1559
|
+
``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.
|
|
1560
|
+
|
|
1561
|
+
EXAMPLES::
|
|
1562
|
+
|
|
1563
|
+
sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])
|
|
1564
|
+
sage: repr_obj = next(p.line_generator())
|
|
1565
|
+
sage: repr_obj.type()
|
|
1566
|
+
4
|
|
1567
|
+
sage: repr_obj.type() == repr_obj.INEQUALITY
|
|
1568
|
+
False
|
|
1569
|
+
sage: repr_obj.type() == repr_obj.EQUATION
|
|
1570
|
+
False
|
|
1571
|
+
sage: repr_obj.type() == repr_obj.VERTEX
|
|
1572
|
+
False
|
|
1573
|
+
sage: repr_obj.type() == repr_obj.RAY
|
|
1574
|
+
False
|
|
1575
|
+
sage: repr_obj.type() == repr_obj.LINE
|
|
1576
|
+
True
|
|
1577
|
+
"""
|
|
1578
|
+
return self.LINE
|
|
1579
|
+
|
|
1580
|
+
def is_line(self):
|
|
1581
|
+
"""
|
|
1582
|
+
Test if the object is a line. By construction it must be.
|
|
1583
|
+
|
|
1584
|
+
TESTS::
|
|
1585
|
+
|
|
1586
|
+
sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])
|
|
1587
|
+
sage: a = next(p.line_generator())
|
|
1588
|
+
sage: a.is_line()
|
|
1589
|
+
True
|
|
1590
|
+
"""
|
|
1591
|
+
return True
|
|
1592
|
+
|
|
1593
|
+
def _repr_(self):
|
|
1594
|
+
"""
|
|
1595
|
+
A string representation of the line.
|
|
1596
|
+
|
|
1597
|
+
TESTS::
|
|
1598
|
+
|
|
1599
|
+
sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])
|
|
1600
|
+
sage: a = next(p.line_generator())
|
|
1601
|
+
sage: a.__repr__()
|
|
1602
|
+
'A line in the direction (0, 1, 0)'
|
|
1603
|
+
"""
|
|
1604
|
+
return 'A line in the direction ' + repr(self.vector())
|
|
1605
|
+
|
|
1606
|
+
def homogeneous_vector(self, base_ring=None):
|
|
1607
|
+
"""
|
|
1608
|
+
Return homogeneous coordinates for this line.
|
|
1609
|
+
|
|
1610
|
+
Since a line is given by a direction, this is the vector with a
|
|
1611
|
+
0 appended.
|
|
1612
|
+
|
|
1613
|
+
INPUT:
|
|
1614
|
+
|
|
1615
|
+
- ``base_ring`` -- the base ring of the vector
|
|
1616
|
+
|
|
1617
|
+
EXAMPLES::
|
|
1618
|
+
|
|
1619
|
+
sage: P = Polyhedron(vertices=[(2,0)], rays=[(1,0)], lines=[(3,2)])
|
|
1620
|
+
sage: P.lines()[0].homogeneous_vector()
|
|
1621
|
+
(3, 2, 0)
|
|
1622
|
+
sage: P.lines()[0].homogeneous_vector(RDF)
|
|
1623
|
+
(3.0, 2.0, 0.0)
|
|
1624
|
+
"""
|
|
1625
|
+
v = list(self._vector) + [0]
|
|
1626
|
+
return vector(base_ring or self._base_ring, v)
|
|
1627
|
+
|
|
1628
|
+
def evaluated_on(self, Hobj):
|
|
1629
|
+
r"""
|
|
1630
|
+
Return `A\vec{\ell}`.
|
|
1631
|
+
|
|
1632
|
+
EXAMPLES::
|
|
1633
|
+
|
|
1634
|
+
sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])
|
|
1635
|
+
sage: a = next(p.line_generator())
|
|
1636
|
+
sage: h = next(p.inequality_generator())
|
|
1637
|
+
sage: a.evaluated_on(h)
|
|
1638
|
+
0
|
|
1639
|
+
"""
|
|
1640
|
+
return Hobj.A() * self.vector()
|
|
1641
|
+
|
|
1642
|
+
|
|
1643
|
+
def repr_pretty(coefficients, type, prefix='x', indices=None,
|
|
1644
|
+
latex=False, style='>=', split=False):
|
|
1645
|
+
r"""
|
|
1646
|
+
Return a pretty representation of equation/inequality represented
|
|
1647
|
+
by the coefficients.
|
|
1648
|
+
|
|
1649
|
+
INPUT:
|
|
1650
|
+
|
|
1651
|
+
- ``coefficients`` -- tuple or other iterable
|
|
1652
|
+
|
|
1653
|
+
- ``type`` -- either ``0`` (``PolyhedronRepresentation.INEQUALITY``)
|
|
1654
|
+
or ``1`` (``PolyhedronRepresentation.EQUATION``)
|
|
1655
|
+
|
|
1656
|
+
- ``prefix`` -- string (default: ``'x'``)
|
|
1657
|
+
|
|
1658
|
+
- ``indices`` -- tuple or other iterable
|
|
1659
|
+
|
|
1660
|
+
- ``latex`` -- boolean
|
|
1661
|
+
|
|
1662
|
+
- ``split`` -- boolean (default: ``False``); if set to ``True``,
|
|
1663
|
+
the output is split into a 3-tuple containing the left-hand side,
|
|
1664
|
+
the relation, and the right-hand side of the object
|
|
1665
|
+
|
|
1666
|
+
- ``style`` -- either ``'positive'`` (making all coefficients positive), or
|
|
1667
|
+
``'<='`` or ``'>='``
|
|
1668
|
+
|
|
1669
|
+
OUTPUT: a string or 3-tuple of strings (depending on ``split``)
|
|
1670
|
+
|
|
1671
|
+
EXAMPLES::
|
|
1672
|
+
|
|
1673
|
+
sage: from sage.geometry.polyhedron.representation import repr_pretty
|
|
1674
|
+
sage: from sage.geometry.polyhedron.representation import PolyhedronRepresentation
|
|
1675
|
+
sage: print(repr_pretty((0, 1, 0, 0), PolyhedronRepresentation.INEQUALITY))
|
|
1676
|
+
x0 >= 0
|
|
1677
|
+
sage: print(repr_pretty((1, 2, 1, 0), PolyhedronRepresentation.INEQUALITY))
|
|
1678
|
+
2*x0 + x1 >= -1
|
|
1679
|
+
sage: print(repr_pretty((1, -1, -1, 1), PolyhedronRepresentation.EQUATION))
|
|
1680
|
+
-x0 - x1 + x2 == -1
|
|
1681
|
+
"""
|
|
1682
|
+
from sage.misc.repr import repr_lincomb
|
|
1683
|
+
|
|
1684
|
+
coeffs = list(coefficients)
|
|
1685
|
+
if indices is None:
|
|
1686
|
+
indices = range(len(coeffs)-1)
|
|
1687
|
+
vars = [1]
|
|
1688
|
+
if latex:
|
|
1689
|
+
vars += [f'{prefix}_{{{i}}}' for i in indices]
|
|
1690
|
+
else:
|
|
1691
|
+
vars += [f'{prefix}{i}' for i in indices]
|
|
1692
|
+
if type == PolyhedronRepresentation.EQUATION:
|
|
1693
|
+
rel = '=' if latex else '=='
|
|
1694
|
+
elif type == PolyhedronRepresentation.INEQUALITY:
|
|
1695
|
+
if style == '<=':
|
|
1696
|
+
rel = r'\leq' if latex else '<='
|
|
1697
|
+
else:
|
|
1698
|
+
rel = r'\geq' if latex else '>='
|
|
1699
|
+
else:
|
|
1700
|
+
raise NotImplementedError(
|
|
1701
|
+
'no pretty printing available: wrong type {}'.format(type))
|
|
1702
|
+
|
|
1703
|
+
rvars = range(len(vars))
|
|
1704
|
+
|
|
1705
|
+
if style == 'positive':
|
|
1706
|
+
pos_part = [max(c, 0) for c in coeffs]
|
|
1707
|
+
neg_part = [pos_part[i] - coeffs[i] for i in rvars]
|
|
1708
|
+
assert all(coeffs[i] == pos_part[i] - neg_part[i] for i in rvars)
|
|
1709
|
+
left_part = repr_lincomb([[vars[i], pos_part[i]] for i in rvars], is_latex=latex, strip_one=True)
|
|
1710
|
+
right_part = repr_lincomb([[vars[i], neg_part[i]] for i in rvars], is_latex=latex, strip_one=True)
|
|
1711
|
+
elif style == '>=':
|
|
1712
|
+
left_part = repr_lincomb([[vars[i], coeffs[i]] for i in rvars[1:]], is_latex=latex)
|
|
1713
|
+
right_part = repr_lincomb([[vars[0], -coeffs[0]]], is_latex=latex, strip_one=True)
|
|
1714
|
+
elif style == '<=':
|
|
1715
|
+
left_part = repr_lincomb([[vars[i], -coeffs[i]] for i in rvars[1:]], is_latex=latex)
|
|
1716
|
+
right_part = repr_lincomb([[vars[0], coeffs[0]]], is_latex=latex, strip_one=True)
|
|
1717
|
+
else:
|
|
1718
|
+
raise NotImplementedError('no pretty printing available: wrong style {}'.format(style))
|
|
1719
|
+
|
|
1720
|
+
if not split:
|
|
1721
|
+
return '{} {} {}'.format(left_part, rel, right_part)
|
|
1722
|
+
else:
|
|
1723
|
+
return (str(left_part), rel, str(right_part))
|