passagemath-polyhedra 10.6.31rc3__cp314-cp314-musllinux_1_2_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 (208) 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 +208 -0
  4. passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +5 -0
  5. passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
  6. passagemath_polyhedra.libs/libgcc_s-0cd532bd.so.1 +0 -0
  7. passagemath_polyhedra.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  8. passagemath_polyhedra.libs/libgomp-8949ffbe.so.1.0.0 +0 -0
  9. passagemath_polyhedra.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
  10. sage/all__sagemath_polyhedra.py +50 -0
  11. sage/game_theory/all.py +8 -0
  12. sage/game_theory/catalog.py +6 -0
  13. sage/game_theory/catalog_normal_form_games.py +923 -0
  14. sage/game_theory/cooperative_game.py +844 -0
  15. sage/game_theory/matching_game.py +1181 -0
  16. sage/game_theory/normal_form_game.py +2697 -0
  17. sage/game_theory/parser.py +275 -0
  18. sage/geometry/all__sagemath_polyhedra.py +22 -0
  19. sage/geometry/cone.py +6940 -0
  20. sage/geometry/cone_catalog.py +847 -0
  21. sage/geometry/cone_critical_angles.py +1027 -0
  22. sage/geometry/convex_set.py +1119 -0
  23. sage/geometry/fan.py +3743 -0
  24. sage/geometry/fan_isomorphism.py +389 -0
  25. sage/geometry/fan_morphism.py +1884 -0
  26. sage/geometry/hasse_diagram.py +202 -0
  27. sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
  28. sage/geometry/hyperplane_arrangement/all.py +1 -0
  29. sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
  30. sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
  31. sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
  32. sage/geometry/hyperplane_arrangement/library.py +825 -0
  33. sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
  34. sage/geometry/hyperplane_arrangement/plot.py +520 -0
  35. sage/geometry/integral_points.py +35 -0
  36. sage/geometry/integral_points_generic_dense.cpython-314-x86_64-linux-musl.so +0 -0
  37. sage/geometry/integral_points_generic_dense.pyx +7 -0
  38. sage/geometry/lattice_polytope.py +5894 -0
  39. sage/geometry/linear_expression.py +773 -0
  40. sage/geometry/newton_polygon.py +767 -0
  41. sage/geometry/point_collection.cpython-314-x86_64-linux-musl.so +0 -0
  42. sage/geometry/point_collection.pyx +1008 -0
  43. sage/geometry/polyhedral_complex.py +2616 -0
  44. sage/geometry/polyhedron/all.py +8 -0
  45. sage/geometry/polyhedron/backend_cdd.py +460 -0
  46. sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
  47. sage/geometry/polyhedron/backend_field.py +347 -0
  48. sage/geometry/polyhedron/backend_normaliz.py +2503 -0
  49. sage/geometry/polyhedron/backend_number_field.py +168 -0
  50. sage/geometry/polyhedron/backend_polymake.py +765 -0
  51. sage/geometry/polyhedron/backend_ppl.py +582 -0
  52. sage/geometry/polyhedron/base.py +1206 -0
  53. sage/geometry/polyhedron/base0.py +1444 -0
  54. sage/geometry/polyhedron/base1.py +886 -0
  55. sage/geometry/polyhedron/base2.py +812 -0
  56. sage/geometry/polyhedron/base3.py +1845 -0
  57. sage/geometry/polyhedron/base4.py +1262 -0
  58. sage/geometry/polyhedron/base5.py +2700 -0
  59. sage/geometry/polyhedron/base6.py +1741 -0
  60. sage/geometry/polyhedron/base7.py +997 -0
  61. sage/geometry/polyhedron/base_QQ.py +1258 -0
  62. sage/geometry/polyhedron/base_RDF.py +98 -0
  63. sage/geometry/polyhedron/base_ZZ.py +934 -0
  64. sage/geometry/polyhedron/base_mutable.py +215 -0
  65. sage/geometry/polyhedron/base_number_field.py +122 -0
  66. sage/geometry/polyhedron/cdd_file_format.py +155 -0
  67. sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
  68. sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-x86_64-linux-musl.so +0 -0
  69. sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
  70. sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
  71. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-x86_64-linux-musl.so +0 -0
  72. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
  73. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
  74. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-x86_64-linux-musl.so +0 -0
  75. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
  76. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
  77. sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
  78. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-x86_64-linux-musl.so +0 -0
  79. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
  80. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
  81. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-x86_64-linux-musl.so +0 -0
  82. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
  83. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
  84. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-x86_64-linux-musl.so +0 -0
  85. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
  86. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
  87. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-x86_64-linux-musl.so +0 -0
  88. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
  89. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
  90. sage/geometry/polyhedron/constructor.py +773 -0
  91. sage/geometry/polyhedron/double_description.py +753 -0
  92. sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
  93. sage/geometry/polyhedron/face.py +1060 -0
  94. sage/geometry/polyhedron/generating_function.py +1810 -0
  95. sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
  96. sage/geometry/polyhedron/library.py +3502 -0
  97. sage/geometry/polyhedron/misc.py +121 -0
  98. sage/geometry/polyhedron/modules/all.py +1 -0
  99. sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
  100. sage/geometry/polyhedron/palp_database.py +447 -0
  101. sage/geometry/polyhedron/parent.py +1279 -0
  102. sage/geometry/polyhedron/plot.py +1986 -0
  103. sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
  104. sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
  105. sage/geometry/polyhedron/representation.py +1723 -0
  106. sage/geometry/pseudolines.py +515 -0
  107. sage/geometry/relative_interior.py +445 -0
  108. sage/geometry/toric_plotter.py +1103 -0
  109. sage/geometry/triangulation/all.py +2 -0
  110. sage/geometry/triangulation/base.cpython-314-x86_64-linux-musl.so +0 -0
  111. sage/geometry/triangulation/base.pyx +963 -0
  112. sage/geometry/triangulation/data.h +147 -0
  113. sage/geometry/triangulation/data.pxd +4 -0
  114. sage/geometry/triangulation/element.py +914 -0
  115. sage/geometry/triangulation/functions.h +10 -0
  116. sage/geometry/triangulation/functions.pxd +4 -0
  117. sage/geometry/triangulation/point_configuration.py +2256 -0
  118. sage/geometry/triangulation/triangulations.h +49 -0
  119. sage/geometry/triangulation/triangulations.pxd +7 -0
  120. sage/geometry/voronoi_diagram.py +319 -0
  121. sage/interfaces/all__sagemath_polyhedra.py +1 -0
  122. sage/interfaces/polymake.py +2028 -0
  123. sage/numerical/all.py +13 -0
  124. sage/numerical/all__sagemath_polyhedra.py +11 -0
  125. sage/numerical/backends/all.py +1 -0
  126. sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
  127. sage/numerical/backends/cvxopt_backend.cpython-314-x86_64-linux-musl.so +0 -0
  128. sage/numerical/backends/cvxopt_backend.pyx +1006 -0
  129. sage/numerical/backends/cvxopt_backend_test.py +19 -0
  130. sage/numerical/backends/cvxopt_sdp_backend.cpython-314-x86_64-linux-musl.so +0 -0
  131. sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
  132. sage/numerical/backends/cvxpy_backend.cpython-314-x86_64-linux-musl.so +0 -0
  133. sage/numerical/backends/cvxpy_backend.pxd +41 -0
  134. sage/numerical/backends/cvxpy_backend.pyx +934 -0
  135. sage/numerical/backends/cvxpy_backend_test.py +13 -0
  136. sage/numerical/backends/generic_backend_test.py +24 -0
  137. sage/numerical/backends/interactivelp_backend.cpython-314-x86_64-linux-musl.so +0 -0
  138. sage/numerical/backends/interactivelp_backend.pxd +36 -0
  139. sage/numerical/backends/interactivelp_backend.pyx +1231 -0
  140. sage/numerical/backends/interactivelp_backend_test.py +12 -0
  141. sage/numerical/backends/logging_backend.py +391 -0
  142. sage/numerical/backends/matrix_sdp_backend.cpython-314-x86_64-linux-musl.so +0 -0
  143. sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
  144. sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
  145. sage/numerical/backends/ppl_backend.cpython-314-x86_64-linux-musl.so +0 -0
  146. sage/numerical/backends/ppl_backend.pyx +1126 -0
  147. sage/numerical/backends/ppl_backend_test.py +13 -0
  148. sage/numerical/backends/scip_backend.cpython-314-x86_64-linux-musl.so +0 -0
  149. sage/numerical/backends/scip_backend.pxd +22 -0
  150. sage/numerical/backends/scip_backend.pyx +1289 -0
  151. sage/numerical/backends/scip_backend_test.py +13 -0
  152. sage/numerical/interactive_simplex_method.py +5338 -0
  153. sage/numerical/knapsack.py +665 -0
  154. sage/numerical/linear_functions.cpython-314-x86_64-linux-musl.so +0 -0
  155. sage/numerical/linear_functions.pxd +31 -0
  156. sage/numerical/linear_functions.pyx +1648 -0
  157. sage/numerical/linear_tensor.py +470 -0
  158. sage/numerical/linear_tensor_constraints.py +448 -0
  159. sage/numerical/linear_tensor_element.cpython-314-x86_64-linux-musl.so +0 -0
  160. sage/numerical/linear_tensor_element.pxd +6 -0
  161. sage/numerical/linear_tensor_element.pyx +459 -0
  162. sage/numerical/mip.cpython-314-x86_64-linux-musl.so +0 -0
  163. sage/numerical/mip.pxd +40 -0
  164. sage/numerical/mip.pyx +3667 -0
  165. sage/numerical/sdp.cpython-314-x86_64-linux-musl.so +0 -0
  166. sage/numerical/sdp.pxd +39 -0
  167. sage/numerical/sdp.pyx +1433 -0
  168. sage/rings/all__sagemath_polyhedra.py +3 -0
  169. sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
  170. sage/rings/polynomial/omega.py +982 -0
  171. sage/schemes/all__sagemath_polyhedra.py +2 -0
  172. sage/schemes/toric/all.py +10 -0
  173. sage/schemes/toric/chow_group.py +1248 -0
  174. sage/schemes/toric/divisor.py +2082 -0
  175. sage/schemes/toric/divisor_class.cpython-314-x86_64-linux-musl.so +0 -0
  176. sage/schemes/toric/divisor_class.pyx +322 -0
  177. sage/schemes/toric/fano_variety.py +1606 -0
  178. sage/schemes/toric/homset.py +650 -0
  179. sage/schemes/toric/ideal.py +451 -0
  180. sage/schemes/toric/library.py +1322 -0
  181. sage/schemes/toric/morphism.py +1958 -0
  182. sage/schemes/toric/points.py +1032 -0
  183. sage/schemes/toric/sheaf/all.py +1 -0
  184. sage/schemes/toric/sheaf/constructor.py +302 -0
  185. sage/schemes/toric/sheaf/klyachko.py +921 -0
  186. sage/schemes/toric/toric_subscheme.py +905 -0
  187. sage/schemes/toric/variety.py +3460 -0
  188. sage/schemes/toric/weierstrass.py +1078 -0
  189. sage/schemes/toric/weierstrass_covering.py +457 -0
  190. sage/schemes/toric/weierstrass_higher.py +288 -0
  191. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
  192. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
  193. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
  194. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
  195. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
  196. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
  197. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
  198. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
  199. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
  200. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
  201. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
  202. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
  203. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
  204. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
  205. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
  206. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
  207. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
  208. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
