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,1279 @@
1
+ # sage_setup: distribution = sagemath-polyhedra
2
+ r"""
3
+ Parents for Polyhedra
4
+ """
5
+
6
+ # ****************************************************************************
7
+ # Copyright (C) 2014 Volker Braun <vbraun.name@gmail.com>
8
+ #
9
+ # Distributed under the terms of the GNU General Public License (GPL)
10
+ # https://www.gnu.org/licenses/
11
+ # *****************************************************************************
12
+
13
+ import sage.geometry.abc
14
+
15
+ from sage.structure.parent import Parent
16
+ from sage.structure.element import get_coercion_model
17
+ from sage.structure.unique_representation import UniqueRepresentation
18
+ from sage.modules.free_module import FreeModule, FreeModule_generic
19
+ from sage.misc.cachefunc import cached_method, cached_function
20
+ from sage.misc.lazy_import import lazy_import
21
+ import sage.rings.abc
22
+ from sage.rings.integer_ring import ZZ
23
+ from sage.rings.rational_field import QQ
24
+
25
+ try:
26
+ from sage.rings.real_double import RDF
27
+ except ImportError:
28
+ RDF = None
29
+
30
+ from sage.categories.fields import Fields
31
+ from sage.categories.rings import Rings
32
+ from sage.categories.modules import Modules
33
+ from .representation import Inequality, Equation, Vertex, Ray, Line
34
+
35
+
36
+ def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, *,
37
+ ambient_space=None, base_ring=None):
38
+ r"""
39
+ Construct a suitable parent class for polyhedra.
40
+
41
+ INPUT:
42
+
43
+ - ``base_ring`` -- a ring; currently there are backends for `\ZZ`,
44
+ `\QQ`, and `\RDF`
45
+
46
+ - ``ambient_dim`` -- integer; the ambient space dimension
47
+
48
+ - ``ambient_space`` -- a free module
49
+
50
+ - ``backend`` -- string. The name of the backend for computations. There are
51
+ several backends implemented:
52
+
53
+ * ``backend="ppl"`` uses the Parma Polyhedra Library
54
+
55
+ * ``backend="cdd"`` uses CDD
56
+
57
+ * ``backend="normaliz"`` uses normaliz
58
+
59
+ * ``backend="polymake"`` uses polymake
60
+
61
+ * ``backend="field"`` a generic Sage implementation
62
+
63
+ OUTPUT:
64
+
65
+ A parent class for polyhedra over the given base ring if the
66
+ backend supports it. If not, the parent base ring can be larger
67
+ (for example, `\QQ` instead of `\ZZ`). If there is no
68
+ implementation at all, a :exc:`ValueError` is raised.
69
+
70
+ EXAMPLES::
71
+
72
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
73
+ sage: Polyhedra(AA, 3) # needs sage.rings.number_field
74
+ Polyhedra in AA^3
75
+ sage: Polyhedra(ZZ, 3)
76
+ Polyhedra in ZZ^3
77
+ sage: type(_)
78
+ <class 'sage.geometry.polyhedron.parent.Polyhedra_ZZ_ppl_with_category'>
79
+ sage: Polyhedra(QQ, 3, backend='cdd')
80
+ Polyhedra in QQ^3
81
+ sage: type(_)
82
+ <class 'sage.geometry.polyhedron.parent.Polyhedra_QQ_cdd_with_category'>
83
+
84
+ CDD does not support integer polytopes directly::
85
+
86
+ sage: Polyhedra(ZZ, 3, backend='cdd')
87
+ Polyhedra in QQ^3
88
+
89
+ Using a more general form of the constructor::
90
+
91
+ sage: V = VectorSpace(QQ, 3)
92
+ sage: Polyhedra(V) is Polyhedra(QQ, 3)
93
+ True
94
+ sage: Polyhedra(V, backend='field') is Polyhedra(QQ, 3, 'field')
95
+ True
96
+ sage: Polyhedra(backend='field', ambient_space=V) is Polyhedra(QQ, 3, 'field')
97
+ True
98
+
99
+ sage: M = FreeModule(ZZ, 2)
100
+ sage: Polyhedra(M, backend='ppl') is Polyhedra(ZZ, 2, 'ppl')
101
+ True
102
+
103
+ TESTS::
104
+
105
+ sage: Polyhedra(RR, 3, backend='field') # needs sage.rings.real_mpfr
106
+ Traceback (most recent call last):
107
+ ...
108
+ ValueError: the 'field' backend for polyhedron cannot be used with non-exact fields
109
+ sage: Polyhedra(RR, 3) # needs sage.rings.real_mpfr
110
+ Traceback (most recent call last):
111
+ ...
112
+ ValueError: no default backend for computations with Real Field with 53 bits of precision
113
+ sage: Polyhedra(QQ[I], 2) # needs sage.rings.number_field
114
+ Traceback (most recent call last):
115
+ ...
116
+ ValueError: invalid base ring: Number Field in I
117
+ with defining polynomial x^2 + 1 with I = 1*I
118
+ cannot be coerced to a real field
119
+ sage: Polyhedra(AA, 3, backend='polymake') # optional - jupymake # needs sage.rings.number_field
120
+ Traceback (most recent call last):
121
+ ...
122
+ ValueError: the 'polymake' backend for polyhedron cannot be used with Algebraic Real Field
123
+
124
+ sage: Polyhedra(QQ, 2, backend='normaliz')
125
+ Polyhedra in QQ^2
126
+ sage: Polyhedra(SR, 2, backend='normaliz') # optional - pynormaliz # needs sage.symbolic
127
+ Polyhedra in (Symbolic Ring)^2
128
+ sage: SCR = SR.subring(no_variables=True) # needs sage.symbolic
129
+ sage: Polyhedra(SCR, 2, backend='normaliz') # optional - pynormaliz # needs sage.symbolic
130
+ Polyhedra in (Symbolic Constants Subring)^2
131
+
132
+ sage: Polyhedra(SCR, 2, backend='number_field') # needs sage.symbolic
133
+ Polyhedra in (Symbolic Constants Subring)^2
134
+ """
135
+ if ambient_space_or_base_ring is not None:
136
+ if ambient_space_or_base_ring in Rings():
137
+ base_ring = ambient_space_or_base_ring
138
+ else:
139
+ ambient_space = ambient_space_or_base_ring
140
+ if ambient_space is not None:
141
+ if ambient_space not in Modules:
142
+ # There is no category of free modules, unfortunately
143
+ # (see https://github.com/sagemath/sage/issues/30164)...
144
+ raise ValueError('ambient_space must be a free module')
145
+ if base_ring is None:
146
+ base_ring = ambient_space.base_ring()
147
+ if ambient_dim is None:
148
+ try:
149
+ ambient_dim = ambient_space.rank()
150
+ except AttributeError:
151
+ # ... so we test whether it is free using the existence of
152
+ # a rank method
153
+ raise ValueError('ambient_space must be a free module')
154
+ if ambient_space is not FreeModule(base_ring, ambient_dim):
155
+ raise NotImplementedError('ambient_space must be a standard free module')
156
+ if backend is None:
157
+ if base_ring is ZZ or base_ring is QQ:
158
+ backend = 'ppl'
159
+ elif base_ring is RDF:
160
+ backend = 'cdd'
161
+ elif base_ring.is_exact():
162
+ # TODO: find a more robust way of checking that the coefficients are indeed
163
+ # real numbers
164
+ if not RDF.has_coerce_map_from(base_ring):
165
+ raise ValueError("invalid base ring: {} cannot be coerced to a real field".format(base_ring))
166
+ backend = 'field'
167
+ else:
168
+ raise ValueError("no default backend for computations with {}".format(base_ring))
169
+
170
+ if backend == 'ppl' and base_ring is QQ:
171
+ return Polyhedra_QQ_ppl(base_ring, ambient_dim, backend)
172
+ elif backend == 'ppl' and base_ring is ZZ:
173
+ return Polyhedra_ZZ_ppl(base_ring, ambient_dim, backend)
174
+ elif backend == 'normaliz' and base_ring is QQ:
175
+ return Polyhedra_QQ_normaliz(base_ring, ambient_dim, backend)
176
+ elif backend == 'normaliz' and base_ring is ZZ:
177
+ return Polyhedra_ZZ_normaliz(base_ring, ambient_dim, backend)
178
+ elif backend == 'normaliz' and (isinstance(base_ring, sage.rings.abc.SymbolicRing) or base_ring.is_exact()):
179
+ return Polyhedra_normaliz(base_ring, ambient_dim, backend)
180
+ elif backend == 'cdd' and base_ring in (ZZ, QQ):
181
+ return Polyhedra_QQ_cdd(QQ, ambient_dim, backend)
182
+ elif backend == 'cdd' and base_ring is RDF:
183
+ return Polyhedra_RDF_cdd(RDF, ambient_dim, backend)
184
+ elif backend == 'polymake':
185
+ base_field = base_ring.fraction_field()
186
+ try:
187
+ from sage.interfaces.polymake import polymake, PolymakeElement
188
+ polymake_base_field = polymake(base_field)
189
+ assert isinstance(polymake_base_field, PolymakeElement) # to muffle pyflakes
190
+ except TypeError:
191
+ raise ValueError(f"the 'polymake' backend for polyhedron cannot be used with {base_field}")
192
+ return Polyhedra_polymake(base_field, ambient_dim, backend)
193
+ elif backend == 'number_field':
194
+ return Polyhedra_number_field(base_ring.fraction_field(), ambient_dim, backend)
195
+ elif backend == 'field':
196
+ if not base_ring.is_exact():
197
+ raise ValueError("the 'field' backend for polyhedron cannot be used with non-exact fields")
198
+ return Polyhedra_field(base_ring.fraction_field(), ambient_dim, backend)
199
+ else:
200
+ raise ValueError('No such backend (=' + str(backend) +
201
+ ') implemented for given basering (=' + str(base_ring) + ').')
202
+
203
+
204
+ class Polyhedra_base(UniqueRepresentation, Parent):
205
+ r"""
206
+ Polyhedra in a fixed ambient space.
207
+
208
+ INPUT:
209
+
210
+ - ``base_ring`` -- either ``ZZ``, ``QQ``, or ``RDF``; the base
211
+ ring of the ambient module/vector space
212
+
213
+ - ``ambient_dim`` -- integer; the ambient space dimension
214
+
215
+ - ``backend`` -- string; the name of the backend for computations. There are
216
+ several backends implemented:
217
+
218
+ * ``backend="ppl"`` uses the Parma Polyhedra Library
219
+
220
+ * ``backend="cdd"`` uses CDD
221
+
222
+ * ``backend="normaliz"`` uses normaliz
223
+
224
+ * ``backend="polymake"`` uses polymake
225
+
226
+ * ``backend="field"`` a generic Sage implementation
227
+
228
+ EXAMPLES::
229
+
230
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
231
+ sage: Polyhedra(ZZ, 3)
232
+ Polyhedra in ZZ^3
233
+ """
234
+ def __init__(self, base_ring, ambient_dim, backend):
235
+ """
236
+ The Python constructor.
237
+
238
+ EXAMPLES::
239
+
240
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
241
+ sage: Polyhedra(QQ, 3)
242
+ Polyhedra in QQ^3
243
+
244
+ TESTS::
245
+
246
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
247
+ sage: P = Polyhedra(QQ, 3)
248
+ sage: TestSuite(P).run()
249
+ sage: P = Polyhedra(QQ, 0)
250
+ sage: TestSuite(P).run()
251
+ """
252
+ self._backend = backend
253
+ self._ambient_dim = ambient_dim
254
+ from sage.categories.polyhedra import PolyhedralSets
255
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
256
+ category = PolyhedralSets(base_ring)
257
+ if ambient_dim == 0:
258
+ category = category & FiniteEnumeratedSets()
259
+ else:
260
+ category = category.Infinite()
261
+
262
+ Parent.__init__(self, base=base_ring, category=category)
263
+ self._Inequality_pool = []
264
+ self._Equation_pool = []
265
+ self._Vertex_pool = []
266
+ self._Ray_pool = []
267
+ self._Line_pool = []
268
+
269
+ def list(self):
270
+ """
271
+ Return the two polyhedra in ambient dimension 0, raise an error otherwise.
272
+
273
+ EXAMPLES::
274
+
275
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
276
+ sage: P = Polyhedra(QQ, 3)
277
+ sage: P.cardinality()
278
+ +Infinity
279
+
280
+ sage: # needs sage.rings.number_field
281
+ sage: P = Polyhedra(AA, 0)
282
+ sage: P.category()
283
+ Category of finite enumerated polyhedral sets over Algebraic Real Field
284
+ sage: P.list()
285
+ [The empty polyhedron in AA^0,
286
+ A 0-dimensional polyhedron in AA^0 defined as the convex hull of 1 vertex]
287
+ sage: P.cardinality()
288
+ 2
289
+ """
290
+ if self.ambient_dim():
291
+ raise NotImplementedError
292
+ return [self.empty(), self.universe()]
293
+
294
+ def recycle(self, polyhedron):
295
+ """
296
+ Recycle the H/V-representation objects of a polyhedron.
297
+
298
+ This speeds up creation of new polyhedra by reusing
299
+ objects. After recycling a polyhedron object, it is not in a
300
+ consistent state any more and neither the polyhedron nor its
301
+ H/V-representation objects may be used any more.
302
+
303
+ INPUT:
304
+
305
+ - ``polyhedron`` -- a polyhedron whose parent is ``self``
306
+
307
+ EXAMPLES::
308
+
309
+ sage: p = Polyhedron([(0,0),(1,0),(0,1)])
310
+ sage: p.parent().recycle(p)
311
+
312
+ TESTS::
313
+
314
+ sage: p = Polyhedron([(0,0),(1,0),(0,1)])
315
+ sage: n = len(p.parent()._Vertex_pool)
316
+ sage: p._delete()
317
+ sage: len(p.parent()._Vertex_pool) - n
318
+ 3
319
+ """
320
+ if self is not polyhedron.parent():
321
+ raise TypeError('The polyhedron has the wrong parent class.')
322
+ self._Inequality_pool.extend(polyhedron.inequalities())
323
+ self._Equation_pool.extend(polyhedron.equations())
324
+ self._Vertex_pool.extend(polyhedron.vertices())
325
+ self._Ray_pool.extend(polyhedron.rays())
326
+ self._Line_pool.extend(polyhedron.lines())
327
+ for Hrep in polyhedron.Hrep_generator():
328
+ Hrep._polyhedron = None
329
+ for Vrep in polyhedron.Vrep_generator():
330
+ Vrep._polyhedron = None
331
+ polyhedron._Hrepresentation = None
332
+ polyhedron._Vrepresentation = None
333
+ if polyhedron.is_mutable():
334
+ polyhedron._dependent_objects = []
335
+
336
+ def ambient_dim(self):
337
+ r"""
338
+ Return the dimension of the ambient space.
339
+
340
+ EXAMPLES::
341
+
342
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
343
+ sage: Polyhedra(QQ, 3).ambient_dim()
344
+ 3
345
+ """
346
+ return self._ambient_dim
347
+
348
+ def backend(self):
349
+ r"""
350
+ Return the backend.
351
+
352
+ EXAMPLES::
353
+
354
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
355
+ sage: Polyhedra(QQ, 3).backend()
356
+ 'ppl'
357
+ """
358
+ return self._backend
359
+
360
+ @cached_method
361
+ def an_element(self):
362
+ r"""
363
+ Return a Polyhedron.
364
+
365
+ EXAMPLES::
366
+
367
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
368
+ sage: Polyhedra(QQ, 4).an_element()
369
+ A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices
370
+ """
371
+ zero = self.base_ring().zero()
372
+ one = self.base_ring().one()
373
+ p = [zero] * self.ambient_dim()
374
+ points = [p]
375
+ for i in range(self.ambient_dim()):
376
+ p = [zero] * self.ambient_dim()
377
+ p[i] = one
378
+ points.append(p)
379
+ return self.element_class(self, [points, [], []], None)
380
+
381
+ @cached_method
382
+ def some_elements(self):
383
+ r"""
384
+ Return a list of some elements of the semigroup.
385
+
386
+ EXAMPLES::
387
+
388
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
389
+ sage: Polyhedra(QQ, 4).some_elements()
390
+ [A 3-dimensional polyhedron in QQ^4
391
+ defined as the convex hull of 4 vertices,
392
+ A 4-dimensional polyhedron in QQ^4
393
+ defined as the convex hull of 1 vertex and 4 rays,
394
+ A 2-dimensional polyhedron in QQ^4
395
+ defined as the convex hull of 2 vertices and 1 ray,
396
+ The empty polyhedron in QQ^4]
397
+ sage: Polyhedra(ZZ, 0).some_elements()
398
+ [The empty polyhedron in ZZ^0,
399
+ A 0-dimensional polyhedron in ZZ^0 defined as the convex hull of 1 vertex]
400
+ """
401
+ if self.ambient_dim() == 0:
402
+ return [
403
+ self.element_class(self, None, None),
404
+ self.element_class(self, None, [[], []])]
405
+ points = []
406
+ R = self.base_ring()
407
+ for i in range(self.ambient_dim() + 5):
408
+ points.append([R(i*j ^ 2) for j in range(self.ambient_dim())])
409
+ return [
410
+ self.element_class(self, [points[0:self.ambient_dim() + 1], [], []], None),
411
+ self.element_class(self, [points[0:1], points[1:self.ambient_dim() + 1], []], None),
412
+ self.element_class(self, [points[0:3], points[4:5], []], None),
413
+ self.element_class(self, None, None)]
414
+
415
+ @cached_method
416
+ def zero(self):
417
+ r"""
418
+ Return the polyhedron consisting of the origin, which is the
419
+ neutral element for Minkowski addition.
420
+
421
+ EXAMPLES::
422
+
423
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
424
+ sage: p = Polyhedra(QQ, 4).zero(); p
425
+ A 0-dimensional polyhedron in QQ^4 defined as the convex hull of 1 vertex
426
+ sage: p + p == p
427
+ True
428
+ """
429
+ Vrep = [[[self.base_ring().zero()] * self.ambient_dim()], [], []]
430
+ return self.element_class(self, Vrep, None)
431
+
432
+ def empty(self):
433
+ """
434
+ Return the empty polyhedron.
435
+
436
+ EXAMPLES::
437
+
438
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
439
+ sage: P = Polyhedra(QQ, 4)
440
+ sage: P.empty()
441
+ The empty polyhedron in QQ^4
442
+ sage: P.empty().is_empty()
443
+ True
444
+ """
445
+ return self(None, None)
446
+
447
+ def universe(self):
448
+ """
449
+ Return the entire ambient space as polyhedron.
450
+
451
+ EXAMPLES::
452
+
453
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
454
+ sage: P = Polyhedra(QQ, 4)
455
+ sage: P.universe()
456
+ A 4-dimensional polyhedron in QQ^4 defined as
457
+ the convex hull of 1 vertex and 4 lines
458
+ sage: P.universe().is_universe()
459
+ True
460
+ """
461
+ R = self.base_ring()
462
+ return self(None, [[[R.one()] + [R.zero()] * self.ambient_dim()], []], convert=True)
463
+
464
+ @cached_method
465
+ def Vrepresentation_space(self):
466
+ r"""
467
+ Return the ambient vector space.
468
+
469
+ This is the vector space or module containing the
470
+ Vrepresentation vectors.
471
+
472
+ OUTPUT: a free module over the base ring of dimension :meth:`ambient_dim`
473
+
474
+ EXAMPLES::
475
+
476
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
477
+ sage: Polyhedra(QQ, 4).Vrepresentation_space()
478
+ Vector space of dimension 4 over Rational Field
479
+ sage: Polyhedra(QQ, 4).ambient_space()
480
+ Vector space of dimension 4 over Rational Field
481
+ """
482
+ if self.base_ring() in Fields():
483
+ from sage.modules.free_module import VectorSpace
484
+ return VectorSpace(self.base_ring(), self.ambient_dim())
485
+ from sage.modules.free_module import FreeModule
486
+ return FreeModule(self.base_ring(), self.ambient_dim())
487
+
488
+ ambient_space = Vrepresentation_space
489
+
490
+ @cached_method
491
+ def Hrepresentation_space(self):
492
+ r"""
493
+ Return the linear space containing the H-representation vectors.
494
+
495
+ OUTPUT: a free module over the base ring of dimension :meth:`ambient_dim` + 1
496
+
497
+ EXAMPLES::
498
+
499
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
500
+ sage: Polyhedra(ZZ, 2).Hrepresentation_space()
501
+ Ambient free module of rank 3 over the principal ideal domain Integer Ring
502
+ """
503
+ if self.base_ring() in Fields():
504
+ from sage.modules.free_module import VectorSpace
505
+ return VectorSpace(self.base_ring(), self.ambient_dim() + 1)
506
+ from sage.modules.free_module import FreeModule
507
+ return FreeModule(self.base_ring(), self.ambient_dim() + 1)
508
+
509
+ def _repr_base_ring(self):
510
+ """
511
+ Return an abbreviated string representation of the base ring.
512
+
513
+ EXAMPLES::
514
+
515
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
516
+ sage: Polyhedra(QQ, 3)._repr_base_ring()
517
+ 'QQ'
518
+ sage: x = polygen(ZZ, 'x')
519
+ sage: K.<sqrt3> = NumberField(x^2 - 3, embedding=AA(3).sqrt()) # needs sage.rings.number_field
520
+ sage: Polyhedra(K, 4)._repr_base_ring() # needs sage.rings.number_field
521
+ '(Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)'
522
+ """
523
+ if self.base_ring() is ZZ:
524
+ return 'ZZ'
525
+ if self.base_ring() is QQ:
526
+ return 'QQ'
527
+ if self.base_ring() is RDF:
528
+ return 'RDF'
529
+ try:
530
+ from sage.rings.qqbar import AA
531
+ except ImportError:
532
+ pass
533
+ else:
534
+ if self.base_ring() is AA:
535
+ return 'AA'
536
+ return f'({self.base_ring()})'
537
+
538
+ def _repr_ambient_module(self) -> str:
539
+ """
540
+ Return an abbreviated string representation of the ambient
541
+ space.
542
+
543
+ OUTPUT: string
544
+
545
+ EXAMPLES::
546
+
547
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
548
+ sage: Polyhedra(QQ, 3)._repr_ambient_module()
549
+ 'QQ^3'
550
+ sage: x = polygen(ZZ, 'x')
551
+ sage: K.<sqrt3> = NumberField(x^2 - 3, embedding=AA(3).sqrt()) # needs sage.rings.number_field
552
+ sage: Polyhedra(K, 4)._repr_ambient_module() # needs sage.rings.number_field
553
+ '(Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)^4'
554
+ """
555
+ s = self._repr_base_ring()
556
+ s += '^' + repr(self.ambient_dim())
557
+ return s
558
+
559
+ def _repr_(self):
560
+ """
561
+ Return a string representation.
562
+
563
+ OUTPUT: string
564
+
565
+ EXAMPLES::
566
+
567
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
568
+ sage: Polyhedra(QQ, 3)
569
+ Polyhedra in QQ^3
570
+ sage: Polyhedra(QQ, 3)._repr_()
571
+ 'Polyhedra in QQ^3'
572
+ """
573
+ return 'Polyhedra in ' + self._repr_ambient_module()
574
+
575
+ def _element_constructor_(self, *args, **kwds):
576
+ """
577
+ The element (polyhedron) constructor.
578
+
579
+ INPUT:
580
+
581
+ - ``Vrep`` -- list ``[vertices, rays, lines]`` or ``None``
582
+
583
+ - ``Hrep`` -- list ``[ieqs, eqns]`` or ``None``
584
+
585
+ - ``convert`` -- boolean (default: ``True``); whether to convert the
586
+ coordinates into the base ring
587
+
588
+ - ``**kwds`` -- (optional) remaining keywords that are passed to the
589
+ polyhedron constructor
590
+
591
+ EXAMPLES::
592
+
593
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
594
+ sage: P = Polyhedra(QQ, 3)
595
+ sage: P._element_constructor_([[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0,0,1)], [], []], None)
596
+ A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
597
+ sage: P([[(0,0,0),(1,0,0),(0,1,0),(0,0,1)], [], []], None)
598
+ A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
599
+ sage: P(0)
600
+ A 0-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex
601
+
602
+ Check that :issue:`21270` is fixed::
603
+
604
+ sage: # needs sage.rings.number_field
605
+ sage: poly = polytopes.regular_polygon(7)
606
+ sage: lp, x = poly.to_linear_program(solver='InteractiveLP',
607
+ ....: return_variable=True)
608
+ sage: lp.set_objective(x[0] + x[1])
609
+ sage: b = lp.get_backend()
610
+ sage: P = b.interactive_lp_problem()
611
+ sage: p = P.plot() # needs sage.plot sage.symbolic
612
+
613
+ sage: Q = Polyhedron(ieqs=[[-499999, 1000000], [1499999, -1000000]])
614
+ sage: P = Polyhedron(ieqs=[[0, 1.0], [1.0, -1.0]], base_ring=RDF) # needs cddexec
615
+ sage: Q.intersection(P) # needs cddexec
616
+ A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices
617
+ sage: P.intersection(Q) # needs cddexec
618
+ A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices
619
+
620
+ The default is not to copy an object if the parent is ``self``::
621
+
622
+ sage: p = polytopes.cube(backend='field')
623
+ sage: P = p.parent()
624
+ sage: q = P._element_constructor_(p)
625
+ sage: q is p
626
+ True
627
+ sage: r = P._element_constructor_(p, copy=True)
628
+ sage: r is p
629
+ False
630
+
631
+ When the parent of the object is not ``self``, the default is not to copy::
632
+
633
+ sage: # needs sage.rings.number_field
634
+ sage: Q = P.base_extend(AA)
635
+ sage: q = Q._element_constructor_(p)
636
+ sage: q is p
637
+ False
638
+ sage: q = Q._element_constructor_(p, copy=False)
639
+ Traceback (most recent call last):
640
+ ...
641
+ ValueError: you need to make a copy when changing the parent
642
+
643
+ For mutable polyhedra either ``copy`` or ``mutable`` must be specified::
644
+
645
+ sage: p = Polyhedron(vertices=[[0, 1], [1, 0]], mutable=True)
646
+ sage: P = p.parent()
647
+ sage: q = P._element_constructor_(p)
648
+ Traceback (most recent call last):
649
+ ...
650
+ ValueError: must make a copy to obtain immutable object from mutable input
651
+ sage: q = P._element_constructor_(p, mutable=True)
652
+ sage: q is p
653
+ True
654
+ sage: r = P._element_constructor_(p, copy=True)
655
+ sage: r.is_mutable()
656
+ False
657
+ sage: r is p
658
+ False
659
+ """
660
+ nargs = len(args)
661
+ convert = kwds.pop('convert', True)
662
+
663
+ def convert_base_ring(lstlst):
664
+ return [[self.base_ring()(x) for x in lst] for lst in lstlst]
665
+
666
+ # renormalize before converting when going from QQ to RDF, see trac 21270
667
+ def convert_base_ring_Hrep(lstlst):
668
+ newlstlst = []
669
+ for lst in lstlst:
670
+ if all(c in QQ for c in lst):
671
+ m = max(abs(w) for w in lst)
672
+ if m == 0:
673
+ newlstlst.append(lst)
674
+ else:
675
+ newlstlst.append([q / m for q in lst])
676
+ else:
677
+ newlstlst.append(lst)
678
+ return convert_base_ring(newlstlst)
679
+ if nargs == 2:
680
+ Vrep, Hrep = args
681
+ if convert and Hrep:
682
+ if self.base_ring == RDF:
683
+ Hrep = [convert_base_ring_Hrep(_) for _ in Hrep]
684
+ else:
685
+ Hrep = [convert_base_ring(_) for _ in Hrep]
686
+ if convert and Vrep:
687
+ Vrep = [convert_base_ring(_) for _ in Vrep]
688
+ return self.element_class(self, Vrep, Hrep, **kwds)
689
+ if nargs == 1 and isinstance(args[0], sage.geometry.abc.Polyhedron):
690
+ copy = kwds.pop('copy', args[0].parent() is not self)
691
+ mutable = kwds.pop('mutable', False)
692
+
693
+ if not copy and args[0].parent() is not self:
694
+ raise ValueError("you need to make a copy when changing the parent")
695
+ if args[0].is_mutable() and not copy and not mutable:
696
+ raise ValueError("must make a copy to obtain immutable object from mutable input")
697
+ if not copy and mutable is args[0].is_mutable():
698
+ return args[0]
699
+
700
+ polyhedron = args[0]
701
+ return self._element_constructor_polyhedron(polyhedron, mutable=mutable, **kwds)
702
+ if nargs == 1 and args[0] == 0:
703
+ return self.zero()
704
+ raise ValueError('cannot convert to polyhedron object')
705
+
706
+ def _element_constructor_polyhedron(self, polyhedron, **kwds):
707
+ """
708
+ The element (polyhedron) constructor for the case of 1 argument, a polyhedron.
709
+
710
+ Set up the element using both representations,
711
+ if the backend can handle it.
712
+
713
+ Otherwise set up the element from Hrepresentation.
714
+
715
+ EXAMPLES::
716
+
717
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
718
+ sage: P = Polyhedra(QQ, 3, backend='cdd')
719
+ sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)])
720
+ sage: p
721
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
722
+ sage: P(p) # needs cddexec_gmp
723
+ A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
724
+
725
+ sage: P = Polyhedra(AA, 3, backend='field') # needs sage.rings.number_field
726
+ sage: vertices = [(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)]
727
+ sage: p = Polyhedron(vertices=vertices)
728
+ sage: P(p) # needs sage.rings.number_field
729
+ A 3-dimensional polyhedron in AA^3 defined as the convex hull of 4 vertices
730
+ """
731
+ Vrep = None
732
+ if hasattr(self.Element, '_init_from_Vrepresentation_and_Hrepresentation'):
733
+ Vrep = [polyhedron.vertex_generator(), polyhedron.ray_generator(),
734
+ polyhedron.line_generator()]
735
+ Hrep = [polyhedron.inequality_generator(), polyhedron.equation_generator()]
736
+ return self._element_constructor_(Vrep, Hrep, Vrep_minimal=True, Hrep_minimal=True, **kwds)
737
+
738
+ def base_extend(self, base_ring, backend=None, ambient_dim=None):
739
+ """
740
+ Return the base extended parent.
741
+
742
+ INPUT:
743
+
744
+ - ``base_ring``, ``backend`` -- see
745
+ :func:`~sage.geometry.polyhedron.constructor.Polyhedron`
746
+ - ``ambient_dim`` -- if not ``None`` change ambient dimension
747
+ accordingly
748
+
749
+ EXAMPLES::
750
+
751
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
752
+ sage: Polyhedra(ZZ, 3).base_extend(QQ)
753
+ Polyhedra in QQ^3
754
+ sage: Polyhedra(ZZ, 3).an_element().base_extend(QQ)
755
+ A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
756
+ sage: Polyhedra(QQ, 2).base_extend(ZZ)
757
+ Polyhedra in QQ^2
758
+
759
+ TESTS:
760
+
761
+ Test that :issue:`22575` is fixed::
762
+
763
+ sage: P = Polyhedra(ZZ,3).base_extend(QQ, backend='field')
764
+ sage: P.backend()
765
+ 'field'
766
+ """
767
+ if self.base_ring().has_coerce_map_from(base_ring):
768
+ new_ring = self.base_ring()
769
+ else:
770
+ new_ring = self._coerce_base_ring(base_ring)
771
+
772
+ return self.change_ring(new_ring, backend=backend, ambient_dim=ambient_dim)
773
+
774
+ def change_ring(self, base_ring, backend=None, ambient_dim=None):
775
+ """
776
+ Return the parent with the new base ring.
777
+
778
+ INPUT:
779
+
780
+ - ``base_ring``, ``backend`` -- see
781
+ :func:`~sage.geometry.polyhedron.constructor.Polyhedron`
782
+ - ``ambient_dim`` -- if not ``None`` change ambient dimension
783
+ accordingly
784
+
785
+ EXAMPLES::
786
+
787
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
788
+ sage: Polyhedra(ZZ, 3).change_ring(QQ)
789
+ Polyhedra in QQ^3
790
+ sage: Polyhedra(ZZ, 3).an_element().change_ring(QQ)
791
+ A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
792
+
793
+ sage: Polyhedra(RDF, 3).change_ring(QQ).backend()
794
+ 'cdd'
795
+ sage: Polyhedra(QQ, 3).change_ring(ZZ, ambient_dim=4)
796
+ Polyhedra in ZZ^4
797
+ sage: Polyhedra(QQ, 3, backend='cdd').change_ring(QQ, ambient_dim=4).backend()
798
+ 'cdd'
799
+ """
800
+ if ambient_dim is None:
801
+ ambient_dim = self.ambient_dim()
802
+
803
+ if base_ring == self.base_ring() and \
804
+ ambient_dim == self.ambient_dim() and \
805
+ (backend is None or backend == self.backend()):
806
+ return self
807
+
808
+ # if not specified try the same backend
809
+ if backend is None and does_backend_handle_base_ring(base_ring, self.backend()):
810
+ return Polyhedra(base_ring, ambient_dim, backend=self.backend())
811
+
812
+ return Polyhedra(base_ring, ambient_dim, backend=backend)
813
+
814
+ def _coerce_base_ring(self, other):
815
+ r"""
816
+ Return the common base ring for both ``self`` and ``other``.
817
+
818
+ This method is not part of the coercion framework, but only a
819
+ convenience function for :class:`Polyhedra_base`.
820
+
821
+ INPUT:
822
+
823
+ - ``other`` -- must be either:
824
+
825
+ * another ``Polyhedron`` object
826
+
827
+ * `\ZZ`, `\QQ`, `RDF`, or a ring that can be coerced into them.
828
+
829
+ * a constant that can be coerced to `\ZZ`, `\QQ`, or `RDF`.
830
+
831
+ OUTPUT:
832
+
833
+ Either `\ZZ`, `\QQ`, or `RDF`. Raises :exc:`TypeError` if
834
+ ``other`` is not a suitable input.
835
+
836
+ .. NOTE::
837
+
838
+ "Real" numbers in sage are not necessarily elements of
839
+ ``RDF``. For example, the literal `1.0` is not.
840
+
841
+ EXAMPLES::
842
+
843
+ sage: triangle_QQ = Polyhedron(vertices=[[1,0],[0,1],[1,1]], base_ring=QQ).parent()
844
+ sage: triangle_RDF = Polyhedron(vertices=[[1,0],[0,1],[1,1]], base_ring=RDF).parent() # needs cddexec
845
+ sage: triangle_QQ._coerce_base_ring(QQ)
846
+ Rational Field
847
+ sage: triangle_QQ._coerce_base_ring(triangle_RDF) # needs cddexec
848
+ Real Double Field
849
+ sage: triangle_RDF._coerce_base_ring(triangle_QQ) # needs cddexec
850
+ Real Double Field
851
+ sage: triangle_QQ._coerce_base_ring(RDF) # needs cddexec
852
+ Real Double Field
853
+ sage: triangle_QQ._coerce_base_ring(ZZ)
854
+ Rational Field
855
+ sage: triangle_QQ._coerce_base_ring(1/2)
856
+ Rational Field
857
+ sage: triangle_QQ._coerce_base_ring(0.5) # needs cddexec
858
+ Real Double Field
859
+
860
+ TESTS:
861
+
862
+ Test that :issue:`28770` is fixed::
863
+
864
+ sage: z = QQ['z'].0
865
+ sage: K = NumberField(z^2 - 2, 's') # needs sage.rings.number_field
866
+ sage: triangle_QQ._coerce_base_ring(K) # needs sage.rings.number_field
867
+ Number Field in s with defining polynomial z^2 - 2
868
+ sage: triangle_QQ._coerce_base_ring(K.gen()) # needs sage.rings.number_field
869
+ Number Field in s with defining polynomial z^2 - 2
870
+
871
+ sage: z = QQ['z'].0
872
+ sage: K = NumberField(z^2 - 2, 's') # needs sage.rings.number_field
873
+ sage: K.gen() * polytopes.simplex(backend='field') # needs sage.rings.number_field
874
+ A 3-dimensional polyhedron in
875
+ (Number Field in s with defining polynomial z^2 - 2)^4
876
+ defined as the convex hull of 4 vertices
877
+ """
878
+ from sage.structure.element import Element
879
+ if isinstance(other, Element):
880
+ other = other.parent()
881
+ if other in Rings():
882
+ other_ring = other
883
+ else:
884
+ try:
885
+ other_ring = other.base_ring()
886
+ except AttributeError:
887
+ try:
888
+ # other is a constant?
889
+ other_ring = other.parent()
890
+ except AttributeError:
891
+ other_ring = None
892
+ for ring in (ZZ, QQ, RDF):
893
+ try:
894
+ ring.coerce(other)
895
+ other_ring = ring
896
+ break
897
+ except TypeError:
898
+ pass
899
+ if other_ring is None:
900
+ raise TypeError(f'Could not coerce {other} into ZZ, QQ, or RDF.')
901
+
902
+ if not other_ring.is_exact():
903
+ other_ring = RDF # the only supported floating-point numbers for now
904
+
905
+ cm_map, cm_ring = get_coercion_model().analyse(self.base_ring(), other_ring)
906
+ if cm_ring is None:
907
+ raise TypeError(f'Could not coerce type {other} into ZZ, QQ, or RDF.')
908
+ return cm_ring
909
+
910
+ def _coerce_map_from_(self, X):
911
+ r"""
912
+ Return whether there is a coercion from ``X``.
913
+
914
+ INPUT:
915
+
916
+ - ``X`` -- anything
917
+
918
+ OUTPUT: boolean
919
+
920
+ EXAMPLES::
921
+
922
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
923
+ sage: Polyhedra(QQ, 3).has_coerce_map_from(Polyhedra(ZZ, 3)) # indirect doctest
924
+ True
925
+ sage: Polyhedra(ZZ, 3).has_coerce_map_from(Polyhedra(QQ, 3))
926
+ False
927
+ """
928
+ if not isinstance(X, Polyhedra_base):
929
+ return False
930
+ if self.ambient_dim() != X.ambient_dim():
931
+ return False
932
+ return self.base_ring().has_coerce_map_from(X.base_ring())
933
+
934
+ def _get_action_(self, other, op, self_is_left):
935
+ """
936
+ Register actions with the coercion model.
937
+
938
+ The monoid actions are Minkowski sum and Cartesian product. In
939
+ addition, we want multiplication by a scalar to be dilation
940
+ and addition by a vector to be translation. This is
941
+ implemented as an action in the coercion model.
942
+
943
+ INPUT:
944
+
945
+ - ``other`` -- a scalar or a vector
946
+
947
+ - ``op`` -- the operator
948
+
949
+ - ``self_is_left`` -- boolean; whether ``self`` is on the left
950
+ of the operator
951
+
952
+ OUTPUT: an action that is used by the coercion model
953
+
954
+ EXAMPLES::
955
+
956
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
957
+ sage: PZZ2 = Polyhedra(ZZ, 2)
958
+ sage: PZZ2.get_action(ZZ) # indirect doctest
959
+ Right action by Integer Ring on Polyhedra in ZZ^2
960
+ sage: PZZ2.get_action(QQ)
961
+ Right action by Rational Field on Polyhedra in QQ^2
962
+ with precomposition on left by Coercion map:
963
+ From: Polyhedra in ZZ^2
964
+ To: Polyhedra in QQ^2
965
+ with precomposition on right by Identity endomorphism of Rational Field
966
+ sage: PQQ2 = Polyhedra(QQ, 2)
967
+ sage: PQQ2.get_action(ZZ)
968
+ Right action by Integer Ring on Polyhedra in QQ^2
969
+ sage: PQQ2.get_action(QQ)
970
+ Right action by Rational Field on Polyhedra in QQ^2
971
+
972
+ sage: Polyhedra(ZZ,2).an_element() * 2
973
+ A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
974
+ sage: Polyhedra(ZZ,2).an_element() * (2/3)
975
+ A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
976
+ sage: Polyhedra(QQ,2).an_element() * 2
977
+ A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
978
+ sage: Polyhedra(QQ,2).an_element() * (2/3)
979
+ A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
980
+
981
+ sage: 2 * Polyhedra(ZZ,2).an_element()
982
+ A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
983
+ sage: (2/3) * Polyhedra(ZZ,2).an_element()
984
+ A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
985
+ sage: 2 * Polyhedra(QQ,2).an_element()
986
+ A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
987
+ sage: (2/3) * Polyhedra(QQ,2).an_element()
988
+ A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
989
+
990
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
991
+ sage: PZZ2.get_action(ZZ^2, op=operator.add)
992
+ Right action by Ambient free module of rank 2 over the principal ideal domain Integer Ring on Polyhedra in ZZ^2
993
+ with precomposition on left by
994
+ Identity endomorphism of Polyhedra in ZZ^2
995
+ with precomposition on right by
996
+ Generic endomorphism of Ambient free module of rank 2 over the principal ideal domain Integer Ring
997
+ """
998
+ import operator
999
+ from sage.structure.coerce_actions import ActedUponAction
1000
+ from sage.categories.action import PrecomposedAction
1001
+
1002
+ if op is operator.add and isinstance(other, FreeModule_generic):
1003
+ base_ring = self._coerce_base_ring(other)
1004
+ extended_self = self.base_extend(base_ring)
1005
+ extended_other = other.base_extend(base_ring)
1006
+ action = ActedUponAction(extended_other, extended_self, not self_is_left)
1007
+ if self_is_left:
1008
+ action = PrecomposedAction(action,
1009
+ extended_self._internal_coerce_map_from(self).__copy__(),
1010
+ extended_other._internal_coerce_map_from(other).__copy__())
1011
+ else:
1012
+ action = PrecomposedAction(action,
1013
+ extended_other._internal_coerce_map_from(other).__copy__(),
1014
+ extended_self._internal_coerce_map_from(self).__copy__())
1015
+ return action
1016
+
1017
+ if op is operator.mul and other in Rings().Commutative():
1018
+ ring = self._coerce_base_ring(other)
1019
+ if ring is self.base_ring():
1020
+ return ActedUponAction(other, self, not self_is_left)
1021
+ extended = self.base_extend(ring)
1022
+ action = ActedUponAction(ring, extended, not self_is_left)
1023
+ if self_is_left:
1024
+ action = PrecomposedAction(action,
1025
+ extended._internal_coerce_map_from(self).__copy__(),
1026
+ ring._internal_coerce_map_from(other).__copy__())
1027
+ else:
1028
+ action = PrecomposedAction(action,
1029
+ ring._internal_coerce_map_from(other).__copy__(),
1030
+ extended._internal_coerce_map_from(self).__copy__())
1031
+ return action
1032
+
1033
+ def _make_Inequality(self, polyhedron, data):
1034
+ """
1035
+ Create a new inequality object.
1036
+
1037
+ INPUT:
1038
+
1039
+ - ``polyhedron`` -- the new polyhedron
1040
+
1041
+ - ``data`` -- the H-representation data
1042
+
1043
+ OUTPUT: a new :class:`~sage.geometry.polyhedron.representation.Inequality` object
1044
+
1045
+ EXAMPLES::
1046
+
1047
+ sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)]) # indirect doctest
1048
+ sage: next(p.inequality_generator())
1049
+ An inequality (0, 0, -1) x + 3 >= 0
1050
+ """
1051
+ try:
1052
+ obj = self._Inequality_pool.pop()
1053
+ except IndexError:
1054
+ obj = Inequality(self)
1055
+ obj._set_data(polyhedron, data)
1056
+ return obj
1057
+
1058
+ def _make_Equation(self, polyhedron, data):
1059
+ """
1060
+ Create a new equation object.
1061
+
1062
+ INPUT:
1063
+
1064
+ - ``polyhedron`` -- the new polyhedron
1065
+
1066
+ - ``data`` -- the H-representation data
1067
+
1068
+ OUTPUT: a new :class:`~sage.geometry.polyhedron.representation.Equation` object
1069
+
1070
+ EXAMPLES::
1071
+
1072
+ sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)]) # indirect doctest
1073
+ sage: next(p.equation_generator())
1074
+ An equation (0, 44, -25) x - 13 == 0
1075
+ """
1076
+ try:
1077
+ obj = self._Equation_pool.pop()
1078
+ except IndexError:
1079
+ obj = Equation(self)
1080
+ obj._set_data(polyhedron, data)
1081
+ return obj
1082
+
1083
+ def _make_Vertex(self, polyhedron, data):
1084
+ """
1085
+ Create a new vertex object.
1086
+
1087
+ INPUT:
1088
+
1089
+ - ``polyhedron`` -- the new polyhedron
1090
+
1091
+ - ``data`` -- the V-representation data
1092
+
1093
+ OUTPUT: a new :class:`~sage.geometry.polyhedron.representation.Vertex` object
1094
+
1095
+ EXAMPLES::
1096
+
1097
+ sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)], rays=[(5/6,6/7,7/8)]) # indirect doctest
1098
+ sage: next(p.vertex_generator())
1099
+ A vertex at (1, 2, 3)
1100
+ """
1101
+ try:
1102
+ obj = self._Vertex_pool.pop()
1103
+ except IndexError:
1104
+ obj = Vertex(self)
1105
+ obj._set_data(polyhedron, data)
1106
+ return obj
1107
+
1108
+ def _make_Ray(self, polyhedron, data):
1109
+ """
1110
+ Create a new ray object.
1111
+
1112
+ INPUT:
1113
+
1114
+ - ``polyhedron`` -- the new polyhedron
1115
+
1116
+ - ``data`` -- the V-representation data
1117
+
1118
+ OUTPUT: a new :class:`~sage.geometry.polyhedron.representation.Ray` object
1119
+
1120
+ EXAMPLES::
1121
+
1122
+ sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)], rays=[(5/6,6/7,7/8)]) # indirect doctest
1123
+ sage: next(p.ray_generator())
1124
+ A ray in the direction (140, 144, 147)
1125
+ """
1126
+ try:
1127
+ obj = self._Ray_pool.pop()
1128
+ except IndexError:
1129
+ obj = Ray(self)
1130
+ obj._set_data(polyhedron, data)
1131
+ return obj
1132
+
1133
+ def _make_Line(self, polyhedron, data):
1134
+ """
1135
+ Create a new line object.
1136
+
1137
+ INPUT:
1138
+
1139
+ - ``polyhedron`` -- the new polyhedron
1140
+
1141
+ - ``data`` -- the V-representation data
1142
+
1143
+ OUTPUT: a new :class:`~sage.geometry.polyhedron.representation.Line` object
1144
+
1145
+ EXAMPLES::
1146
+
1147
+ sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)], lines=[(5/6,6/7,7/8)]) # indirect doctest
1148
+ sage: next(p.line_generator())
1149
+ A line in the direction (140, 144, 147)
1150
+ """
1151
+ try:
1152
+ obj = self._Line_pool.pop()
1153
+ except IndexError:
1154
+ obj = Line(self)
1155
+ obj._set_data(polyhedron, data)
1156
+ return obj
1157
+
1158
+
1159
+ from sage.geometry.polyhedron.backend_cdd import Polyhedron_QQ_cdd
1160
+ lazy_import('sage.geometry.polyhedron.backend_cdd_rdf', 'Polyhedron_RDF_cdd')
1161
+ from sage.geometry.polyhedron.backend_ppl import Polyhedron_ZZ_ppl, Polyhedron_QQ_ppl
1162
+ from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz, Polyhedron_ZZ_normaliz, Polyhedron_QQ_normaliz
1163
+ from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake
1164
+ from sage.geometry.polyhedron.backend_field import Polyhedron_field
1165
+ from sage.geometry.polyhedron.backend_number_field import Polyhedron_number_field
1166
+
1167
+
1168
+ class Polyhedra_ZZ_ppl(Polyhedra_base):
1169
+ Element = Polyhedron_ZZ_ppl
1170
+
1171
+ def _element_constructor_polyhedron(self, polyhedron, **kwds):
1172
+ """
1173
+ The element (polyhedron) constructor for the case of 1 argument, a polyhedron.
1174
+
1175
+ Set up with the ``ppl_polyhedron`` of ``self``, if available.
1176
+
1177
+ EXAMPLES::
1178
+
1179
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
1180
+ sage: P = Polyhedra(ZZ, 3)
1181
+ sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)], base_ring=QQ)
1182
+ sage: p
1183
+ A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
1184
+ sage: P(p)
1185
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
1186
+
1187
+ sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)], backend='cdd') # needs cddexec_gmp
1188
+ sage: P(p)
1189
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
1190
+ """
1191
+ from copy import copy
1192
+ if polyhedron.backend() == "ppl":
1193
+ return self._element_constructor_(None, None, ppl_polyhedron=copy(polyhedron._ppl_polyhedron), **kwds)
1194
+ else:
1195
+ return Polyhedra_base._element_constructor_polyhedron(self, polyhedron, **kwds)
1196
+
1197
+
1198
+ class Polyhedra_ZZ_normaliz(Polyhedra_base):
1199
+ Element = Polyhedron_ZZ_normaliz
1200
+
1201
+
1202
+ class Polyhedra_QQ_ppl(Polyhedra_base):
1203
+ Element = Polyhedron_QQ_ppl
1204
+
1205
+ def _element_constructor_polyhedron(self, polyhedron, **kwds):
1206
+ """
1207
+ The element (polyhedron) constructor for the case of 1 argument, a polyhedron.
1208
+
1209
+ Set up with the ``ppl_polyhedron`` of ``self``, if available.
1210
+
1211
+ EXAMPLES::
1212
+
1213
+ sage: from sage.geometry.polyhedron.parent import Polyhedra
1214
+ sage: P = Polyhedra(QQ, 3)
1215
+ sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)])
1216
+ sage: p
1217
+ A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
1218
+ sage: P(p)
1219
+ A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
1220
+
1221
+ sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)], backend='cdd') # needs cddexec_gmp
1222
+ sage: P(p)
1223
+ A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
1224
+ """
1225
+ from copy import copy
1226
+ if polyhedron.backend() == "ppl":
1227
+ return self._element_constructor_(None, None, ppl_polyhedron=copy(polyhedron._ppl_polyhedron), **kwds)
1228
+ else:
1229
+ return Polyhedra_base._element_constructor_polyhedron(self, polyhedron, **kwds)
1230
+
1231
+
1232
+ class Polyhedra_QQ_normaliz(Polyhedra_base):
1233
+ Element = Polyhedron_QQ_normaliz
1234
+
1235
+
1236
+ class Polyhedra_QQ_cdd(Polyhedra_base):
1237
+ Element = Polyhedron_QQ_cdd
1238
+
1239
+
1240
+ class Polyhedra_RDF_cdd(Polyhedra_base):
1241
+ Element = Polyhedron_RDF_cdd
1242
+
1243
+
1244
+ class Polyhedra_normaliz(Polyhedra_base):
1245
+ Element = Polyhedron_normaliz
1246
+
1247
+
1248
+ class Polyhedra_polymake(Polyhedra_base):
1249
+ Element = Polyhedron_polymake
1250
+
1251
+
1252
+ class Polyhedra_field(Polyhedra_base):
1253
+ Element = Polyhedron_field
1254
+
1255
+
1256
+ class Polyhedra_number_field(Polyhedra_base):
1257
+ Element = Polyhedron_number_field
1258
+
1259
+
1260
+ @cached_function
1261
+ def does_backend_handle_base_ring(base_ring, backend):
1262
+ r"""
1263
+ Return true, if ``backend`` can handle ``base_ring``.
1264
+
1265
+ EXAMPLES::
1266
+
1267
+ sage: from sage.geometry.polyhedron.parent import does_backend_handle_base_ring
1268
+ sage: does_backend_handle_base_ring(QQ, 'ppl')
1269
+ True
1270
+ sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'ppl') # needs sage.rings.number_field sage.symbolic
1271
+ False
1272
+ sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'field') # needs sage.rings.number_field sage.symbolic
1273
+ True
1274
+ """
1275
+ try:
1276
+ Polyhedra(base_ring, 0, backend)
1277
+ except ValueError:
1278
+ return False
1279
+ return True