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,1845 @@
1
+ # sage_setup: distribution = sagemath-polyhedra
2
+ r"""
3
+ Base class for polyhedra: Methods regarding the combinatorics of a polyhedron
4
+
5
+ Excluding methods relying on :mod:`sage.graphs`.
6
+ """
7
+
8
+ # ****************************************************************************
9
+ # Copyright (C) 2008-2012 Marshall Hampton <hamptonio@gmail.com>
10
+ # Copyright (C) 2011-2015 Volker Braun <vbraun.name@gmail.com>
11
+ # Copyright (C) 2012-2018 Frederic Chapoton
12
+ # Copyright (C) 2013 Andrey Novoseltsev
13
+ # Copyright (C) 2014-2017 Moritz Firsching
14
+ # Copyright (C) 2014-2019 Thierry Monteil
15
+ # Copyright (C) 2015 Nathann Cohen
16
+ # Copyright (C) 2015-2017 Jeroen Demeyer
17
+ # Copyright (C) 2015-2017 Vincent Delecroix
18
+ # Copyright (C) 2015-2018 Dima Pasechnik
19
+ # Copyright (C) 2015-2020 Jean-Philippe Labbe <labbe at math.huji.ac.il>
20
+ # Copyright (C) 2015-2021 Matthias Koeppe
21
+ # Copyright (C) 2016-2019 Daniel Krenn
22
+ # Copyright (C) 2017 Marcelo Forets
23
+ # Copyright (C) 2017-2018 Mark Bell
24
+ # Copyright (C) 2019 Julian Ritter
25
+ # Copyright (C) 2019-2020 Laith Rastanawi
26
+ # Copyright (C) 2019-2020 Sophia Elia
27
+ # Copyright (C) 2019-2021 Jonathan Kliem <jonathan.kliem@gmail.com>
28
+ #
29
+ # This program is free software: you can redistribute it and/or modify
30
+ # it under the terms of the GNU General Public License as published by
31
+ # the Free Software Foundation, either version 2 of the License, or
32
+ # (at your option) any later version.
33
+ # https://www.gnu.org/licenses/
34
+ # ****************************************************************************
35
+
36
+ from sage.misc.cachefunc import cached_method
37
+ from sage.matrix.constructor import matrix
38
+ from sage.rings.integer_ring import ZZ
39
+ from sage.rings.rational_field import QQ
40
+ from .base2 import Polyhedron_base2
41
+
42
+
43
+ class Polyhedron_base3(Polyhedron_base2):
44
+ """
45
+ Methods related to the combinatorics of a polyhedron.
46
+
47
+ See :class:`sage.geometry.polyhedron.base.Polyhedron_base`.
48
+
49
+ TESTS::
50
+
51
+ sage: from sage.geometry.polyhedron.base3 import Polyhedron_base3
52
+ sage: P = polytopes.cube()
53
+ sage: Polyhedron_base3.is_simple(P)
54
+ True
55
+ sage: Polyhedron_base3.is_simplicial(P)
56
+ False
57
+ sage: Polyhedron_base3.is_prism(P)
58
+ True
59
+ sage: Polyhedron_base3.is_pyramid(P)
60
+ False
61
+ sage: Polyhedron_base3.combinatorial_polyhedron.f(P)
62
+ A 3-dimensional combinatorial polyhedron with 6 facets
63
+ sage: Polyhedron_base3.facets(P)
64
+ (A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
65
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
66
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
67
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
68
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
69
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices)
70
+ sage: Polyhedron_base3.f_vector.f(P)
71
+ (1, 8, 12, 6, 1)
72
+ sage: next(Polyhedron_base3.face_generator(P))
73
+ A 3-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 8 vertices
74
+ """
75
+
76
+ def _init_empty_polyhedron(self):
77
+ """
78
+ Initialize an empty polyhedron.
79
+
80
+ TESTS::
81
+
82
+ sage: Polyhedron().vertex_adjacency_matrix() # indirect doctest
83
+ []
84
+ sage: Polyhedron().facet_adjacency_matrix()
85
+ [0]
86
+ """
87
+ Polyhedron_base2._init_empty_polyhedron(self)
88
+
89
+ V_matrix = matrix(ZZ, 0, 0, 0)
90
+ V_matrix.set_immutable()
91
+ self.vertex_adjacency_matrix.set_cache(V_matrix)
92
+
93
+ H_matrix = matrix(ZZ, 1, 1, 0)
94
+ H_matrix.set_immutable()
95
+ self.facet_adjacency_matrix.set_cache(H_matrix)
96
+
97
+ @cached_method
98
+ def slack_matrix(self):
99
+ r"""
100
+ Return the slack matrix.
101
+
102
+ The entries correspond to the evaluation of the Hrepresentation
103
+ elements on the Vrepresentation elements.
104
+
105
+ .. NOTE::
106
+
107
+ The columns correspond to inequalities/equations in the
108
+ order :meth:`~sage.geometry.polyhedron.base0.Polyhedron_base0.Hrepresentation`, the rows correspond to
109
+ vertices/rays/lines in the order
110
+ :meth:`~sage.geometry.polyhedron.base0.Polyhedron_base0.Vrepresentation`.
111
+
112
+ .. SEEALSO::
113
+
114
+ :meth:`incidence_matrix`.
115
+
116
+ EXAMPLES::
117
+
118
+ sage: P = polytopes.cube()
119
+ sage: P.slack_matrix()
120
+ [0 2 2 2 0 0]
121
+ [0 0 2 2 0 2]
122
+ [0 0 0 2 2 2]
123
+ [0 2 0 2 2 0]
124
+ [2 2 0 0 2 0]
125
+ [2 2 2 0 0 0]
126
+ [2 0 2 0 0 2]
127
+ [2 0 0 0 2 2]
128
+
129
+ sage: P = polytopes.cube(intervals='zero_one')
130
+ sage: P.slack_matrix()
131
+ [0 1 1 1 0 0]
132
+ [0 0 1 1 0 1]
133
+ [0 0 0 1 1 1]
134
+ [0 1 0 1 1 0]
135
+ [1 1 0 0 1 0]
136
+ [1 1 1 0 0 0]
137
+ [1 0 1 0 0 1]
138
+ [1 0 0 0 1 1]
139
+
140
+ sage: # needs sage.groups sage.rings.number_field
141
+ sage: P = polytopes.dodecahedron().faces(2)[0].as_polyhedron()
142
+ sage: P.slack_matrix()
143
+ [1/2*sqrt5 - 1/2 0 0 1 1/2*sqrt5 - 1/2 0]
144
+ [ 0 0 1/2*sqrt5 - 1/2 1/2*sqrt5 - 1/2 1 0]
145
+ [ 0 1/2*sqrt5 - 1/2 1 0 1/2*sqrt5 - 1/2 0]
146
+ [ 1 1/2*sqrt5 - 1/2 0 1/2*sqrt5 - 1/2 0 0]
147
+ [1/2*sqrt5 - 1/2 1 1/2*sqrt5 - 1/2 0 0 0]
148
+
149
+ sage: P = Polyhedron(rays=[[1, 0], [0, 1]])
150
+ sage: P.slack_matrix()
151
+ [0 0]
152
+ [0 1]
153
+ [1 0]
154
+
155
+ TESTS::
156
+
157
+ sage: Polyhedron().slack_matrix()
158
+ []
159
+ sage: Polyhedron(base_ring=QuadraticField(2)).slack_matrix().base_ring() # needs sage.rings.number_field
160
+ Number Field in a with defining polynomial x^2 - 2 with a = 1.41...
161
+ """
162
+ if not self.n_Vrepresentation() or not self.n_Hrepresentation():
163
+ slack_matrix = matrix(self.base_ring(), self.n_Vrepresentation(),
164
+ self.n_Hrepresentation(), 0)
165
+ else:
166
+ Vrep_matrix = matrix(self.base_ring(), self.Vrepresentation())
167
+ Hrep_matrix = matrix(self.base_ring(), self.Hrepresentation())
168
+
169
+ # Getting homogeneous coordinates of the Vrepresentation.
170
+ hom_helper = matrix(self.base_ring(), [1 if v.is_vertex() else 0 for v in self.Vrepresentation()])
171
+ hom_Vrep = hom_helper.stack(Vrep_matrix.transpose())
172
+
173
+ slack_matrix = (Hrep_matrix * hom_Vrep).transpose()
174
+
175
+ slack_matrix.set_immutable()
176
+ return slack_matrix
177
+
178
+ @cached_method
179
+ def incidence_matrix(self):
180
+ """
181
+ Return the incidence matrix.
182
+
183
+ .. NOTE::
184
+
185
+ The columns correspond to inequalities/equations in the
186
+ order :meth:`~sage.geometry.polyhedron.base0.Polyhedron_base0.Hrepresentation`, the rows correspond to
187
+ vertices/rays/lines in the order
188
+ :meth:`~sage.geometry.polyhedron.base0.Polyhedron_base0.Vrepresentation`.
189
+
190
+ .. SEEALSO::
191
+
192
+ :meth:`slack_matrix`.
193
+
194
+ EXAMPLES::
195
+
196
+ sage: p = polytopes.cuboctahedron()
197
+ sage: p.incidence_matrix()
198
+ [0 0 1 1 0 1 0 0 0 0 1 0 0 0]
199
+ [0 0 0 1 0 0 1 0 1 0 1 0 0 0]
200
+ [0 0 1 1 1 0 0 1 0 0 0 0 0 0]
201
+ [1 0 0 1 1 0 1 0 0 0 0 0 0 0]
202
+ [0 0 0 0 0 1 0 0 1 1 1 0 0 0]
203
+ [0 0 1 0 0 1 0 1 0 0 0 1 0 0]
204
+ [1 0 0 0 0 0 1 0 1 0 0 0 1 0]
205
+ [1 0 0 0 1 0 0 1 0 0 0 0 0 1]
206
+ [0 1 0 0 0 1 0 0 0 1 0 1 0 0]
207
+ [0 1 0 0 0 0 0 0 1 1 0 0 1 0]
208
+ [0 1 0 0 0 0 0 1 0 0 0 1 0 1]
209
+ [1 1 0 0 0 0 0 0 0 0 0 0 1 1]
210
+ sage: v = p.Vrepresentation(0)
211
+ sage: v
212
+ A vertex at (-1, -1, 0)
213
+ sage: h = p.Hrepresentation(2)
214
+ sage: h
215
+ An inequality (1, 1, -1) x + 2 >= 0
216
+ sage: h.eval(v) # evaluation (1, 1, -1) * (-1/2, -1/2, 0) + 1
217
+ 0
218
+ sage: h*v # same as h.eval(v)
219
+ 0
220
+ sage: p.incidence_matrix() [0,2] # this entry is (v,h)
221
+ 1
222
+ sage: h.contains(v)
223
+ True
224
+ sage: p.incidence_matrix() [2,0] # note: not symmetric
225
+ 0
226
+
227
+ The incidence matrix depends on the ambient dimension::
228
+
229
+ sage: simplex = polytopes.simplex(); simplex
230
+ A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 4 vertices
231
+ sage: simplex.incidence_matrix()
232
+ [1 1 1 1 0]
233
+ [1 1 1 0 1]
234
+ [1 1 0 1 1]
235
+ [1 0 1 1 1]
236
+ sage: simplex = simplex.affine_hull_projection(); simplex
237
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
238
+ sage: simplex.incidence_matrix()
239
+ [1 1 1 0]
240
+ [1 1 0 1]
241
+ [1 0 1 1]
242
+ [0 1 1 1]
243
+
244
+ An incidence matrix does not determine a unique
245
+ polyhedron::
246
+
247
+ sage: P = Polyhedron(vertices=[[0,1],[1,1],[1,0]])
248
+ sage: P.incidence_matrix()
249
+ [1 1 0]
250
+ [1 0 1]
251
+ [0 1 1]
252
+
253
+ sage: Q = Polyhedron(vertices=[[0,1], [1,0]], rays=[[1,1]])
254
+ sage: Q.incidence_matrix()
255
+ [1 1 0]
256
+ [1 0 1]
257
+ [0 1 1]
258
+
259
+
260
+ An example of two polyhedra with isomorphic face lattices
261
+ but different incidence matrices::
262
+
263
+ sage: Q.incidence_matrix()
264
+ [1 1 0]
265
+ [1 0 1]
266
+ [0 1 1]
267
+
268
+ sage: R = Polyhedron(vertices=[[0,1], [1,0]], rays=[[1,3/2], [3/2,1]])
269
+ sage: R.incidence_matrix()
270
+ [1 1 0]
271
+ [1 0 1]
272
+ [0 1 0]
273
+ [0 0 1]
274
+
275
+ The incidence matrix has base ring integers. This way one can express various
276
+ counting questions::
277
+
278
+ sage: P = polytopes.twenty_four_cell()
279
+ sage: M = P.incidence_matrix()
280
+ sage: sum(sum(x) for x in M) == P.flag_f_vector(0, 3) # needs sage.combinat
281
+ True
282
+
283
+ TESTS:
284
+
285
+ Check that :issue:`28828` is fixed::
286
+
287
+ sage: R.incidence_matrix().is_immutable()
288
+ True
289
+
290
+ Test that this method works for inexact base ring
291
+ (``cdd`` sets the cache already)::
292
+
293
+ sage: # needs sage.groups
294
+ sage: P = polytopes.dodecahedron(exact=False)
295
+ sage: M = P.incidence_matrix.cache
296
+ sage: P.incidence_matrix.clear_cache()
297
+ sage: M == P.incidence_matrix()
298
+ True
299
+ """
300
+ if self.base_ring() in (ZZ, QQ):
301
+ # Much faster for integers or rationals.
302
+ incidence_matrix = self.slack_matrix().zero_pattern_matrix(ZZ)
303
+ incidence_matrix.set_immutable()
304
+ return incidence_matrix
305
+
306
+ incidence_matrix = matrix(ZZ, self.n_Vrepresentation(),
307
+ self.n_Hrepresentation(), 0)
308
+
309
+ Vvectors_vertices = tuple((v.vector(), v.index())
310
+ for v in self.Vrep_generator()
311
+ if v.is_vertex())
312
+ Vvectors_rays_lines = tuple((v.vector(), v.index())
313
+ for v in self.Vrep_generator()
314
+ if not v.is_vertex())
315
+
316
+ # Determine ``is_zero`` to save lots of time.
317
+ if self.base_ring().is_exact():
318
+ def is_zero(x):
319
+ return not x
320
+ else:
321
+ is_zero = self._is_zero
322
+
323
+ for H in self.Hrep_generator():
324
+ Hconst = H.b()
325
+ Hvec = H.A()
326
+ Hindex = H.index()
327
+ for Vvec, Vindex in Vvectors_vertices:
328
+ if is_zero(Hvec*Vvec + Hconst):
329
+ incidence_matrix[Vindex, Hindex] = 1
330
+
331
+ # A ray or line is considered incident with a hyperplane,
332
+ # if it is orthogonal to the normal vector of the hyperplane.
333
+ for Vvec, Vindex in Vvectors_rays_lines:
334
+ if is_zero(Hvec*Vvec):
335
+ incidence_matrix[Vindex, Hindex] = 1
336
+
337
+ incidence_matrix.set_immutable()
338
+ return incidence_matrix
339
+
340
+ @cached_method
341
+ def combinatorial_polyhedron(self):
342
+ r"""
343
+ Return the combinatorial type of ``self``.
344
+
345
+ See :class:`sage.geometry.polyhedron.combinatorial_polyhedron.base.CombinatorialPolyhedron`.
346
+
347
+ EXAMPLES::
348
+
349
+ sage: polytopes.cube().combinatorial_polyhedron()
350
+ A 3-dimensional combinatorial polyhedron with 6 facets
351
+
352
+ sage: polytopes.cyclic_polytope(4,10).combinatorial_polyhedron()
353
+ A 4-dimensional combinatorial polyhedron with 35 facets
354
+
355
+ sage: Polyhedron(rays=[[0,1], [1,0]]).combinatorial_polyhedron()
356
+ A 2-dimensional combinatorial polyhedron with 2 facets
357
+ """
358
+ from sage.geometry.polyhedron.combinatorial_polyhedron.base import CombinatorialPolyhedron
359
+ return CombinatorialPolyhedron(self)
360
+
361
+ def _test_combinatorial_polyhedron(self, tester=None, **options):
362
+ """
363
+ Run test suite of combinatorial polyhedron.
364
+
365
+ TESTS::
366
+
367
+ sage: polytopes.cross_polytope(3)._test_combinatorial_polyhedron()
368
+ """
369
+ from sage.misc.sage_unittest import TestSuite
370
+
371
+ tester = self._tester(tester=tester, **options)
372
+ tester.info("\n Running the test suite of self.combinatorial_polyhedron()")
373
+ TestSuite(self.combinatorial_polyhedron()).run(verbose=tester._verbose,
374
+ prefix=tester._prefix+" ")
375
+ tester.info(tester._prefix + " ", newline=False)
376
+
377
+ def face_generator(self, face_dimension=None, algorithm=None):
378
+ r"""
379
+ Return an iterator over the faces of given dimension.
380
+
381
+ If dimension is not specified return an iterator over all faces.
382
+
383
+ INPUT:
384
+
385
+ - ``face_dimension`` -- integer (default: ``None``);
386
+ yield only faces of this dimension if specified
387
+
388
+ - ``algorithm`` -- string (optional);
389
+ specify whether to start with facets or vertices:
390
+
391
+ * ``'primal'`` -- start with the facets
392
+ * ``'dual'`` -- start with the vertices
393
+ * ``None`` -- choose automatically
394
+
395
+ OUTPUT:
396
+
397
+ A :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator_geom`.
398
+ This class iterates over faces as
399
+ :class:`~sage.geometry.polyhedron.face.PolyhedronFace`. See
400
+ :mod:`~sage.geometry.polyhedron.face` for details. The order
401
+ is random but fixed.
402
+
403
+ EXAMPLES::
404
+
405
+ sage: P = polytopes.cube()
406
+ sage: it = P.face_generator()
407
+ sage: it
408
+ Iterator over the faces of a 3-dimensional polyhedron in ZZ^3
409
+ sage: list(it)
410
+ [A 3-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 8 vertices,
411
+ A -1-dimensional face of a Polyhedron in ZZ^3,
412
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
413
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
414
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
415
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
416
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
417
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
418
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
419
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
420
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
421
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
422
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
423
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
424
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
425
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
426
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
427
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
428
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
429
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
430
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
431
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
432
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
433
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
434
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
435
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
436
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
437
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices]
438
+
439
+ sage: P = polytopes.hypercube(4)
440
+ sage: list(P.face_generator(2))[:4]
441
+ [A 2-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 4 vertices,
442
+ A 2-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 4 vertices,
443
+ A 2-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 4 vertices,
444
+ A 2-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 4 vertices]
445
+
446
+ If a polytope has more facets than vertices, the dual mode is chosen::
447
+
448
+ sage: P = polytopes.cross_polytope(3)
449
+ sage: list(P.face_generator())
450
+ [A 3-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 6 vertices,
451
+ A -1-dimensional face of a Polyhedron in ZZ^3,
452
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
453
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
454
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
455
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
456
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
457
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
458
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
459
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
460
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
461
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
462
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices,
463
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices,
464
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices,
465
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices,
466
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
467
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
468
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
469
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices,
470
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices,
471
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
472
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
473
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices,
474
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
475
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
476
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices,
477
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices]
478
+
479
+ The face iterator can also be slightly modified.
480
+ In non-dual mode we can skip subfaces of the current (proper) face::
481
+
482
+ sage: P = polytopes.cube()
483
+ sage: it = P.face_generator(algorithm='primal')
484
+ sage: _ = next(it), next(it)
485
+ sage: face = next(it)
486
+ sage: face.ambient_H_indices()
487
+ (5,)
488
+ sage: it.ignore_subfaces()
489
+ sage: face = next(it)
490
+ sage: face.ambient_H_indices()
491
+ (4,)
492
+ sage: it.ignore_subfaces()
493
+ sage: [face.ambient_H_indices() for face in it]
494
+ [(3,),
495
+ (2,),
496
+ (1,),
497
+ (0,),
498
+ (2, 3),
499
+ (1, 3),
500
+ (1, 2, 3),
501
+ (1, 2),
502
+ (0, 2),
503
+ (0, 1, 2),
504
+ (0, 1)]
505
+
506
+ In dual mode we can skip supfaces of the current (proper) face::
507
+
508
+ sage: P = polytopes.cube()
509
+ sage: it = P.face_generator(algorithm='dual')
510
+ sage: _ = next(it), next(it)
511
+ sage: face = next(it)
512
+ sage: face.ambient_V_indices()
513
+ (7,)
514
+ sage: it.ignore_supfaces()
515
+ sage: next(it)
516
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex
517
+ sage: face = next(it)
518
+ sage: face.ambient_V_indices()
519
+ (5,)
520
+ sage: it.ignore_supfaces()
521
+ sage: [face.ambient_V_indices() for face in it]
522
+ [(4,),
523
+ (3,),
524
+ (2,),
525
+ (1,),
526
+ (0,),
527
+ (1, 6),
528
+ (3, 4),
529
+ (2, 3),
530
+ (0, 3),
531
+ (0, 1, 2, 3),
532
+ (1, 2),
533
+ (0, 1)]
534
+
535
+ In non-dual mode, we cannot skip supfaces::
536
+
537
+ sage: it = P.face_generator(algorithm='primal')
538
+ sage: _ = next(it), next(it)
539
+ sage: next(it)
540
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices
541
+ sage: it.ignore_supfaces()
542
+ Traceback (most recent call last):
543
+ ...
544
+ ValueError: only possible when in dual mode
545
+
546
+ In dual mode, we cannot skip subfaces::
547
+
548
+ sage: it = P.face_generator(algorithm='dual')
549
+ sage: _ = next(it), next(it)
550
+ sage: next(it)
551
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex
552
+ sage: it.ignore_subfaces()
553
+ Traceback (most recent call last):
554
+ ...
555
+ ValueError: only possible when not in dual mode
556
+
557
+ We can only skip sub-/supfaces of proper faces::
558
+
559
+ sage: it = P.face_generator(algorithm='primal')
560
+ sage: next(it)
561
+ A 3-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 8 vertices
562
+ sage: it.ignore_subfaces()
563
+ Traceback (most recent call last):
564
+ ...
565
+ ValueError: iterator not set to a face yet
566
+
567
+ .. SEEALSO::
568
+
569
+ :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator_geom`.
570
+
571
+ ALGORITHM:
572
+
573
+ See :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator`.
574
+
575
+ TESTS::
576
+
577
+ sage: P = polytopes.simplex()
578
+ sage: list(P.face_generator(-2))
579
+ []
580
+ sage: list(P.face_generator(-1))
581
+ [A -1-dimensional face of a Polyhedron in ZZ^4]
582
+ sage: list(P.face_generator(3))
583
+ [A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 4 vertices]
584
+
585
+ sage: list(Polyhedron().face_generator())
586
+ [A -1-dimensional face of a Polyhedron in ZZ^0]
587
+
588
+ Check that :issue:`29155` is fixed::
589
+
590
+ sage: P = polytopes.permutahedron(3)
591
+ sage: [f] = P.face_generator(2)
592
+ sage: f.ambient_Hrepresentation()
593
+ (An equation (1, 1, 1) x - 6 == 0,)
594
+
595
+ Check that we catch incorrect algorithms::
596
+
597
+ sage: list(P.face_generator(2, algorithm='integrate'))[:4]
598
+ Traceback (most recent call last):
599
+ ...
600
+ ValueError: algorithm must be 'primal', 'dual' or None
601
+ """
602
+ dual = None
603
+ if algorithm == 'primal':
604
+ dual = False
605
+ elif algorithm == 'dual':
606
+ dual = True
607
+ elif algorithm is not None:
608
+ raise ValueError("algorithm must be 'primal', 'dual' or None")
609
+
610
+ from sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator import FaceIterator_geom
611
+ return FaceIterator_geom(self, output_dimension=face_dimension, dual=dual)
612
+
613
+ def faces(self, face_dimension):
614
+ """
615
+ Return the faces of given dimension.
616
+
617
+ INPUT:
618
+
619
+ - ``face_dimension`` -- integer; the dimension of the faces
620
+ whose representation will be returned
621
+
622
+ OUTPUT:
623
+
624
+ A tuple of
625
+ :class:`~sage.geometry.polyhedron.face.PolyhedronFace`. See
626
+ module :mod:`sage.geometry.polyhedron.face` for details. The order
627
+ is random but fixed.
628
+
629
+ .. SEEALSO::
630
+
631
+ :meth:`face_generator`,
632
+ :meth:`~sage.geometry.polyhedron.base0.Polyhedron_base0.facet`.
633
+
634
+ EXAMPLES:
635
+
636
+ Here we find the vertex and face indices of the eight three-dimensional
637
+ facets of the four-dimensional hypercube::
638
+
639
+ sage: p = polytopes.hypercube(4)
640
+ sage: list(f.ambient_V_indices() for f in p.faces(3))
641
+ [(0, 5, 6, 7, 8, 9, 14, 15),
642
+ (1, 4, 5, 6, 10, 13, 14, 15),
643
+ (1, 2, 6, 7, 8, 10, 11, 15),
644
+ (8, 9, 10, 11, 12, 13, 14, 15),
645
+ (0, 3, 4, 5, 9, 12, 13, 14),
646
+ (0, 2, 3, 7, 8, 9, 11, 12),
647
+ (1, 2, 3, 4, 10, 11, 12, 13),
648
+ (0, 1, 2, 3, 4, 5, 6, 7)]
649
+
650
+ sage: face = p.faces(3)[3]
651
+ sage: face.ambient_Hrepresentation()
652
+ (An inequality (1, 0, 0, 0) x + 1 >= 0,)
653
+ sage: face.vertices()
654
+ (A vertex at (-1, -1, 1, -1),
655
+ A vertex at (-1, -1, 1, 1),
656
+ A vertex at (-1, 1, -1, -1),
657
+ A vertex at (-1, 1, 1, -1),
658
+ A vertex at (-1, 1, 1, 1),
659
+ A vertex at (-1, 1, -1, 1),
660
+ A vertex at (-1, -1, -1, 1),
661
+ A vertex at (-1, -1, -1, -1))
662
+
663
+ You can use the
664
+ :meth:`~sage.geometry.polyhedron.representation.PolyhedronRepresentation.index`
665
+ method to enumerate vertices and inequalities::
666
+
667
+ sage: def get_idx(rep): return rep.index()
668
+ sage: [get_idx(_) for _ in face.ambient_Hrepresentation()]
669
+ [4]
670
+ sage: [get_idx(_) for _ in face.ambient_Vrepresentation()]
671
+ [8, 9, 10, 11, 12, 13, 14, 15]
672
+
673
+ sage: [ ([get_idx(_) for _ in face.ambient_Vrepresentation()],
674
+ ....: [get_idx(_) for _ in face.ambient_Hrepresentation()])
675
+ ....: for face in p.faces(3) ]
676
+ [([0, 5, 6, 7, 8, 9, 14, 15], [7]),
677
+ ([1, 4, 5, 6, 10, 13, 14, 15], [6]),
678
+ ([1, 2, 6, 7, 8, 10, 11, 15], [5]),
679
+ ([8, 9, 10, 11, 12, 13, 14, 15], [4]),
680
+ ([0, 3, 4, 5, 9, 12, 13, 14], [3]),
681
+ ([0, 2, 3, 7, 8, 9, 11, 12], [2]),
682
+ ([1, 2, 3, 4, 10, 11, 12, 13], [1]),
683
+ ([0, 1, 2, 3, 4, 5, 6, 7], [0])]
684
+
685
+ TESTS::
686
+
687
+ sage: pr = Polyhedron(rays = [[1,0,0],[-1,0,0],[0,1,0]], vertices = [[-1,-1,-1]], lines=[(0,0,1)])
688
+ sage: pr.faces(4)
689
+ ()
690
+ sage: pr.faces(3)[0].ambient_V_indices()
691
+ (0, 1, 2, 3)
692
+ sage: pr.facets()[0].ambient_V_indices()
693
+ (0, 1, 2)
694
+ sage: pr.faces(1)
695
+ ()
696
+ sage: pr.faces(0)
697
+ ()
698
+ sage: pr.faces(-1)
699
+ (A -1-dimensional face of a Polyhedron in QQ^3,)
700
+ """
701
+ return tuple(self.face_generator(face_dimension))
702
+
703
+ def facets(self):
704
+ r"""
705
+ Return the facets of the polyhedron.
706
+
707
+ Facets are the maximal nontrivial faces of polyhedra.
708
+ The empty face and the polyhedron itself are trivial.
709
+
710
+ A facet of a `d`-dimensional polyhedron is a face of dimension
711
+ `d-1`. For `d \neq 0` the converse is true as well.
712
+
713
+ OUTPUT:
714
+
715
+ A tuple of
716
+ :class:`~sage.geometry.polyhedron.face.PolyhedronFace`. See
717
+ :mod:`~sage.geometry.polyhedron.face` for details. The order
718
+ is random but fixed.
719
+
720
+ .. SEEALSO:: :meth:`facets`
721
+
722
+ EXAMPLES:
723
+
724
+ Here we find the eight three-dimensional facets of the
725
+ four-dimensional hypercube::
726
+
727
+ sage: p = polytopes.hypercube(4)
728
+ sage: p.facets()
729
+ (A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
730
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
731
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
732
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
733
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
734
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
735
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
736
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices)
737
+
738
+ This is the same result as explicitly finding the
739
+ three-dimensional faces::
740
+
741
+ sage: dim = p.dimension()
742
+ sage: p.faces(dim-1)
743
+ (A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
744
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
745
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
746
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
747
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
748
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
749
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
750
+ A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices)
751
+
752
+ The ``0``-dimensional polyhedron does not have facets::
753
+
754
+ sage: P = Polyhedron([[0]])
755
+ sage: P.facets()
756
+ ()
757
+ """
758
+ if self.dimension() == 0:
759
+ return ()
760
+ return self.faces(self.dimension()-1)
761
+
762
+ @cached_method(do_pickle=True, key=lambda self, x, y, z: None)
763
+ def f_vector(self, num_threads=None, parallelization_depth=None, algorithm=None):
764
+ r"""
765
+ Return the f-vector.
766
+
767
+ INPUT:
768
+
769
+ - ``num_threads`` -- integer (optional); specify the number of threads;
770
+ otherwise determined by :func:`~sage.parallel.ncpus.ncpus`
771
+
772
+ - ``parallelization_depth`` -- integer (optional); specify
773
+ how deep in the lattice the parallelization is done
774
+
775
+ - ``algorithm`` -- string (optional);
776
+ specify whether the face generator starts with facets or vertices:
777
+
778
+ * ``'primal'`` -- start with the facets
779
+ * ``'dual'`` -- start with the vertices
780
+ * ``None`` -- choose automatically
781
+
782
+ OUTPUT:
783
+
784
+ Return a vector whose `i`-th entry is the number of
785
+ `i-2`-dimensional faces of the polytope.
786
+
787
+ .. NOTE::
788
+
789
+ The ``vertices`` as given by :meth:`~sage.geometry.polyhedron.base0.Polyhedron_base0.vertices`
790
+ do not need to correspond to `0`-dimensional faces. If a polyhedron
791
+ contains `k` lines they correspond to `k`-dimensional faces.
792
+ See example below.
793
+
794
+ EXAMPLES::
795
+
796
+ sage: p = Polyhedron(vertices=[[1, 2, 3], [1, 3, 2],
797
+ ....: [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1], [0, 0, 0]])
798
+ sage: p.f_vector()
799
+ (1, 7, 12, 7, 1)
800
+
801
+ sage: polytopes.cyclic_polytope(4,10).f_vector()
802
+ (1, 10, 45, 70, 35, 1)
803
+
804
+ sage: polytopes.hypercube(5).f_vector()
805
+ (1, 32, 80, 80, 40, 10, 1)
806
+
807
+ Polyhedra with lines do not have `0`-faces::
808
+
809
+ sage: Polyhedron(ieqs=[[1,-1,0,0],[1,1,0,0]]).f_vector()
810
+ (1, 0, 0, 2, 1)
811
+
812
+ However, the method :meth:`Polyhedron_base.vertices` returns
813
+ two points that belong to the ``Vrepresentation``::
814
+
815
+ sage: P = Polyhedron(ieqs=[[1,-1,0],[1,1,0]])
816
+ sage: P.vertices()
817
+ (A vertex at (1, 0), A vertex at (-1, 0))
818
+ sage: P.f_vector()
819
+ (1, 0, 2, 1)
820
+
821
+ TESTS:
822
+
823
+ Check that :issue:`28828` is fixed::
824
+
825
+ sage: P.f_vector().is_immutable()
826
+ True
827
+
828
+ The cache of the f-vector is being pickled::
829
+
830
+ sage: P = polytopes.cube()
831
+ sage: P.f_vector()
832
+ (1, 8, 12, 6, 1)
833
+ sage: Q = loads(dumps(P))
834
+ sage: Q.f_vector.is_in_cache()
835
+ True
836
+ """
837
+ return self.combinatorial_polyhedron().f_vector(num_threads, parallelization_depth, algorithm=algorithm)
838
+
839
+ def bounded_edges(self):
840
+ """
841
+ Return the bounded edges (excluding rays and lines).
842
+
843
+ OUTPUT: a generator for pairs of vertices, one pair per edge
844
+
845
+ EXAMPLES::
846
+
847
+ sage: p = Polyhedron(vertices=[[1,0],[0,1]], rays=[[1,0],[0,1]])
848
+ sage: [ e for e in p.bounded_edges() ]
849
+ [(A vertex at (0, 1), A vertex at (1, 0))]
850
+ sage: for e in p.bounded_edges(): print(e)
851
+ (A vertex at (0, 1), A vertex at (1, 0))
852
+ """
853
+ obj = self.Vrepresentation()
854
+ for i in range(len(obj)):
855
+ if not obj[i].is_vertex():
856
+ continue
857
+ for j in range(i+1, len(obj)):
858
+ if not obj[j].is_vertex():
859
+ continue
860
+ if self.vertex_adjacency_matrix()[i, j] == 0:
861
+ continue
862
+ yield (obj[i], obj[j])
863
+
864
+ @cached_method
865
+ def vertex_adjacency_matrix(self, algorithm=None):
866
+ """
867
+ Return the binary matrix of vertex adjacencies.
868
+
869
+ INPUT:
870
+
871
+ - ``algorithm`` -- string (optional);
872
+ specify whether the face generator starts with facets or vertices:
873
+
874
+ * ``'primal'`` -- start with the facets
875
+ * ``'dual'`` -- start with the vertices
876
+ * ``None`` -- choose automatically
877
+
878
+ EXAMPLES::
879
+
880
+ sage: polytopes.simplex(4).vertex_adjacency_matrix()
881
+ [0 1 1 1 1]
882
+ [1 0 1 1 1]
883
+ [1 1 0 1 1]
884
+ [1 1 1 0 1]
885
+ [1 1 1 1 0]
886
+
887
+ The rows and columns of the vertex adjacency matrix correspond
888
+ to the :meth:`Vrepresentation` objects: vertices, rays, and
889
+ lines. The `(i,j)` matrix entry equals `1` if the `i`-th and
890
+ `j`-th V-representation object are adjacent.
891
+
892
+ Two vertices are adjacent if they are the endpoints of an
893
+ edge, that is, a one-dimensional face. For unbounded polyhedra
894
+ this clearly needs to be generalized and we define two
895
+ V-representation objects (see
896
+ :mod:`sage.geometry.polyhedron.constructor`) to be adjacent if
897
+ they together generate a one-face. There are three possible
898
+ combinations:
899
+
900
+ * Two vertices can bound a finite-length edge.
901
+
902
+ * A vertex and a ray can generate a half-infinite edge
903
+ starting at the vertex and with the direction given by the
904
+ ray.
905
+
906
+ * A vertex and a line can generate an infinite edge. The
907
+ position of the vertex on the line is arbitrary in this
908
+ case, only its transverse position matters. The direction of
909
+ the edge is given by the line generator.
910
+
911
+ For example, take the half-plane::
912
+
913
+ sage: half_plane = Polyhedron(ieqs=[(0,1,0)])
914
+ sage: half_plane.Hrepresentation()
915
+ (An inequality (1, 0) x + 0 >= 0,)
916
+
917
+ Its (non-unique) V-representation consists of a vertex, a ray,
918
+ and a line. The only edge is spanned by the vertex and the
919
+ line generator, so they are adjacent::
920
+
921
+ sage: half_plane.Vrepresentation()
922
+ (A line in the direction (0, 1), A ray in the direction (1, 0), A vertex at (0, 0))
923
+ sage: half_plane.vertex_adjacency_matrix()
924
+ [0 0 1]
925
+ [0 0 0]
926
+ [1 0 0]
927
+
928
+ In one dimension higher, that is for a half-space in 3
929
+ dimensions, there is no one-dimensional face. Hence nothing is
930
+ adjacent::
931
+
932
+ sage: Polyhedron(ieqs=[(0,1,0,0)]).vertex_adjacency_matrix()
933
+ [0 0 0 0]
934
+ [0 0 0 0]
935
+ [0 0 0 0]
936
+ [0 0 0 0]
937
+
938
+ EXAMPLES:
939
+
940
+ In a bounded polygon, every vertex has precisely two adjacent ones::
941
+
942
+ sage: P = Polyhedron(vertices=[(0, 1), (1, 0), (3, 0), (4, 1)])
943
+ sage: for v in P.Vrep_generator():
944
+ ....: print("{} {}".format(P.adjacency_matrix().row(v.index()), v))
945
+ (0, 1, 0, 1) A vertex at (0, 1)
946
+ (1, 0, 1, 0) A vertex at (1, 0)
947
+ (0, 1, 0, 1) A vertex at (3, 0)
948
+ (1, 0, 1, 0) A vertex at (4, 1)
949
+
950
+ If the V-representation of the polygon contains vertices and
951
+ one ray, then each V-representation object is adjacent to two
952
+ V-representation objects::
953
+
954
+ sage: P = Polyhedron(vertices=[(0, 1), (1, 0), (3, 0), (4, 1)],
955
+ ....: rays=[(0,1)])
956
+ sage: for v in P.Vrep_generator():
957
+ ....: print("{} {}".format(P.adjacency_matrix().row(v.index()), v))
958
+ (0, 1, 0, 0, 1) A ray in the direction (0, 1)
959
+ (1, 0, 1, 0, 0) A vertex at (0, 1)
960
+ (0, 1, 0, 1, 0) A vertex at (1, 0)
961
+ (0, 0, 1, 0, 1) A vertex at (3, 0)
962
+ (1, 0, 0, 1, 0) A vertex at (4, 1)
963
+
964
+ If the V-representation of the polygon contains vertices and
965
+ two distinct rays, then each vertex is adjacent to two
966
+ V-representation objects (which can now be vertices or
967
+ rays). The two rays are not adjacent to each other::
968
+
969
+ sage: P = Polyhedron(vertices=[(0, 1), (1, 0), (3, 0), (4, 1)],
970
+ ....: rays=[(0,1), (1,1)])
971
+ sage: for v in P.Vrep_generator():
972
+ ....: print("{} {}".format(P.adjacency_matrix().row(v.index()), v))
973
+ (0, 1, 0, 0, 0) A ray in the direction (0, 1)
974
+ (1, 0, 1, 0, 0) A vertex at (0, 1)
975
+ (0, 1, 0, 0, 1) A vertex at (1, 0)
976
+ (0, 0, 0, 0, 1) A ray in the direction (1, 1)
977
+ (0, 0, 1, 1, 0) A vertex at (3, 0)
978
+
979
+ The vertex adjacency matrix has base ring integers. This way one can express various
980
+ counting questions::
981
+
982
+ sage: P = polytopes.cube()
983
+ sage: Q = P.stack(P.faces(2)[0])
984
+ sage: M = Q.vertex_adjacency_matrix()
985
+ sage: sum(M)
986
+ (4, 4, 3, 3, 4, 4, 4, 3, 3)
987
+ sage: G = Q.vertex_graph() # needs sage.graphs
988
+ sage: G.degree() # needs sage.graphs
989
+ [4, 4, 3, 3, 4, 4, 4, 3, 3]
990
+
991
+ TESTS:
992
+
993
+ Check that :issue:`28828` is fixed::
994
+
995
+ sage: P.adjacency_matrix().is_immutable()
996
+ True
997
+ """
998
+ return self.combinatorial_polyhedron().vertex_adjacency_matrix(algorithm=algorithm)
999
+
1000
+ adjacency_matrix = vertex_adjacency_matrix
1001
+
1002
+ @cached_method
1003
+ def facet_adjacency_matrix(self, algorithm=None):
1004
+ """
1005
+ Return the adjacency matrix for the facets.
1006
+
1007
+ INPUT:
1008
+
1009
+ - ``algorithm`` -- string (optional);
1010
+ specify whether the face generator starts with facets or vertices:
1011
+
1012
+ * ``'primal'`` -- start with the facets
1013
+ * ``'dual'`` -- start with the vertices
1014
+ * ``None`` -- choose automatically
1015
+
1016
+ EXAMPLES::
1017
+
1018
+ sage: s4 = polytopes.simplex(4, project=True) # needs cddexec
1019
+ sage: s4.facet_adjacency_matrix() # needs cddexec
1020
+ [0 1 1 1 1]
1021
+ [1 0 1 1 1]
1022
+ [1 1 0 1 1]
1023
+ [1 1 1 0 1]
1024
+ [1 1 1 1 0]
1025
+
1026
+ sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)])
1027
+ sage: p.facet_adjacency_matrix()
1028
+ [0 1 1]
1029
+ [1 0 1]
1030
+ [1 1 0]
1031
+
1032
+
1033
+ The facet adjacency matrix has base ring integers. This way one can express various
1034
+ counting questions::
1035
+
1036
+ sage: P = polytopes.cube()
1037
+ sage: Q = P.stack(P.faces(2)[0])
1038
+ sage: M = Q.facet_adjacency_matrix()
1039
+ sage: sum(M)
1040
+ (4, 4, 4, 4, 3, 3, 3, 3, 4)
1041
+
1042
+ TESTS:
1043
+
1044
+ Check that :issue:`28828` is fixed::
1045
+
1046
+ sage: s4.facet_adjacency_matrix().is_immutable() # needs cddexec
1047
+ True
1048
+
1049
+ Checks that :issue:`22455` is fixed::
1050
+
1051
+ sage: s = polytopes.simplex(2)
1052
+ sage: s.facet_adjacency_matrix()
1053
+ [0 1 1]
1054
+ [1 0 1]
1055
+ [1 1 0]
1056
+ """
1057
+ return self.combinatorial_polyhedron().facet_adjacency_matrix(algorithm=algorithm)
1058
+
1059
+ def a_maximal_chain(self):
1060
+ r"""
1061
+ Return a maximal chain of the face lattice in increasing order.
1062
+
1063
+ EXAMPLES::
1064
+
1065
+ sage: P = polytopes.cube()
1066
+ sage: P.a_maximal_chain()
1067
+ [A -1-dimensional face of a Polyhedron in ZZ^3,
1068
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
1069
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
1070
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
1071
+ A 3-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 8 vertices]
1072
+ sage: P = polytopes.cube()
1073
+ sage: chain = P.a_maximal_chain(); chain
1074
+ [A -1-dimensional face of a Polyhedron in ZZ^3,
1075
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex,
1076
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices,
1077
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices,
1078
+ A 3-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 8 vertices]
1079
+ sage: [face.ambient_V_indices() for face in chain]
1080
+ [(), (5,), (0, 5), (0, 3, 4, 5), (0, 1, 2, 3, 4, 5, 6, 7)]
1081
+
1082
+ TESTS:
1083
+
1084
+ Check output for the empty polyhedron::
1085
+
1086
+ sage: P = Polyhedron()
1087
+ sage: P.a_maximal_chain()
1088
+ [A -1-dimensional face of a Polyhedron in ZZ^0]
1089
+ """
1090
+ comb_chain = self.combinatorial_polyhedron().a_maximal_chain()
1091
+
1092
+ from sage.geometry.polyhedron.face import combinatorial_face_to_polyhedral_face
1093
+ empty_face = self.faces(-1)[0]
1094
+ universe = self.faces(self.dim())[0]
1095
+
1096
+ if self.dim() == -1:
1097
+ return [empty_face]
1098
+
1099
+ return [empty_face] + \
1100
+ [combinatorial_face_to_polyhedral_face(self, face)
1101
+ for face in comb_chain] + \
1102
+ [universe]
1103
+
1104
+ def is_simplex(self):
1105
+ r"""
1106
+ Return whether the polyhedron is a simplex.
1107
+
1108
+ A simplex is a bounded polyhedron with `d+1` vertices, where
1109
+ `d` is the dimension.
1110
+
1111
+ EXAMPLES::
1112
+
1113
+ sage: Polyhedron([(0,0,0), (1,0,0), (0,1,0)]).is_simplex()
1114
+ True
1115
+ sage: polytopes.simplex(3).is_simplex()
1116
+ True
1117
+ sage: polytopes.hypercube(3).is_simplex()
1118
+ False
1119
+ """
1120
+ return self.is_compact() and (self.dim()+1 == self.n_vertices())
1121
+
1122
+ def simplicity(self):
1123
+ r"""
1124
+ Return the largest integer `k` such that the polytope is `k`-simple.
1125
+
1126
+ A polytope `P` is `k`-simple, if every `(d-1-k)`-face
1127
+ is contained in exactly `k+1` facets of `P` for `1 \leq k \leq d-1`.
1128
+ Equivalently it is `k`-simple if the polar/dual polytope is `k`-simplicial.
1129
+ If ``self`` is a simplex, it returns its dimension.
1130
+
1131
+ EXAMPLES::
1132
+
1133
+ sage: polytopes.hypersimplex(4,2).simplicity()
1134
+ 1
1135
+ sage: polytopes.hypersimplex(5,2).simplicity()
1136
+ 2
1137
+ sage: polytopes.hypersimplex(6,2).simplicity()
1138
+ 3
1139
+ sage: polytopes.simplex(3).simplicity()
1140
+ 3
1141
+ sage: polytopes.simplex(1).simplicity()
1142
+ 1
1143
+
1144
+ The method is not implemented for unbounded polyhedra::
1145
+
1146
+ sage: p = Polyhedron(vertices=[(0,0)],rays=[(1,0),(0,1)])
1147
+ sage: p.simplicity()
1148
+ Traceback (most recent call last):
1149
+ ...
1150
+ NotImplementedError: this function is implemented for polytopes only
1151
+ """
1152
+ if not self.is_compact():
1153
+ raise NotImplementedError("this function is implemented for polytopes only")
1154
+ return self.combinatorial_polyhedron().simplicity()
1155
+
1156
+ def is_simple(self):
1157
+ """
1158
+ Test for simplicity of a polytope.
1159
+
1160
+ See :wikipedia:`Simple_polytope`
1161
+
1162
+ EXAMPLES::
1163
+
1164
+ sage: p = Polyhedron([[0,0,0],[1,0,0],[0,1,0],[0,0,1]])
1165
+ sage: p.is_simple()
1166
+ True
1167
+ sage: p = Polyhedron([[0,0,0],[4,4,0],[4,0,0],[0,4,0],[2,2,2]])
1168
+ sage: p.is_simple()
1169
+ False
1170
+ """
1171
+ if not self.is_compact():
1172
+ return False
1173
+ return self.combinatorial_polyhedron().is_simple()
1174
+
1175
+ def simpliciality(self):
1176
+ r"""
1177
+ Return the largest integer `k` such that the polytope is `k`-simplicial.
1178
+
1179
+ A polytope is `k`-simplicial, if every `k`-face is a simplex.
1180
+ If ``self`` is a simplex, returns its dimension.
1181
+
1182
+ EXAMPLES::
1183
+
1184
+ sage: polytopes.cyclic_polytope(10,4).simpliciality()
1185
+ 3
1186
+ sage: polytopes.hypersimplex(5,2).simpliciality()
1187
+ 2
1188
+ sage: polytopes.cross_polytope(4).simpliciality()
1189
+ 3
1190
+ sage: polytopes.simplex(3).simpliciality()
1191
+ 3
1192
+ sage: polytopes.simplex(1).simpliciality()
1193
+ 1
1194
+
1195
+ The method is not implemented for unbounded polyhedra::
1196
+
1197
+ sage: p = Polyhedron(vertices=[(0,0)],rays=[(1,0),(0,1)])
1198
+ sage: p.simpliciality()
1199
+ Traceback (most recent call last):
1200
+ ...
1201
+ NotImplementedError: this function is implemented for polytopes only
1202
+ """
1203
+ if not self.is_compact():
1204
+ raise NotImplementedError("this function is implemented for polytopes only")
1205
+ return self.combinatorial_polyhedron().simpliciality()
1206
+
1207
+ def is_simplicial(self):
1208
+ """
1209
+ Test if the polytope is simplicial.
1210
+
1211
+ A polytope is simplicial if every facet is a simplex.
1212
+
1213
+ See :wikipedia:`Simplicial_polytope`
1214
+
1215
+ EXAMPLES::
1216
+
1217
+ sage: p = polytopes.hypercube(3)
1218
+ sage: p.is_simplicial()
1219
+ False
1220
+ sage: q = polytopes.simplex(5, project=True) # needs cddexec
1221
+ sage: q.is_simplicial() # needs cddexec
1222
+ True
1223
+ sage: p = Polyhedron([[0,0,0],[1,0,0],[0,1,0],[0,0,1]])
1224
+ sage: p.is_simplicial()
1225
+ True
1226
+ sage: q = Polyhedron([[1,1,1],[-1,1,1],[1,-1,1],[-1,-1,1],[1,1,-1]])
1227
+ sage: q.is_simplicial()
1228
+ False
1229
+ sage: P = polytopes.simplex(); P
1230
+ A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 4 vertices
1231
+ sage: P.is_simplicial()
1232
+ True
1233
+
1234
+ The method is not implemented for unbounded polyhedra::
1235
+
1236
+ sage: p = Polyhedron(vertices=[(0,0)],rays=[(1,0),(0,1)])
1237
+ sage: p.is_simplicial()
1238
+ Traceback (most recent call last):
1239
+ ...
1240
+ NotImplementedError: this function is implemented for polytopes only
1241
+ """
1242
+ if not self.is_compact():
1243
+ raise NotImplementedError("this function is implemented for polytopes only")
1244
+ return self.combinatorial_polyhedron().is_simplicial()
1245
+
1246
+ def is_pyramid(self, certificate=False):
1247
+ """
1248
+ Test whether the polytope is a pyramid over one of its facets.
1249
+
1250
+ INPUT:
1251
+
1252
+ - ``certificate`` -- boolean (default: ``False``); specifies whether
1253
+ to return a vertex of the polytope which is the apex of a pyramid,
1254
+ if found
1255
+
1256
+ OUTPUT: if ``certificate`` is ``True``, returns a tuple containing:
1257
+
1258
+ 1. Boolean.
1259
+ 2. The apex of the pyramid or ``None``.
1260
+
1261
+ If ``certificate`` is ``False`` returns a boolean.
1262
+
1263
+ EXAMPLES::
1264
+
1265
+ sage: P = polytopes.simplex(3)
1266
+ sage: P.is_pyramid()
1267
+ True
1268
+ sage: P.is_pyramid(certificate=True)
1269
+ (True, A vertex at (1, 0, 0, 0))
1270
+ sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() # needs sage.rings.number_field
1271
+ sage: egyptian_pyramid.is_pyramid() # needs sage.rings.number_field
1272
+ True
1273
+ sage: Q = polytopes.octahedron()
1274
+ sage: Q.is_pyramid()
1275
+ False
1276
+
1277
+ For the `0`-dimensional polyhedron, the output is ``True``,
1278
+ but it cannot be constructed as a pyramid over the empty polyhedron::
1279
+
1280
+ sage: P = Polyhedron([[0]])
1281
+ sage: P.is_pyramid()
1282
+ True
1283
+ sage: Polyhedron().pyramid()
1284
+ Traceback (most recent call last):
1285
+ ...
1286
+ ZeroDivisionError: rational division by zero
1287
+ """
1288
+ if not self.is_compact():
1289
+ raise ValueError("polyhedron has to be compact")
1290
+
1291
+ return self.combinatorial_polyhedron().is_pyramid(certificate)
1292
+
1293
+ def is_bipyramid(self, certificate=False):
1294
+ r"""
1295
+ Test whether the polytope is combinatorially equivalent to a
1296
+ bipyramid over some polytope.
1297
+
1298
+ INPUT:
1299
+
1300
+ - ``certificate`` -- boolean (default: ``False``); specifies whether
1301
+ to return two vertices of the polytope which are the apices of a
1302
+ bipyramid, if found
1303
+
1304
+ OUTPUT: if ``certificate`` is ``True``, returns a tuple containing:
1305
+
1306
+ 1. Boolean.
1307
+ 2. ``None`` or a tuple containing:
1308
+ a. The first apex.
1309
+ b. The second apex.
1310
+
1311
+ If ``certificate`` is ``False`` returns a boolean.
1312
+
1313
+ EXAMPLES::
1314
+
1315
+ sage: P = polytopes.octahedron()
1316
+ sage: P.is_bipyramid()
1317
+ True
1318
+ sage: P.is_bipyramid(certificate=True)
1319
+ (True, [A vertex at (1, 0, 0), A vertex at (-1, 0, 0)])
1320
+ sage: Q = polytopes.cyclic_polytope(3,7)
1321
+ sage: Q.is_bipyramid()
1322
+ False
1323
+ sage: R = Q.bipyramid()
1324
+ sage: R.is_bipyramid(certificate=True)
1325
+ (True, [A vertex at (1, 3, 13, 63), A vertex at (-1, 3, 13, 63)])
1326
+
1327
+ TESTS::
1328
+
1329
+ sage: P = polytopes.permutahedron(4).bipyramid()
1330
+ sage: P.is_bipyramid()
1331
+ True
1332
+
1333
+ sage: P = polytopes.cube()
1334
+ sage: P.is_bipyramid()
1335
+ False
1336
+
1337
+ sage: P = Polyhedron(vertices=[[0,1], [1,0]], rays=[[1,1]])
1338
+ sage: P.is_bipyramid()
1339
+ Traceback (most recent call last):
1340
+ ...
1341
+ ValueError: polyhedron has to be compact
1342
+ """
1343
+ if not self.is_compact():
1344
+ raise ValueError("polyhedron has to be compact")
1345
+
1346
+ return self.combinatorial_polyhedron().is_bipyramid(certificate)
1347
+
1348
+ def is_prism(self, certificate=False):
1349
+ """
1350
+ Test whether the polytope is combinatorially equivalent to a prism of
1351
+ some polytope.
1352
+
1353
+ INPUT:
1354
+
1355
+ - ``certificate`` -- boolean (default: ``False``); specifies whether
1356
+ to return two facets of the polytope which are the bases of a prism,
1357
+ if found
1358
+
1359
+ OUTPUT: if ``certificate`` is ``True``, returns a tuple containing:
1360
+
1361
+ 1. Boolean.
1362
+ 2. ``None`` or a tuple containing:
1363
+ a. List of the vertices of the first base facet.
1364
+ b. List of the vertices of the second base facet.
1365
+
1366
+ If ``certificate`` is ``False`` returns a boolean.
1367
+
1368
+ EXAMPLES::
1369
+
1370
+ sage: P = polytopes.cube()
1371
+ sage: P.is_prism()
1372
+ True
1373
+ sage: P.is_prism(certificate=True)
1374
+ (True,
1375
+ [(A vertex at (1, -1, -1),
1376
+ A vertex at (1, -1, 1),
1377
+ A vertex at (-1, -1, 1),
1378
+ A vertex at (-1, -1, -1)),
1379
+ (A vertex at (1, 1, -1),
1380
+ A vertex at (1, 1, 1),
1381
+ A vertex at (-1, 1, -1),
1382
+ A vertex at (-1, 1, 1))])
1383
+ sage: Q = polytopes.cyclic_polytope(3,8)
1384
+ sage: Q.is_prism()
1385
+ False
1386
+ sage: R = Q.prism()
1387
+ sage: R.is_prism(certificate=True)
1388
+ (True,
1389
+ [(A vertex at (0, 3, 9, 27),
1390
+ A vertex at (0, 6, 36, 216),
1391
+ A vertex at (0, 0, 0, 0),
1392
+ A vertex at (0, 7, 49, 343),
1393
+ A vertex at (0, 5, 25, 125),
1394
+ A vertex at (0, 1, 1, 1),
1395
+ A vertex at (0, 2, 4, 8),
1396
+ A vertex at (0, 4, 16, 64)),
1397
+ (A vertex at (1, 6, 36, 216),
1398
+ A vertex at (1, 0, 0, 0),
1399
+ A vertex at (1, 7, 49, 343),
1400
+ A vertex at (1, 5, 25, 125),
1401
+ A vertex at (1, 1, 1, 1),
1402
+ A vertex at (1, 2, 4, 8),
1403
+ A vertex at (1, 4, 16, 64),
1404
+ A vertex at (1, 3, 9, 27))])
1405
+
1406
+ TESTS::
1407
+
1408
+ sage: P = polytopes.cross_polytope(5)
1409
+ sage: P.is_prism()
1410
+ False
1411
+
1412
+ sage: P = polytopes.permutahedron(4).prism()
1413
+ sage: P.is_prism()
1414
+ True
1415
+
1416
+ sage: P = Polyhedron(vertices=[[0,1], [1,0]], rays=[[1,1]])
1417
+ sage: P.is_prism()
1418
+ Traceback (most recent call last):
1419
+ ...
1420
+ NotImplementedError: polyhedron has to be compact
1421
+ """
1422
+ if not self.is_compact():
1423
+ raise NotImplementedError("polyhedron has to be compact")
1424
+
1425
+ return self.combinatorial_polyhedron().is_prism(certificate)
1426
+
1427
+ def is_lawrence_polytope(self):
1428
+ """
1429
+ Return ``True`` if ``self`` is a Lawrence polytope.
1430
+
1431
+ A polytope is called a Lawrence polytope if it has a centrally
1432
+ symmetric (normalized) Gale diagram.
1433
+
1434
+ EXAMPLES::
1435
+
1436
+ sage: P = polytopes.hypersimplex(5,2)
1437
+ sage: L = P.lawrence_polytope()
1438
+ sage: L.is_lattice_polytope()
1439
+ True
1440
+
1441
+ sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() # needs sage.number_field
1442
+ sage: egyptian_pyramid.is_lawrence_polytope() # needs sage.number_field
1443
+ True
1444
+
1445
+ sage: polytopes.octahedron().is_lawrence_polytope()
1446
+ False
1447
+
1448
+ REFERENCES:
1449
+
1450
+ For more information, see [BaSt1990]_.
1451
+ """
1452
+ if not self.is_compact():
1453
+ raise NotImplementedError("self must be a polytope")
1454
+
1455
+ return self.combinatorial_polyhedron().is_lawrence_polytope()
1456
+
1457
+ def neighborliness(self):
1458
+ r"""
1459
+ Return the largest ``k``, such that the polyhedron is ``k``-neighborly.
1460
+
1461
+ A polyhedron is `k`-neighborly if every set of `n` vertices forms a face
1462
+ for `n` up to `k`.
1463
+
1464
+ In case of the `d`-dimensional simplex, it returns `d + 1`.
1465
+
1466
+ .. SEEALSO::
1467
+
1468
+ :meth:`is_neighborly`
1469
+
1470
+ EXAMPLES::
1471
+
1472
+ sage: cube = polytopes.cube()
1473
+ sage: cube.neighborliness()
1474
+ 1
1475
+ sage: P = Polyhedron(); P
1476
+ The empty polyhedron in ZZ^0
1477
+ sage: P.neighborliness()
1478
+ 0
1479
+ sage: P = Polyhedron([[0]]); P
1480
+ A 0-dimensional polyhedron in ZZ^1 defined as the convex hull of 1 vertex
1481
+ sage: P.neighborliness()
1482
+ 1
1483
+ sage: S = polytopes.simplex(5); S
1484
+ A 5-dimensional polyhedron in ZZ^6 defined as the convex hull of 6 vertices
1485
+ sage: S.neighborliness()
1486
+ 6
1487
+ sage: C = polytopes.cyclic_polytope(7,10); C
1488
+ A 7-dimensional polyhedron in QQ^7 defined as the convex hull of 10 vertices
1489
+ sage: C.neighborliness()
1490
+ 3
1491
+ sage: C = polytopes.cyclic_polytope(6,11); C
1492
+ A 6-dimensional polyhedron in QQ^6 defined as the convex hull of 11 vertices
1493
+ sage: C.neighborliness()
1494
+ 3
1495
+ sage: [polytopes.cyclic_polytope(5,n).neighborliness() for n in range(6,10)]
1496
+ [6, 2, 2, 2]
1497
+ """
1498
+ return self.combinatorial_polyhedron().neighborliness()
1499
+
1500
+ def is_neighborly(self, k=None):
1501
+ r"""
1502
+ Return whether the polyhedron is neighborly.
1503
+
1504
+ If the input ``k`` is provided, then return whether the polyhedron is ``k``-neighborly
1505
+
1506
+ A polyhedron is neighborly if every set of `n` vertices forms a face
1507
+ for `n` up to floor of half the dimension of the polyhedron.
1508
+ It is `k`-neighborly if this is true for `n` up to `k`.
1509
+
1510
+ INPUT:
1511
+
1512
+ - ``k`` -- the dimension up to which to check if every set of ``k``
1513
+ vertices forms a face. If no ``k`` is provided, check up to floor
1514
+ of half the dimension of the polyhedron.
1515
+
1516
+ OUTPUT:
1517
+
1518
+ - ``True`` if every set of up to ``k`` vertices forms a face,
1519
+ - ``False`` otherwise
1520
+
1521
+ .. SEEALSO::
1522
+
1523
+ :meth:`neighborliness`
1524
+
1525
+ EXAMPLES::
1526
+
1527
+ sage: cube = polytopes.hypercube(3)
1528
+ sage: cube.is_neighborly()
1529
+ True
1530
+ sage: cube = polytopes.hypercube(4)
1531
+ sage: cube.is_neighborly()
1532
+ False
1533
+
1534
+ Cyclic polytopes are neighborly::
1535
+
1536
+ sage: all(polytopes.cyclic_polytope(i, i + 1 + j).is_neighborly() for i in range(5) for j in range(3))
1537
+ True
1538
+
1539
+ The neighborliness of a polyhedron equals floor of dimension half
1540
+ (or larger in case of a simplex) if and only if the polyhedron
1541
+ is neighborly::
1542
+
1543
+ sage: testpolys = [polytopes.cube(), polytopes.cyclic_polytope(6, 9), polytopes.simplex(6)]
1544
+ sage: [(P.neighborliness() >= P.dim() // 2) == P.is_neighborly() for P in testpolys]
1545
+ [True, True, True]
1546
+ """
1547
+ return self.combinatorial_polyhedron().is_neighborly()
1548
+
1549
+ def join_of_Vrep(self, *Vrepresentatives):
1550
+ r"""
1551
+ Return the smallest face that contains ``Vrepresentatives``.
1552
+
1553
+ INPUT:
1554
+
1555
+ - ``Vrepresentatives`` -- vertices/rays/lines of ``self`` or indices of such
1556
+
1557
+ OUTPUT: a :class:`~sage.geometry.polyhedron.face.PolyhedronFace`
1558
+
1559
+ .. NOTE::
1560
+
1561
+ In the case of unbounded polyhedra, the join of rays etc. may not be well-defined.
1562
+
1563
+ EXAMPLES::
1564
+
1565
+ sage: P = polytopes.permutahedron(5)
1566
+ sage: P.join_of_Vrep(1)
1567
+ A 0-dimensional face of a Polyhedron in ZZ^5 defined as the convex hull of 1 vertex
1568
+ sage: P.join_of_Vrep()
1569
+ A -1-dimensional face of a Polyhedron in ZZ^5
1570
+ sage: P.join_of_Vrep(0,12,13).ambient_V_indices()
1571
+ (0, 12, 13, 68)
1572
+
1573
+ The input is flexible::
1574
+
1575
+ sage: P.join_of_Vrep(2, P.vertices()[3], P.Vrepresentation(4))
1576
+ A 2-dimensional face of a Polyhedron in ZZ^5 defined as the convex hull of 6 vertices
1577
+
1578
+ ::
1579
+
1580
+ sage: P = polytopes.cube()
1581
+ sage: a, b = P.faces(0)[:2]
1582
+ sage: P.join_of_Vrep(a, b)
1583
+ A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices
1584
+
1585
+ In the case of an unbounded polyhedron, the join may not be well-defined::
1586
+
1587
+ sage: P = Polyhedron(vertices=[[1,0], [0,1]], rays=[[1,1]])
1588
+ sage: P.join_of_Vrep(0)
1589
+ A 0-dimensional face of a Polyhedron in QQ^2 defined as the convex hull of 1 vertex
1590
+ sage: P.join_of_Vrep(0,1)
1591
+ A 1-dimensional face of a Polyhedron in QQ^2 defined as the convex hull of 2 vertices
1592
+ sage: P.join_of_Vrep(0,2)
1593
+ A 1-dimensional face of a Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 ray
1594
+ sage: P.join_of_Vrep(1,2)
1595
+ A 1-dimensional face of a Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 ray
1596
+ sage: P.join_of_Vrep(2)
1597
+ Traceback (most recent call last):
1598
+ ...
1599
+ ValueError: the join is not well-defined
1600
+
1601
+ The ``Vrepresentatives`` must be of ``self``::
1602
+
1603
+ sage: P = polytopes.cube(backend='ppl')
1604
+ sage: Q = polytopes.cube(backend='field')
1605
+ sage: v = P.vertices()[0]
1606
+ sage: P.join_of_Vrep(v)
1607
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex
1608
+ sage: Q.join_of_Vrep(v)
1609
+ Traceback (most recent call last):
1610
+ ...
1611
+ ValueError: not a Vrepresentative of ``self``
1612
+ sage: f = P.faces(0)[0]
1613
+ sage: P.join_of_Vrep(v)
1614
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex
1615
+ sage: Q.join_of_Vrep(v)
1616
+ Traceback (most recent call last):
1617
+ ...
1618
+ ValueError: not a Vrepresentative of ``self``
1619
+
1620
+ TESTS:
1621
+
1622
+ ``least_common_superface_of_Vrep`` is an alias::
1623
+
1624
+ sage: P.least_common_superface_of_Vrep(v)
1625
+ A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex
1626
+ sage: P.least_common_superface_of_Vrep == P.join_of_Vrep
1627
+ True
1628
+
1629
+ Error message for invalid input::
1630
+
1631
+ sage: P.join_of_Vrep('foo')
1632
+ Traceback (most recent call last):
1633
+ ...
1634
+ ValueError: foo is not a Vrepresentative
1635
+ """
1636
+ from sage.geometry.polyhedron.representation import Vrepresentation
1637
+ from sage.geometry.polyhedron.face import PolyhedronFace
1638
+
1639
+ new_indices = [0]*len(Vrepresentatives)
1640
+ for i, v in enumerate(Vrepresentatives):
1641
+ if isinstance(v, PolyhedronFace) and v.dim() == 0:
1642
+ if v.polyhedron() is not self:
1643
+ raise ValueError("not a Vrepresentative of ``self``")
1644
+ new_indices[i] = v.ambient_V_indices()[0]
1645
+ elif v in ZZ:
1646
+ new_indices[i] = v
1647
+ elif isinstance(v, Vrepresentation):
1648
+ if v.polyhedron() is not self:
1649
+ raise ValueError("not a Vrepresentative of ``self``")
1650
+ new_indices[i] = v.index()
1651
+ else:
1652
+ raise ValueError("{} is not a Vrepresentative".format(v))
1653
+
1654
+ return self.face_generator().join_of_Vrep(*new_indices)
1655
+
1656
+ least_common_superface_of_Vrep = join_of_Vrep
1657
+
1658
+ def meet_of_Hrep(self, *Hrepresentatives):
1659
+ r"""
1660
+ Return the largest face that is contained in ``Hrepresentatives``.
1661
+
1662
+ INPUT:
1663
+
1664
+ - ``Hrepresentatives`` -- facets or indices of Hrepresentatives;
1665
+ the indices are assumed to be the indices of the
1666
+ :meth:`~sage.geometry.polyhedron.base0.Polyhedron_base0.Hrepresentation`
1667
+
1668
+ OUTPUT: a :class:`~sage.geometry.polyhedron.face.PolyhedronFace`
1669
+
1670
+ EXAMPLES::
1671
+
1672
+ sage: P = polytopes.permutahedron(5)
1673
+ sage: P.meet_of_Hrep()
1674
+ A 4-dimensional face of a Polyhedron in ZZ^5 defined as the convex hull of 120 vertices
1675
+ sage: P.meet_of_Hrep(1)
1676
+ A 3-dimensional face of a Polyhedron in ZZ^5 defined as the convex hull of 24 vertices
1677
+ sage: P.meet_of_Hrep(4)
1678
+ A 3-dimensional face of a Polyhedron in ZZ^5 defined as the convex hull of 12 vertices
1679
+ sage: P.meet_of_Hrep(1,3,7)
1680
+ A 1-dimensional face of a Polyhedron in ZZ^5 defined as the convex hull of 2 vertices
1681
+ sage: P.meet_of_Hrep(1,3,7).ambient_H_indices()
1682
+ (0, 1, 3, 7)
1683
+
1684
+ The indices are the indices of the
1685
+ :meth:`~sage.geometry.polyhedron.base0.Polyhedron_base0.Hrepresentation`.
1686
+ ``0`` corresponds to an equation and is ignored::
1687
+
1688
+ sage: P.meet_of_Hrep(0)
1689
+ A 4-dimensional face of a Polyhedron in ZZ^5 defined as the convex hull of 120 vertices
1690
+
1691
+ The input is flexible::
1692
+
1693
+ sage: P.meet_of_Hrep(P.facets()[-1], P.inequalities()[2], 7)
1694
+ A 1-dimensional face of a Polyhedron in ZZ^5 defined as the convex hull of 2 vertices
1695
+
1696
+ The ``Hrepresentatives`` must belong to ``self``::
1697
+
1698
+ sage: P = polytopes.cube(backend='ppl')
1699
+ sage: Q = polytopes.cube(backend='field')
1700
+ sage: f = P.facets()[0]
1701
+ sage: P.meet_of_Hrep(f)
1702
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices
1703
+ sage: Q.meet_of_Hrep(f)
1704
+ Traceback (most recent call last):
1705
+ ...
1706
+ ValueError: not a facet of ``self``
1707
+ sage: f = P.inequalities()[0]
1708
+ sage: P.meet_of_Hrep(f)
1709
+ A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices
1710
+ sage: Q.meet_of_Hrep(f)
1711
+ Traceback (most recent call last):
1712
+ ...
1713
+ ValueError: not a facet of ``self``
1714
+
1715
+ TESTS:
1716
+
1717
+ Equations are not considered by the combinatorial polyhedron.
1718
+ We check that the index corresponds to the
1719
+ :meth:`~sage.geometry.polyhedron.base0.Polyhedron_base0.Hrepresentation` index::
1720
+
1721
+ sage: P = polytopes.permutahedron(3, backend='field')
1722
+ sage: P.Hrepresentation()
1723
+ (An inequality (0, 0, 1) x - 1 >= 0,
1724
+ An inequality (0, 1, 0) x - 1 >= 0,
1725
+ An inequality (0, 1, 1) x - 3 >= 0,
1726
+ An inequality (1, 0, 0) x - 1 >= 0,
1727
+ An inequality (1, 0, 1) x - 3 >= 0,
1728
+ An inequality (1, 1, 0) x - 3 >= 0,
1729
+ An equation (1, 1, 1) x - 6 == 0)
1730
+ sage: P.meet_of_Hrep(0).ambient_Hrepresentation()
1731
+ (An inequality (0, 0, 1) x - 1 >= 0, An equation (1, 1, 1) x - 6 == 0)
1732
+
1733
+ sage: P = polytopes.permutahedron(3, backend='ppl')
1734
+ sage: P.Hrepresentation()
1735
+ (An equation (1, 1, 1) x - 6 == 0,
1736
+ An inequality (1, 1, 0) x - 3 >= 0,
1737
+ An inequality (-1, -1, 0) x + 5 >= 0,
1738
+ An inequality (0, 1, 0) x - 1 >= 0,
1739
+ An inequality (-1, 0, 0) x + 3 >= 0,
1740
+ An inequality (1, 0, 0) x - 1 >= 0,
1741
+ An inequality (0, -1, 0) x + 3 >= 0)
1742
+ sage: P.meet_of_Hrep(1).ambient_Hrepresentation()
1743
+ (An equation (1, 1, 1) x - 6 == 0, An inequality (1, 1, 0) x - 3 >= 0)
1744
+
1745
+ ``greatest_common_subface_of_Hrep`` is an alias::
1746
+
1747
+ sage: P.greatest_common_subface_of_Hrep(1).ambient_Hrepresentation()
1748
+ (An equation (1, 1, 1) x - 6 == 0, An inequality (1, 1, 0) x - 3 >= 0)
1749
+ sage: P.greatest_common_subface_of_Hrep == P.meet_of_Hrep
1750
+ True
1751
+
1752
+ Error message for invalid input::
1753
+
1754
+ sage: P.meet_of_Hrep('foo')
1755
+ Traceback (most recent call last):
1756
+ ...
1757
+ ValueError: foo is not a Hrepresentative
1758
+ """
1759
+ from sage.geometry.polyhedron.representation import Inequality, Equation
1760
+ from sage.geometry.polyhedron.face import PolyhedronFace
1761
+
1762
+ # Equations are ignored by combinatorial polyhedron for indexing.
1763
+ offset = 0
1764
+ if self.n_equations() and self.Hrepresentation(0).is_equation():
1765
+ offset = self.n_equations()
1766
+
1767
+ new_indices = []
1768
+ for i, facet in enumerate(Hrepresentatives):
1769
+ if isinstance(facet, PolyhedronFace) and facet.dim() + 1 == self.dim():
1770
+ if facet.polyhedron() is not self:
1771
+ raise ValueError("not a facet of ``self``")
1772
+ H_indices = facet.ambient_H_indices()
1773
+ facet = H_indices[0] if H_indices[0] >= offset else H_indices[-1]
1774
+
1775
+ if facet in ZZ and facet >= offset:
1776
+ # Note that ``CombinatorialPolyhedron`` ignores indices of equations
1777
+ # and has equations last.
1778
+ new_indices.append(facet - offset)
1779
+ elif isinstance(facet, Inequality):
1780
+ if facet.polyhedron() is not self:
1781
+ raise ValueError("not a facet of ``self``")
1782
+ new_indices.append(facet.index() - offset)
1783
+ elif isinstance(facet, Equation):
1784
+ # Ignore equations.
1785
+ continue
1786
+ elif facet in ZZ and 0 <= facet < offset:
1787
+ # Ignore equations.
1788
+ continue
1789
+ else:
1790
+ raise ValueError("{} is not a Hrepresentative".format(facet))
1791
+
1792
+ return self.face_generator().meet_of_Hrep(*new_indices)
1793
+
1794
+ greatest_common_subface_of_Hrep = meet_of_Hrep
1795
+
1796
+ def _test_combinatorial_face_as_combinatorial_polyhedron(self, tester=None, **options):
1797
+ """
1798
+ Run tests on obtaining the combinatorial face as combinatorial polyhedron.
1799
+
1800
+ TESTS::
1801
+
1802
+ sage: polytopes.cross_polytope(3)._test_combinatorial_face_as_combinatorial_polyhedron()
1803
+ """
1804
+ if not self.is_compact():
1805
+ return
1806
+ if self.dim() > 7 or self.n_vertices() > 100 or self.n_facets() > 100:
1807
+ # Avoid very long tests.
1808
+ return
1809
+ if self.dim() < 1:
1810
+ # Avoid trivial cases.
1811
+ return
1812
+
1813
+ from sage.misc.prandom import random
1814
+
1815
+ if tester is None:
1816
+ tester = self._tester(**options)
1817
+
1818
+ it = self.face_generator()
1819
+ _ = next(it), next(it) # get rid of non_proper faces
1820
+ C1 = self.combinatorial_polyhedron()
1821
+ it1 = C1.face_iter()
1822
+ C2 = C1.dual()
1823
+ algorithm = 'primal' if it1.dual else 'dual'
1824
+ it2 = C2.face_iter(algorithm=algorithm)
1825
+
1826
+ for f in it:
1827
+ f1 = next(it1)
1828
+ f2 = next(it2)
1829
+ if random() < 0.95:
1830
+ # Only test a random 5 percent of the faces.
1831
+ continue
1832
+
1833
+ P = f.as_polyhedron()
1834
+ D1 = f1.as_combinatorial_polyhedron()
1835
+ D2 = f2.as_combinatorial_polyhedron(quotient=True).dual()
1836
+ D1._test_bitsets(tester, **options)
1837
+ D2._test_bitsets(tester, **options)
1838
+ try:
1839
+ import sage.graphs.graph
1840
+ assert sage.graphs.graph # to muffle pyflakes
1841
+ except ImportError:
1842
+ pass
1843
+ else:
1844
+ tester.assertTrue(P.combinatorial_polyhedron().vertex_facet_graph().is_isomorphic(D1.vertex_facet_graph()))
1845
+ tester.assertTrue(P.combinatorial_polyhedron().vertex_facet_graph().is_isomorphic(D2.vertex_facet_graph()))