@@ -0,0 +1,1060 @@
1
+ # sage_setup: distribution = sagemath-polyhedra
2
+ """
3
+ A class to keep information about faces of a polyhedron
4
+
5
+ This module gives you a tool to work with the faces of a polyhedron
6
+ and their relative position. First, you need to find the faces. To get
7
+ the faces in a particular dimension, use the
8
+ :meth:`~sage.geometry.polyhedron.base.face` method::
9
+
10
+ sage: P = polytopes.cross_polytope(3)
11
+ sage: P.faces(3)
12
+ (A 3-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 6 vertices,)
13
+ sage: [f.ambient_V_indices() for f in P.facets()]
14
+ [(3, 4, 5),
15
+ (2, 4, 5),
16
+ (1, 3, 5),
17
+ (1, 2, 5),
18
+ (0, 3, 4),
19
+ (0, 2, 4),
20
+ (0, 1, 3),
21
+ (0, 1, 2)]
22
+ sage: [f.ambient_V_indices() for f in P.faces(1)]
23
+ [(4, 5),
24
+ (3, 5),
25
+ (2, 5),
26
+ (1, 5),
27
+ (3, 4),
28
+ (2, 4),
29
+ (0, 4),
30
+ (1, 3),
31
+ (0, 3),
32
+ (1, 2),
33
+ (0, 2),
34
+ (0, 1)]
35
+
36
+ or :meth:`~sage.geometry.polyhedron.base.face_lattice` to get the
37
+ whole face lattice as a poset::
38
+
39
+ sage: P.face_lattice() # needs sage.combinat
40
+ Finite lattice containing 28 elements
41
+
42
+ The faces are printed in shorthand notation where each integer is the
43
+ index of a vertex/ray/line in the same order as the containing
44
+ Polyhedron's :meth:`~sage.geometry.polyhedron.base.Vrepresentation` ::
45
+
46
+ sage: face = P.faces(1)[8]; face
47
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices
48
+ sage: face.ambient_V_indices()
49
+ (0, 3)
50
+ sage: P.Vrepresentation(0)
51
+ A vertex at (-1, 0, 0)
52
+ sage: P.Vrepresentation(3)
53
+ A vertex at (0, 0, 1)
54
+ sage: face.vertices()
55
+ (A vertex at (-1, 0, 0), A vertex at (0, 0, 1))
56
+
57
+ The face itself is not represented by Sage's
58
+ :func:`sage.geometry.polyhedron.constructor.Polyhedron` class, but by
59
+ an auxiliary class to keep the information. You can get the face as a
60
+ polyhedron with the :meth:`PolyhedronFace.as_polyhedron` method::
61
+
62
+ sage: face.as_polyhedron()
63
+ A 1-dimensional polyhedron in ZZ^3 defined as the convex hull of 2 vertices
64
+ sage: _.equations()
65
+ (An equation (0, 1, 0) x + 0 == 0,
66
+ An equation (1, 0, -1) x + 1 == 0)
67
+ """
68
+
69
+ ########################################################################
70
+ # Copyright (C) 2012 Volker Braun <vbraun.name@gmail.com>
71
+ #
72
+ # Distributed under the terms of the GNU General Public License (GPL)
73
+ #
74
+ # http://www.gnu.org/licenses/
75
+ ########################################################################
76
+
77
+ from sage.structure.richcmp import richcmp_method, richcmp
78
+ from sage.misc.cachefunc import cached_method
79
+ from sage.modules.free_module_element import vector
80
+ from sage.matrix.constructor import matrix
81
+ from sage.geometry.convex_set import ConvexSet_closed
82
+
83
+
84
+ #########################################################################
85
+ @richcmp_method
86
+ class PolyhedronFace(ConvexSet_closed):
87
+ r"""
88
+ A face of a polyhedron.
89
+
90
+ This class is for use in
91
+ :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.face_lattice`.
92
+
93
+ INPUT:
94
+
95
+ No checking is performed whether the H/V-representation indices
96
+ actually determine a face of the polyhedron. You should not
97
+ manually create :class:`PolyhedronFace` objects unless you know
98
+ what you are doing.
99
+
100
+ OUTPUT: a :class:`PolyhedronFace`
101
+
102
+ EXAMPLES::
103
+
104
+ sage: octahedron = polytopes.cross_polytope(3)
105
+ sage: inequality = octahedron.Hrepresentation(2)
106
+ sage: face_h = tuple([ inequality ])
107
+ sage: face_v = tuple( inequality.incident() )
108
+ sage: face_h_indices = [ h.index() for h in face_h ]
109
+ sage: face_v_indices = [ v.index() for v in face_v ]
110
+ sage: from sage.geometry.polyhedron.face import PolyhedronFace
111
+ sage: face = PolyhedronFace(octahedron, face_v_indices, face_h_indices)
112
+ sage: face
113
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices
114
+ sage: face.dim()
115
+ 2
116
+ sage: face.ambient_V_indices()
117
+ (0, 1, 2)
118
+ sage: face.ambient_Hrepresentation()
119
+ (An inequality (1, 1, 1) x + 1 >= 0,)
120
+ sage: face.ambient_Vrepresentation()
121
+ (A vertex at (-1, 0, 0), A vertex at (0, -1, 0), A vertex at (0, 0, -1))
122
+
123
+ TESTS::
124
+
125
+ sage: TestSuite(face).run()
126
+ """
127
+
128
+ def __init__(self, polyhedron, V_indices, H_indices):
129
+ r"""
130
+ The constructor.
131
+
132
+ See :class:`PolyhedronFace` for more information.
133
+
134
+ INPUT:
135
+
136
+ - ``polyhedron`` -- a :class:`Polyhedron`; the ambient
137
+ polyhedron
138
+
139
+ - ``V_indices`` -- list of sorted integers; the indices of the
140
+ face-spanning V-representation objects in the ambient
141
+ polyhedron
142
+
143
+ - ``H_indices`` -- list of sorted integers; the indices of the
144
+ H-representation objects of the ambient polyhedron that are
145
+ saturated on the face
146
+
147
+ TESTS::
148
+
149
+ sage: from sage.geometry.polyhedron.face import PolyhedronFace
150
+ sage: PolyhedronFace(Polyhedron(), [], []) # indirect doctest
151
+ A -1-dimensional face of a Polyhedron in ZZ^0
152
+ sage: TestSuite(_).run(skip='_test_pickling')
153
+ """
154
+ self._polyhedron = polyhedron
155
+ self._ambient_Vrepresentation_indices = tuple(V_indices)
156
+ self._ambient_Hrepresentation_indices = tuple(H_indices)
157
+ self._ambient_Vrepresentation = tuple(polyhedron.Vrepresentation(i) for i in V_indices)
158
+ self._ambient_Hrepresentation = tuple(polyhedron.Hrepresentation(i) for i in H_indices)
159
+ if polyhedron.is_mutable():
160
+ polyhedron._add_dependent_object(self)
161
+
162
+ def __hash__(self):
163
+ r"""
164
+ TESTS::
165
+
166
+ sage: P = Polyhedron([[0,0],[0,1],[23,3],[9,12]])
167
+ sage: list(map(hash, P.faces(1))) # random
168
+ [2377119663630407734,
169
+ 2377136578164722109,
170
+ 5966674064902575359,
171
+ 4795242501625591634]
172
+ """
173
+ return hash((self._polyhedron, self._ambient_Vrepresentation_indices))
174
+
175
+ def vertex_generator(self):
176
+ """
177
+ Return a generator for the vertices of the face.
178
+
179
+ EXAMPLES::
180
+
181
+ sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[1,1]])
182
+ sage: face = triangle.facets()[0]
183
+ sage: for v in face.vertex_generator(): print(v)
184
+ A vertex at (1, 0)
185
+ A vertex at (1, 1)
186
+ sage: type(face.vertex_generator())
187
+ <... 'generator'>
188
+
189
+ TESTS::
190
+
191
+ sage: TestSuite(face).run(skip='_test_pickling')
192
+ """
193
+ for V in self.ambient_Vrepresentation():
194
+ if V.is_vertex():
195
+ yield V
196
+
197
+ @cached_method
198
+ def vertices(self):
199
+ """
200
+ Return all vertices of the face.
201
+
202
+ OUTPUT: a tuple of vertices
203
+
204
+ EXAMPLES::
205
+
206
+ sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[1,1]])
207
+ sage: face = triangle.faces(1)[2]
208
+ sage: face.vertices()
209
+ (A vertex at (0, 1), A vertex at (1, 0))
210
+
211
+ TESTS::
212
+
213
+ sage: TestSuite(face).run(skip='_test_pickling')
214
+ """
215
+ return tuple(self.vertex_generator())
216
+
217
+ @cached_method
218
+ def n_vertices(self):
219
+ """
220
+ Return the number of vertices of the face.
221
+
222
+ OUTPUT: integer
223
+
224
+ EXAMPLES::
225
+
226
+ sage: Q = polytopes.cross_polytope(3)
227
+ sage: face = Q.faces(2)[0]
228
+ sage: face.n_vertices()
229
+ 3
230
+
231
+ TESTS::
232
+
233
+ sage: TestSuite(face).run(skip='_test_pickling')
234
+ """
235
+ return len(self.vertices())
236
+
237
+ def ray_generator(self):
238
+ """
239
+ Return a generator for the rays of the face.
240
+
241
+ EXAMPLES::
242
+
243
+ sage: pi = Polyhedron(ieqs = [[1,1,0],[1,0,1]])
244
+ sage: face = pi.faces(1)[1]
245
+ sage: next(face.ray_generator())
246
+ A ray in the direction (1, 0)
247
+
248
+ TESTS::
249
+
250
+ sage: TestSuite(face).run(skip='_test_pickling')
251
+ """
252
+ for V in self.ambient_Vrepresentation():
253
+ if V.is_ray():
254
+ yield V
255
+
256
+ @cached_method
257
+ def rays(self):
258
+ """
259
+ Return the rays of the face.
260
+
261
+ OUTPUT: a tuple of rays
262
+
263
+ EXAMPLES::
264
+
265
+ sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0],[1,1,0,0]])
266
+ sage: face = p.faces(2)[2]
267
+ sage: face.rays()
268
+ (A ray in the direction (1, 0, 0), A ray in the direction (0, 1, 0))
269
+ """
270
+ return tuple(self.ray_generator())
271
+
272
+ @cached_method
273
+ def n_rays(self):
274
+ """
275
+ Return the number of rays of the face.
276
+
277
+ OUTPUT: integer
278
+
279
+ EXAMPLES::
280
+
281
+ sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0],[1,1,0,0]])
282
+ sage: face = p.faces(2)[0]
283
+ sage: face.n_rays()
284
+ 2
285
+ """
286
+ return len(self.rays())
287
+
288
+ def line_generator(self):
289
+ """
290
+ Return a generator for the lines of the face.
291
+
292
+ EXAMPLES::
293
+
294
+ sage: pr = Polyhedron(rays = [[1,0],[-1,0],[0,1]], vertices = [[-1,-1]])
295
+ sage: face = pr.faces(1)[0]
296
+ sage: next(face.line_generator())
297
+ A line in the direction (1, 0)
298
+
299
+ TESTS::
300
+
301
+ sage: TestSuite(face).run(skip='_test_pickling')
302
+ """
303
+ for V in self.ambient_Vrepresentation():
304
+ if V.is_line():
305
+ yield V
306
+
307
+ @cached_method
308
+ def lines(self):
309
+ """
310
+ Return all lines of the face.
311
+
312
+ OUTPUT: a tuple of lines
313
+
314
+ EXAMPLES::
315
+
316
+ sage: p = Polyhedron(rays = [[1,0],[-1,0],[0,1],[1,1]], vertices = [[-2,-2],[2,3]])
317
+ sage: p.lines()
318
+ (A line in the direction (1, 0),)
319
+ """
320
+ return tuple(self.line_generator())
321
+
322
+ @cached_method
323
+ def n_lines(self):
324
+ """
325
+ Return the number of lines of the face.
326
+
327
+ OUTPUT: integer
328
+
329
+ EXAMPLES::
330
+
331
+ sage: p = Polyhedron(rays = [[1,0],[-1,0],[0,1],[1,1]], vertices = [[-2,-2],[2,3]])
332
+ sage: p.n_lines()
333
+ 1
334
+ """
335
+ return len(self.lines())
336
+
337
+ def __richcmp__(self, other, op):
338
+ """
339
+ Compare ``self`` and ``other``.
340
+
341
+ INPUT:
342
+
343
+ - ``other`` -- anything
344
+
345
+ OUTPUT:
346
+
347
+ Two faces test equal if and only if they are faces of the same
348
+ (not just isomorphic) polyhedron and their generators have the
349
+ same indices.
350
+
351
+ EXAMPLES::
352
+
353
+ sage: square = polytopes.hypercube(2)
354
+ sage: f = square.faces(1)
355
+ sage: matrix(4,4, lambda i,j: ZZ(f[i] <= f[j]))
356
+ [1 1 1 0]
357
+ [0 1 0 0]
358
+ [0 1 1 0]
359
+ [1 1 1 1]
360
+ sage: matrix(4,4, lambda i,j: ZZ(f[i] == f[j])) == 1
361
+ True
362
+ """
363
+ if not isinstance(other, PolyhedronFace):
364
+ return NotImplemented
365
+ if self._polyhedron is not other._polyhedron:
366
+ if (self._polyhedron.Vrepresentation() != other._polyhedron.Vrepresentation()
367
+ or self._polyhedron.Hrepresentation() != other._polyhedron.Hrepresentation()):
368
+ return NotImplemented
369
+ return richcmp(self._ambient_Vrepresentation_indices,
370
+ other._ambient_Vrepresentation_indices, op)
371
+
372
+ def ambient_Hrepresentation(self, index=None):
373
+ r"""
374
+ Return the H-representation objects of the ambient polytope
375
+ defining the face.
376
+
377
+ INPUT:
378
+
379
+ - ``index`` -- integer or ``None`` (default)
380
+
381
+ OUTPUT:
382
+
383
+ If the optional argument is not present, a tuple of
384
+ H-representation objects. Each entry is either an inequality
385
+ or an equation.
386
+
387
+ If the optional integer ``index`` is specified, the
388
+ ``index``-th element of the tuple is returned.
389
+
390
+ EXAMPLES::
391
+
392
+ sage: square = polytopes.hypercube(2)
393
+ sage: for face in square.face_lattice(): # needs sage.combinat
394
+ ....: print(face.ambient_Hrepresentation())
395
+ (An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0,
396
+ An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0)
397
+ (An inequality (-1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0)
398
+ (An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0)
399
+ (An inequality (-1, 0) x + 1 >= 0,)
400
+ (An inequality (0, -1) x + 1 >= 0, An inequality (1, 0) x + 1 >= 0)
401
+ (An inequality (0, -1) x + 1 >= 0,)
402
+ (An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0)
403
+ (An inequality (0, 1) x + 1 >= 0,)
404
+ (An inequality (1, 0) x + 1 >= 0,)
405
+ ()
406
+ """
407
+ if index is None:
408
+ return self._ambient_Hrepresentation
409
+ else:
410
+ return self._ambient_Hrepresentation[index]
411
+
412
+ def ambient_Vrepresentation(self, index=None):
413
+ r"""
414
+ Return the V-representation objects of the ambient polytope
415
+ defining the face.
416
+
417
+ INPUT:
418
+
419
+ - ``index`` -- integer or ``None`` (default)
420
+
421
+ OUTPUT:
422
+
423
+ If the optional argument is not present, a tuple of
424
+ V-representation objects. Each entry is either a vertex, a
425
+ ray, or a line.
426
+
427
+ If the optional integer ``index`` is specified, the
428
+ ``index``-th element of the tuple is returned.
429
+
430
+ EXAMPLES::
431
+
432
+ sage: square = polytopes.hypercube(2)
433
+ sage: for fl in square.face_lattice(): # needs sage.combinat
434
+ ....: print(fl.ambient_Vrepresentation())
435
+ ()
436
+ (A vertex at (1, -1),)
437
+ (A vertex at (1, 1),)
438
+ (A vertex at (1, -1), A vertex at (1, 1))
439
+ (A vertex at (-1, 1),)
440
+ (A vertex at (1, 1), A vertex at (-1, 1))
441
+ (A vertex at (-1, -1),)
442
+ (A vertex at (1, -1), A vertex at (-1, -1))
443
+ (A vertex at (-1, 1), A vertex at (-1, -1))
444
+ (A vertex at (1, -1), A vertex at (1, 1),
445
+ A vertex at (-1, 1), A vertex at (-1, -1))
446
+ """
447
+ if index is None:
448
+ return self._ambient_Vrepresentation
449
+ else:
450
+ return self._ambient_Vrepresentation[index]
451
+
452
+ def n_ambient_Hrepresentation(self):
453
+ """
454
+ Return the number of objects that make up the ambient
455
+ H-representation of the polyhedron.
456
+
457
+ See also :meth:`ambient_Hrepresentation`.
458
+
459
+ OUTPUT: integer
460
+
461
+ EXAMPLES::
462
+
463
+ sage: p = polytopes.cross_polytope(4)
464
+ sage: face = p.face_lattice()[5]; face # needs sage.combinat
465
+ A 1-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 2 vertices
466
+ sage: face.ambient_Hrepresentation() # needs sage.combinat
467
+ (An inequality (1, -1, 1, -1) x + 1 >= 0,
468
+ An inequality (1, 1, 1, 1) x + 1 >= 0,
469
+ An inequality (1, 1, 1, -1) x + 1 >= 0,
470
+ An inequality (1, -1, 1, 1) x + 1 >= 0)
471
+ sage: face.n_ambient_Hrepresentation() # needs sage.combinat
472
+ 4
473
+ """
474
+ return len(self.ambient_Hrepresentation())
475
+
476
+ def n_ambient_Vrepresentation(self):
477
+ """
478
+ Return the number of objects that make up the ambient
479
+ V-representation of the polyhedron.
480
+
481
+ See also :meth:`ambient_Vrepresentation`.
482
+
483
+ OUTPUT: integer
484
+
485
+ EXAMPLES::
486
+
487
+ sage: p = polytopes.cross_polytope(4)
488
+ sage: face = p.face_lattice()[5]; face # needs sage.combinat
489
+ A 1-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 2 vertices
490
+ sage: face.ambient_Vrepresentation() # needs sage.combinat
491
+ (A vertex at (-1, 0, 0, 0), A vertex at (0, 0, -1, 0))
492
+ sage: face.n_ambient_Vrepresentation() # needs sage.combinat
493
+ 2
494
+ """
495
+ return len(self.ambient_Vrepresentation())
496
+
497
+ def ambient_H_indices(self):
498
+ """
499
+ Return the indices of the H-representation objects of the
500
+ ambient polyhedron that make up the H-representation of ``self``.
501
+
502
+ See also :meth:`ambient_Hrepresentation`.
503
+
504
+ OUTPUT: tuple of indices
505
+
506
+ EXAMPLES::
507
+
508
+ sage: Q = polytopes.cross_polytope(3)
509
+ sage: F = Q.faces(1)
510
+ sage: [f.ambient_H_indices() for f in F]
511
+ [(4, 5),
512
+ (5, 6),
513
+ (4, 7),
514
+ (6, 7),
515
+ (0, 5),
516
+ (3, 4),
517
+ (0, 3),
518
+ (1, 6),
519
+ (0, 1),
520
+ (2, 7),
521
+ (2, 3),
522
+ (1, 2)]
523
+ """
524
+ return self._ambient_Hrepresentation_indices
525
+
526
+ def ambient_V_indices(self):
527
+ """
528
+ Return the indices of the V-representation objects of the
529
+ ambient polyhedron that make up the V-representation of ``self``.
530
+
531
+ See also :meth:`ambient_Vrepresentation`.
532
+
533
+ OUTPUT: tuple of indices
534
+
535
+ EXAMPLES::
536
+
537
+ sage: P = polytopes.cube()
538
+ sage: F = P.faces(2)
539
+ sage: [f.ambient_V_indices() for f in F]
540
+ [(0, 3, 4, 5),
541
+ (0, 1, 5, 6),
542
+ (4, 5, 6, 7),
543
+ (2, 3, 4, 7),
544
+ (1, 2, 6, 7),
545
+ (0, 1, 2, 3)]
546
+ """
547
+ return self._ambient_Vrepresentation_indices
548
+
549
+ def ambient_dim(self):
550
+ r"""
551
+ Return the dimension of the containing polyhedron.
552
+
553
+ EXAMPLES::
554
+
555
+ sage: P = Polyhedron(vertices = [[1,0,0,0],[0,1,0,0]])
556
+ sage: face = P.faces(1)[0]
557
+ sage: face.ambient_dim()
558
+ 4
559
+ """
560
+ return self._polyhedron.ambient_dim()
561
+
562
+ @cached_method
563
+ def dim(self):
564
+ """
565
+ Return the dimension of the face.
566
+
567
+ OUTPUT: integer
568
+
569
+ EXAMPLES::
570
+
571
+ sage: fl = polytopes.dodecahedron().face_lattice() # needs sage.combinat sage.rings.number_field
572
+ sage: sorted(x.dim() for x in fl) # needs sage.combinat sage.rings.number_field
573
+ [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
574
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
575
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3]
576
+
577
+ TESTS:
578
+
579
+ Check that :issue:`28650` is fixed::
580
+
581
+ sage: P = Polyhedron(vertices=[[1,0]], rays=[[1,0], [0,1]])
582
+ sage: P.faces(2)
583
+ (A 2-dimensional face of a Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,)
584
+ """
585
+ if self.n_ambient_Vrepresentation() == 0:
586
+ return -1
587
+ else:
588
+ origin = self.vertices()[0].vector()
589
+ v_list = [vector(v) - origin for v in
590
+ self.ambient_Vrepresentation() if v.is_vertex()]
591
+ v_list += [vector(v) for v in self.ambient_Vrepresentation()
592
+ if v.is_ray() or v.is_line()]
593
+ return matrix(v_list).rank()
594
+
595
+ def _repr_(self):
596
+ r"""
597
+ Return a string representation.
598
+
599
+ OUTPUT: a string listing the V-representation indices of the face
600
+
601
+ EXAMPLES::
602
+
603
+ sage: square = polytopes.hypercube(2)
604
+ sage: a_face = list( square.face_lattice() )[8] # needs sage.combinat
605
+ sage: a_face.__repr__() # needs sage.combinat
606
+ 'A 1-dimensional face of a Polyhedron in ZZ^2 defined as the convex hull of 2 vertices'
607
+ """
608
+ desc = ''
609
+ desc += 'A ' + repr(self.dim()) + '-dimensional face'
610
+ desc += ' of a Polyhedron in '
611
+ desc += self.polyhedron().parent()._repr_ambient_module()
612
+
613
+ if self.n_vertices() > 0:
614
+ desc += ' defined as the convex hull of '
615
+ desc += repr(self.n_vertices())
616
+ if self.n_vertices() == 1:
617
+ desc += ' vertex'
618
+ else:
619
+ desc += ' vertices'
620
+
621
+ if self.n_rays() > 0:
622
+ if self.n_lines() > 0:
623
+ desc += ", "
624
+ else:
625
+ desc += " and "
626
+ desc += repr(self.n_rays())
627
+ if self.n_rays() == 1:
628
+ desc += ' ray'
629
+ else:
630
+ desc += ' rays'
631
+
632
+ if self.n_lines() > 0:
633
+ if self.n_rays() > 0:
634
+ desc += ", "
635
+ else:
636
+ desc += " and "
637
+ desc += repr(self.n_lines())
638
+ if self.n_lines() == 1:
639
+ desc += ' line'
640
+ else:
641
+ desc += ' lines'
642
+
643
+ return desc
644
+
645
+ def polyhedron(self):
646
+ """
647
+ Return the containing polyhedron.
648
+
649
+ EXAMPLES::
650
+
651
+ sage: P = polytopes.cross_polytope(3); P
652
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices
653
+ sage: face = P.facets()[3]; face
654
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices
655
+ sage: face.polyhedron()
656
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices
657
+ """
658
+ return self._polyhedron
659
+
660
+ ambient = polyhedron
661
+
662
+ def ambient_vector_space(self, base_field=None):
663
+ r"""
664
+ Return the ambient vector space.
665
+
666
+ It is the ambient free module of the containing polyhedron tensored
667
+ with a field.
668
+
669
+ INPUT:
670
+
671
+ - ``base_field`` -- a field (default: the fraction field of the base ring)
672
+
673
+ EXAMPLES::
674
+
675
+ sage: half_plane = Polyhedron(ieqs=[(0,1,0)])
676
+ sage: line = half_plane.faces(1)[0]; line
677
+ A 1-dimensional face of a
678
+ Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line
679
+ sage: line.ambient_vector_space()
680
+ Vector space of dimension 2 over Rational Field
681
+ sage: line.ambient_vector_space(AA) # needs sage.rings.number_field
682
+ Vector space of dimension 2 over Algebraic Real Field
683
+ """
684
+ return self.polyhedron().ambient_vector_space(base_field=base_field)
685
+
686
+ def is_relatively_open(self):
687
+ r"""
688
+ Return whether ``self`` is relatively open.
689
+
690
+ OUTPUT: boolean
691
+
692
+ EXAMPLES::
693
+
694
+ sage: half_plane = Polyhedron(ieqs=[(0,1,0)])
695
+ sage: line = half_plane.faces(1)[0]; line
696
+ A 1-dimensional face of a
697
+ Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line
698
+ sage: line.is_relatively_open()
699
+ True
700
+ """
701
+ return self.as_polyhedron().is_relatively_open()
702
+
703
+ def is_compact(self):
704
+ r"""
705
+ Return whether ``self`` is compact.
706
+
707
+ OUTPUT: boolean
708
+
709
+ EXAMPLES::
710
+
711
+ sage: half_plane = Polyhedron(ieqs=[(0,1,0)])
712
+ sage: line = half_plane.faces(1)[0]; line
713
+ A 1-dimensional face of a
714
+ Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line
715
+ sage: line.is_compact()
716
+ False
717
+ """
718
+ return not any(V.is_ray() or V.is_line()
719
+ for V in self.ambient_Vrepresentation())
720
+
721
+ @cached_method
722
+ def as_polyhedron(self, **kwds):
723
+ """
724
+ Return the face as an independent polyhedron.
725
+
726
+ OUTPUT: a polyhedron
727
+
728
+ EXAMPLES::
729
+
730
+ sage: P = polytopes.cross_polytope(3); P
731
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices
732
+ sage: face = P.faces(2)[3]; face
733
+ A 2-dimensional face of a
734
+ Polyhedron in ZZ^3 defined as the convex hull of 3 vertices
735
+ sage: face.as_polyhedron()
736
+ A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 3 vertices
737
+
738
+ sage: P.intersection(face.as_polyhedron()) == face.as_polyhedron()
739
+ True
740
+ """
741
+ P = self._polyhedron
742
+ parent = P.parent()
743
+ Vrep = (self.vertices(), self.rays(), self.lines())
744
+ result = P.__class__(parent, Vrep, None)
745
+ if any(kwds.get(kwd) is not None
746
+ for kwd in ('base_ring', 'backend')):
747
+ from .constructor import Polyhedron
748
+ return Polyhedron(result, **kwds)
749
+ return result
750
+
751
+ def _some_elements_(self):
752
+ r"""
753
+ Generate some points of ``self``.
754
+
755
+ If ``self`` is empty, no points are generated; no exception will be raised.
756
+
757
+ EXAMPLES::
758
+
759
+ sage: P = polytopes.cross_polytope(3); P
760
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices
761
+ sage: face = P.faces(2)[3]; face
762
+ A 2-dimensional face of a
763
+ Polyhedron in ZZ^3 defined as the convex hull of 3 vertices
764
+ sage: face.as_polyhedron().vertices()
765
+ (A vertex at (0, -1, 0), A vertex at (0, 0, -1), A vertex at (1, 0, 0))
766
+ sage: face.an_element() # indirect doctest
767
+ (1/3, -1/3, -1/3)
768
+ sage: face.some_elements() # indirect doctest
769
+ [(1/3, -1/3, -1/3), (0, -1, 0), (0, -1/2, -1/2), (1/2, -1/4, -1/4)]
770
+ """
771
+ yield from self.as_polyhedron().some_elements()
772
+
773
+ def contains(self, point):
774
+ """
775
+ Test whether the polyhedron contains the given ``point``.
776
+
777
+ INPUT:
778
+
779
+ - ``point`` -- a point or its coordinates
780
+
781
+ EXAMPLES::
782
+
783
+ sage: half_plane = Polyhedron(ieqs=[(0,1,0)])
784
+ sage: line = half_plane.faces(1)[0]; line
785
+ A 1-dimensional face of a
786
+ Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line
787
+ sage: line.contains([0, 1])
788
+ True
789
+
790
+ As a shorthand, one may use the usual ``in`` operator::
791
+
792
+ sage: [5, 7] in line
793
+ False
794
+ """
795
+ # preprocess in the same way as Polyhedron_base.contains
796
+ try:
797
+ p = vector(point)
798
+ except TypeError: # point not iterable or no common ring for elements
799
+ if len(point) > 0:
800
+ return False
801
+ else:
802
+ p = vector(self.polyhedron().base_ring(), [])
803
+
804
+ if len(p) != self.ambient_dim():
805
+ return False
806
+
807
+ if not self.polyhedron().contains(p):
808
+ return False
809
+
810
+ for H in self.ambient_Hrepresentation():
811
+ if H.eval(p) != 0:
812
+ return False
813
+ return True
814
+
815
+ __contains__ = contains
816
+
817
+ @cached_method
818
+ def normal_cone(self, direction='outer'):
819
+ """
820
+ Return the polyhedral cone consisting of normal vectors to
821
+ hyperplanes supporting ``self``.
822
+
823
+ INPUT:
824
+
825
+ - ``direction`` -- string (default: ``'outer'``); the direction in
826
+ which to consider the normals. The other allowed option is
827
+ ``'inner'``.
828
+
829
+ OUTPUT: a polyhedron
830
+
831
+ EXAMPLES::
832
+
833
+ sage: p = Polyhedron(vertices=[[1,2], [2,1], [-2,2], [-2,-2], [2,-2]])
834
+ sage: for v in p.face_generator(0):
835
+ ....: vect = v.vertices()[0].vector()
836
+ ....: nc = v.normal_cone().rays_list()
837
+ ....: print("{} has outer normal cone spanned by {}".format(vect,nc))
838
+ ....:
839
+ (2, 1) has outer normal cone spanned by [[1, 0], [1, 1]]
840
+ (1, 2) has outer normal cone spanned by [[0, 1], [1, 1]]
841
+ (2, -2) has outer normal cone spanned by [[0, -1], [1, 0]]
842
+ (-2, -2) has outer normal cone spanned by [[-1, 0], [0, -1]]
843
+ (-2, 2) has outer normal cone spanned by [[-1, 0], [0, 1]]
844
+
845
+ sage: for v in p.face_generator(0):
846
+ ....: vect = v.vertices()[0].vector()
847
+ ....: nc = v.normal_cone(direction='inner').rays_list()
848
+ ....: print("{} has inner normal cone spanned by {}".format(vect,nc))
849
+ ....:
850
+ (2, 1) has inner normal cone spanned by [[-1, -1], [-1, 0]]
851
+ (1, 2) has inner normal cone spanned by [[-1, -1], [0, -1]]
852
+ (2, -2) has inner normal cone spanned by [[-1, 0], [0, 1]]
853
+ (-2, -2) has inner normal cone spanned by [[0, 1], [1, 0]]
854
+ (-2, 2) has inner normal cone spanned by [[0, -1], [1, 0]]
855
+
856
+ The function works for polytopes that are not full-dimensional::
857
+
858
+ sage: p = polytopes.permutahedron(3)
859
+ sage: f1 = p.faces(0)[0]
860
+ sage: f2 = p.faces(1)[0]
861
+ sage: f3 = p.faces(2)[0]
862
+ sage: f1.normal_cone()
863
+ A 3-dimensional polyhedron in ZZ^3 defined as
864
+ the convex hull of 1 vertex, 2 rays, 1 line
865
+ sage: f2.normal_cone()
866
+ A 2-dimensional polyhedron in ZZ^3 defined as
867
+ the convex hull of 1 vertex, 1 ray, 1 line
868
+ sage: f3.normal_cone()
869
+ A 1-dimensional polyhedron in ZZ^3 defined as
870
+ the convex hull of 1 vertex and 1 line
871
+
872
+ Normal cones are only defined for non-empty faces::
873
+
874
+ sage: f0 = p.faces(-1)[0]
875
+ sage: f0.normal_cone()
876
+ Traceback (most recent call last):
877
+ ...
878
+ ValueError: the empty face does not have a normal cone
879
+ """
880
+ if self.dim() == -1:
881
+ raise ValueError("the empty face does not have a normal cone")
882
+ elif direction not in ['outer', 'inner']:
883
+ raise ValueError("the direction should be either 'outer' or 'inner'")
884
+ rays = []
885
+ lines = []
886
+ for facet in self.ambient_Hrepresentation():
887
+ if facet.is_equation():
888
+ lines += [facet.A()]
889
+ elif direction == 'outer':
890
+ rays += [-facet.A()]
891
+ else: # 'inner'
892
+ rays += [facet.A()]
893
+ parent = self.polyhedron().parent()
894
+ origin = self.polyhedron().ambient_space().zero()
895
+ return parent.element_class(parent, [[origin], rays, lines], None)
896
+
897
+ @cached_method
898
+ def affine_tangent_cone(self):
899
+ """
900
+ Return the affine tangent cone of ``self`` as a polyhedron.
901
+
902
+ It is equal to the sum of ``self`` and the cone of feasible directions
903
+ at any point of the relative interior of ``self``.
904
+
905
+ OUTPUT: a polyhedron
906
+
907
+ EXAMPLES::
908
+
909
+ sage: half_plane_in_space = Polyhedron(ieqs=[(0,1,0,0)], eqns=[(0,0,0,1)])
910
+ sage: line = half_plane_in_space.faces(1)[0]; line
911
+ A 1-dimensional face of a
912
+ Polyhedron in QQ^3 defined as the convex hull of 1 vertex and 1 line
913
+ sage: T_line = line.affine_tangent_cone()
914
+ sage: T_line == half_plane_in_space
915
+ True
916
+
917
+ sage: c = polytopes.cube()
918
+ sage: edge = min(c.faces(1))
919
+ sage: edge.vertices()
920
+ (A vertex at (1, -1, -1), A vertex at (1, 1, -1))
921
+ sage: T_edge = edge.affine_tangent_cone()
922
+ sage: T_edge.Vrepresentation()
923
+ (A line in the direction (0, 1, 0),
924
+ A ray in the direction (0, 0, 1),
925
+ A vertex at (1, 0, -1),
926
+ A ray in the direction (-1, 0, 0))
927
+
928
+ TESTS:
929
+
930
+ Check that :issue:`32658` is fixed::
931
+
932
+ sage: P = polytopes.hypercube(2)
933
+ sage: P.faces(-1)[0].affine_tangent_cone()
934
+ Traceback (most recent call last):
935
+ ...
936
+ ValueError: affine tangent cone of the empty face not defined
937
+ """
938
+ if self.dim() == -1:
939
+ raise ValueError("affine tangent cone of the empty face not defined")
940
+ parent = self.polyhedron().parent()
941
+ new_ieqs = [H for H in self.ambient_Hrepresentation()
942
+ if H.is_inequality()]
943
+ new_eqns = [H for H in self.ambient_Hrepresentation()
944
+ if H.is_equation()]
945
+ return parent.element_class(parent, None, [new_ieqs, new_eqns])
946
+
947
+ @cached_method
948
+ def stacking_locus(self):
949
+ """
950
+ Return the polyhedron containing the points that sees every facet
951
+ containing ``self``.
952
+
953
+ OUTPUT: a polyhedron
954
+
955
+ EXAMPLES::
956
+
957
+ sage: cp = polytopes.cross_polytope(4)
958
+ sage: facet = cp.facets()[0]
959
+ sage: facet.stacking_locus().vertices()
960
+ (A vertex at (1/2, 1/2, 1/2, 1/2),
961
+ A vertex at (1, 0, 0, 0),
962
+ A vertex at (0, 0, 0, 1),
963
+ A vertex at (0, 0, 1, 0),
964
+ A vertex at (0, 1, 0, 0))
965
+ sage: face = cp.faces(2)[0]
966
+ sage: face.stacking_locus().vertices()
967
+ (A vertex at (0, 1, 0, 0),
968
+ A vertex at (0, 0, 1, 0),
969
+ A vertex at (1, 0, 0, 0),
970
+ A vertex at (1, 1, 1, 0),
971
+ A vertex at (1/2, 1/2, 1/2, 1/2),
972
+ A vertex at (1/2, 1/2, 1/2, -1/2))
973
+ """
974
+ # Taking all facets that contain the face
975
+ if self.dim() == self.polyhedron().dim() - 1:
976
+ face_star = set([self.ambient_Hrepresentation()[-1]])
977
+ else:
978
+ face_star = set(facet for facet in self.ambient_Hrepresentation() if facet.is_inequality()
979
+ if all(not facet.interior_contains(x) for x in self.vertices()))
980
+
981
+ neighboring_facets = set()
982
+ for facet in face_star:
983
+ for neighbor_facet in facet.neighbors():
984
+ if neighbor_facet not in face_star:
985
+ neighboring_facets.add(neighbor_facet)
986
+
987
+ # Create the polyhedron where we can put the new vertex
988
+ locus_ieqs = [facet.vector() for facet in neighboring_facets]
989
+ locus_ieqs += [-facet.vector() for facet in face_star]
990
+ locus_eqns = self.polyhedron().equations_list()
991
+ parent = self.polyhedron().parent().change_ring(self.polyhedron().base_ring().fraction_field())
992
+
993
+ return parent.element_class(parent, None, [locus_ieqs, locus_eqns])
994
+
995
+
996
+ def combinatorial_face_to_polyhedral_face(polyhedron, combinatorial_face):
997
+ r"""
998
+ Convert a combinatorial face to a face of a polyhedron.
999
+
1000
+ INPUT:
1001
+
1002
+ - ``polyhedron`` -- a polyhedron containing ``combinatorial_face``
1003
+ - ``combinatorial_face`` -- a :class:`CombinatorialFace`
1004
+
1005
+ OUTPUT: a :class:`PolyhedronFace`
1006
+
1007
+ EXAMPLES::
1008
+
1009
+ sage: from sage.geometry.polyhedron.face import combinatorial_face_to_polyhedral_face
1010
+ sage: P = polytopes.simplex()
1011
+ sage: C = P.combinatorial_polyhedron()
1012
+ sage: it = C.face_iter()
1013
+ sage: comb_face = next(it)
1014
+ sage: combinatorial_face_to_polyhedral_face(P, comb_face)
1015
+ A 2-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 3 vertices
1016
+
1017
+ TESTS:
1018
+
1019
+ Making sure that backends do not change their order of
1020
+ inequalities/equations without applying the changes to this method::
1021
+
1022
+ sage: polytopes.simplex(backend='field').equations()[0].index()
1023
+ 4
1024
+ sage: polytopes.simplex(backend='ppl').equations()[0].index()
1025
+ 0
1026
+ sage: polytopes.simplex(backend='cdd').equations()[0].index() # needs cddexec_gmp
1027
+ 4
1028
+ sage: polytopes.simplex(backend='normaliz').equations()[0].index() # optional - pynormaliz
1029
+ 4
1030
+ sage: polytopes.simplex(backend='polymake').equations()[0].index() # optional - jupymake
1031
+ 4
1032
+ """
1033
+ V_indices = combinatorial_face.ambient_V_indices()
1034
+ n_equations = polyhedron.n_equations()
1035
+
1036
+ if polyhedron.backend() in ('ppl',):
1037
+ # Equations before inequalities in Hrep.
1038
+ H_indices = tuple(range(n_equations))
1039
+ H_indices += tuple(x+n_equations for x in combinatorial_face.ambient_H_indices(add_equations=False))
1040
+ elif polyhedron.backend() in ('normaliz', 'cdd', 'field', 'number_field', 'polymake'):
1041
+ # Equations after the inequalities in Hrep.
1042
+ n_ieqs = polyhedron.n_inequalities()
1043
+ H_indices = tuple(combinatorial_face.ambient_H_indices(add_equations=False))
1044
+ H_indices += tuple(range(n_ieqs, n_ieqs + n_equations))
1045
+ else:
1046
+ raise NotImplementedError("unknown backend")
1047
+
1048
+ if polyhedron.dimension() == 0:
1049
+ # Taking care of a special case:
1050
+ # In this case the face lattice has a coatom,
1051
+ # but the polyhedron does not have a facet
1052
+ # (a facet is defined to be non-empty).
1053
+
1054
+ # More important, there is no inequality for that coatom.
1055
+ # So the above would produce an index error.
1056
+ # Instead, any case of the 0-dimensional polyhedron
1057
+ # satisfies all of the equations.
1058
+ H_indices = tuple(range(n_equations))
1059
+
1060
+ return PolyhedronFace(polyhedron, V_indices, H_indices)