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.

Files changed (206) hide show
  1. passagemath_polyhedra-10.6.31rc3.dist-info/METADATA +367 -0
  2. passagemath_polyhedra-10.6.31rc3.dist-info/METADATA.bak +369 -0
  3. passagemath_polyhedra-10.6.31rc3.dist-info/RECORD +206 -0
  4. passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +6 -0
  5. passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
  6. passagemath_polyhedra.libs/libgmp-6e109695.so.10.5.0 +0 -0
  7. passagemath_polyhedra.libs/libgomp-e985bcbb.so.1.0.0 +0 -0
  8. sage/all__sagemath_polyhedra.py +50 -0
  9. sage/game_theory/all.py +8 -0
  10. sage/game_theory/catalog.py +6 -0
  11. sage/game_theory/catalog_normal_form_games.py +923 -0
  12. sage/game_theory/cooperative_game.py +844 -0
  13. sage/game_theory/matching_game.py +1181 -0
  14. sage/game_theory/normal_form_game.py +2697 -0
  15. sage/game_theory/parser.py +275 -0
  16. sage/geometry/all__sagemath_polyhedra.py +22 -0
  17. sage/geometry/cone.py +6940 -0
  18. sage/geometry/cone_catalog.py +847 -0
  19. sage/geometry/cone_critical_angles.py +1027 -0
  20. sage/geometry/convex_set.py +1119 -0
  21. sage/geometry/fan.py +3743 -0
  22. sage/geometry/fan_isomorphism.py +389 -0
  23. sage/geometry/fan_morphism.py +1884 -0
  24. sage/geometry/hasse_diagram.py +202 -0
  25. sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
  26. sage/geometry/hyperplane_arrangement/all.py +1 -0
  27. sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
  28. sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
  29. sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
  30. sage/geometry/hyperplane_arrangement/library.py +825 -0
  31. sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
  32. sage/geometry/hyperplane_arrangement/plot.py +520 -0
  33. sage/geometry/integral_points.py +35 -0
  34. sage/geometry/integral_points_generic_dense.cpython-314-x86_64-linux-gnu.so +0 -0
  35. sage/geometry/integral_points_generic_dense.pyx +7 -0
  36. sage/geometry/lattice_polytope.py +5894 -0
  37. sage/geometry/linear_expression.py +773 -0
  38. sage/geometry/newton_polygon.py +767 -0
  39. sage/geometry/point_collection.cpython-314-x86_64-linux-gnu.so +0 -0
  40. sage/geometry/point_collection.pyx +1008 -0
  41. sage/geometry/polyhedral_complex.py +2616 -0
  42. sage/geometry/polyhedron/all.py +8 -0
  43. sage/geometry/polyhedron/backend_cdd.py +460 -0
  44. sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
  45. sage/geometry/polyhedron/backend_field.py +347 -0
  46. sage/geometry/polyhedron/backend_normaliz.py +2503 -0
  47. sage/geometry/polyhedron/backend_number_field.py +168 -0
  48. sage/geometry/polyhedron/backend_polymake.py +765 -0
  49. sage/geometry/polyhedron/backend_ppl.py +582 -0
  50. sage/geometry/polyhedron/base.py +1206 -0
  51. sage/geometry/polyhedron/base0.py +1444 -0
  52. sage/geometry/polyhedron/base1.py +886 -0
  53. sage/geometry/polyhedron/base2.py +812 -0
  54. sage/geometry/polyhedron/base3.py +1845 -0
  55. sage/geometry/polyhedron/base4.py +1262 -0
  56. sage/geometry/polyhedron/base5.py +2700 -0
  57. sage/geometry/polyhedron/base6.py +1741 -0
  58. sage/geometry/polyhedron/base7.py +997 -0
  59. sage/geometry/polyhedron/base_QQ.py +1258 -0
  60. sage/geometry/polyhedron/base_RDF.py +98 -0
  61. sage/geometry/polyhedron/base_ZZ.py +934 -0
  62. sage/geometry/polyhedron/base_mutable.py +215 -0
  63. sage/geometry/polyhedron/base_number_field.py +122 -0
  64. sage/geometry/polyhedron/cdd_file_format.py +155 -0
  65. sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
  66. sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-x86_64-linux-gnu.so +0 -0
  67. sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
  68. sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
  69. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-x86_64-linux-gnu.so +0 -0
  70. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
  71. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
  72. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-x86_64-linux-gnu.so +0 -0
  73. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
  74. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
  75. sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
  76. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-x86_64-linux-gnu.so +0 -0
  77. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
  78. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
  79. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-x86_64-linux-gnu.so +0 -0
  80. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
  81. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
  82. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-x86_64-linux-gnu.so +0 -0
  83. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
  84. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
  85. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-x86_64-linux-gnu.so +0 -0
  86. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
  87. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
  88. sage/geometry/polyhedron/constructor.py +773 -0
  89. sage/geometry/polyhedron/double_description.py +753 -0
  90. sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
  91. sage/geometry/polyhedron/face.py +1060 -0
  92. sage/geometry/polyhedron/generating_function.py +1810 -0
  93. sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
  94. sage/geometry/polyhedron/library.py +3502 -0
  95. sage/geometry/polyhedron/misc.py +121 -0
  96. sage/geometry/polyhedron/modules/all.py +1 -0
  97. sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
  98. sage/geometry/polyhedron/palp_database.py +447 -0
  99. sage/geometry/polyhedron/parent.py +1279 -0
  100. sage/geometry/polyhedron/plot.py +1986 -0
  101. sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
  102. sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
  103. sage/geometry/polyhedron/representation.py +1723 -0
  104. sage/geometry/pseudolines.py +515 -0
  105. sage/geometry/relative_interior.py +445 -0
  106. sage/geometry/toric_plotter.py +1103 -0
  107. sage/geometry/triangulation/all.py +2 -0
  108. sage/geometry/triangulation/base.cpython-314-x86_64-linux-gnu.so +0 -0
  109. sage/geometry/triangulation/base.pyx +963 -0
  110. sage/geometry/triangulation/data.h +147 -0
  111. sage/geometry/triangulation/data.pxd +4 -0
  112. sage/geometry/triangulation/element.py +914 -0
  113. sage/geometry/triangulation/functions.h +10 -0
  114. sage/geometry/triangulation/functions.pxd +4 -0
  115. sage/geometry/triangulation/point_configuration.py +2256 -0
  116. sage/geometry/triangulation/triangulations.h +49 -0
  117. sage/geometry/triangulation/triangulations.pxd +7 -0
  118. sage/geometry/voronoi_diagram.py +319 -0
  119. sage/interfaces/all__sagemath_polyhedra.py +1 -0
  120. sage/interfaces/polymake.py +2028 -0
  121. sage/numerical/all.py +13 -0
  122. sage/numerical/all__sagemath_polyhedra.py +11 -0
  123. sage/numerical/backends/all.py +1 -0
  124. sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
  125. sage/numerical/backends/cvxopt_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  126. sage/numerical/backends/cvxopt_backend.pyx +1006 -0
  127. sage/numerical/backends/cvxopt_backend_test.py +19 -0
  128. sage/numerical/backends/cvxopt_sdp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  129. sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
  130. sage/numerical/backends/cvxpy_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  131. sage/numerical/backends/cvxpy_backend.pxd +41 -0
  132. sage/numerical/backends/cvxpy_backend.pyx +934 -0
  133. sage/numerical/backends/cvxpy_backend_test.py +13 -0
  134. sage/numerical/backends/generic_backend_test.py +24 -0
  135. sage/numerical/backends/interactivelp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  136. sage/numerical/backends/interactivelp_backend.pxd +36 -0
  137. sage/numerical/backends/interactivelp_backend.pyx +1231 -0
  138. sage/numerical/backends/interactivelp_backend_test.py +12 -0
  139. sage/numerical/backends/logging_backend.py +391 -0
  140. sage/numerical/backends/matrix_sdp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  141. sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
  142. sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
  143. sage/numerical/backends/ppl_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  144. sage/numerical/backends/ppl_backend.pyx +1126 -0
  145. sage/numerical/backends/ppl_backend_test.py +13 -0
  146. sage/numerical/backends/scip_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  147. sage/numerical/backends/scip_backend.pxd +22 -0
  148. sage/numerical/backends/scip_backend.pyx +1289 -0
  149. sage/numerical/backends/scip_backend_test.py +13 -0
  150. sage/numerical/interactive_simplex_method.py +5338 -0
  151. sage/numerical/knapsack.py +665 -0
  152. sage/numerical/linear_functions.cpython-314-x86_64-linux-gnu.so +0 -0
  153. sage/numerical/linear_functions.pxd +31 -0
  154. sage/numerical/linear_functions.pyx +1648 -0
  155. sage/numerical/linear_tensor.py +470 -0
  156. sage/numerical/linear_tensor_constraints.py +448 -0
  157. sage/numerical/linear_tensor_element.cpython-314-x86_64-linux-gnu.so +0 -0
  158. sage/numerical/linear_tensor_element.pxd +6 -0
  159. sage/numerical/linear_tensor_element.pyx +459 -0
  160. sage/numerical/mip.cpython-314-x86_64-linux-gnu.so +0 -0
  161. sage/numerical/mip.pxd +40 -0
  162. sage/numerical/mip.pyx +3667 -0
  163. sage/numerical/sdp.cpython-314-x86_64-linux-gnu.so +0 -0
  164. sage/numerical/sdp.pxd +39 -0
  165. sage/numerical/sdp.pyx +1433 -0
  166. sage/rings/all__sagemath_polyhedra.py +3 -0
  167. sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
  168. sage/rings/polynomial/omega.py +982 -0
  169. sage/schemes/all__sagemath_polyhedra.py +2 -0
  170. sage/schemes/toric/all.py +10 -0
  171. sage/schemes/toric/chow_group.py +1248 -0
  172. sage/schemes/toric/divisor.py +2082 -0
  173. sage/schemes/toric/divisor_class.cpython-314-x86_64-linux-gnu.so +0 -0
  174. sage/schemes/toric/divisor_class.pyx +322 -0
  175. sage/schemes/toric/fano_variety.py +1606 -0
  176. sage/schemes/toric/homset.py +650 -0
  177. sage/schemes/toric/ideal.py +451 -0
  178. sage/schemes/toric/library.py +1322 -0
  179. sage/schemes/toric/morphism.py +1958 -0
  180. sage/schemes/toric/points.py +1032 -0
  181. sage/schemes/toric/sheaf/all.py +1 -0
  182. sage/schemes/toric/sheaf/constructor.py +302 -0
  183. sage/schemes/toric/sheaf/klyachko.py +921 -0
  184. sage/schemes/toric/toric_subscheme.py +905 -0
  185. sage/schemes/toric/variety.py +3460 -0
  186. sage/schemes/toric/weierstrass.py +1078 -0
  187. sage/schemes/toric/weierstrass_covering.py +457 -0
  188. sage/schemes/toric/weierstrass_higher.py +288 -0
  189. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
  190. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
  191. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
  192. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
  193. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
  194. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
  195. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
  196. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
  197. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
  198. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
  199. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
  200. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
  201. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
  202. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
  203. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
  204. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
  205. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
  206. 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))