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,753 @@
1
+ # sage_setup: distribution = sagemath-polyhedra
2
+ r"""
3
+ Double Description Algorithm for Cones
4
+
5
+ This module implements the double description algorithm for extremal
6
+ vertex enumeration in a pointed cone following [FP1996]_. With a
7
+ little bit of preprocessing (see
8
+ :mod:`~sage.geometry.polyhedron.double_description_inhomogeneous`)
9
+ this defines a backend for polyhedral computations. But as far as this
10
+ module is concerned, *inequality* always means without a constant term
11
+ and the origin is always a point of the cone.
12
+
13
+ EXAMPLES::
14
+
15
+ sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
16
+ sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
17
+ sage: alg = StandardAlgorithm(A); alg
18
+ Pointed cone with inequalities
19
+ (1, 0, 1)
20
+ (0, 1, 1)
21
+ (-1, -1, 1)
22
+ sage: DD, _ = alg.initial_pair(); DD
23
+ Double description pair (A, R) defined by
24
+ [ 1 0 1] [ 2/3 -1/3 -1/3]
25
+ A = [ 0 1 1], R = [-1/3 2/3 -1/3]
26
+ [-1 -1 1] [ 1/3 1/3 1/3]
27
+
28
+ The implementation works over any exact field that is embedded in
29
+ `\RR`, for example::
30
+
31
+ sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
32
+ sage: A = matrix(AA, [(1,0,1), (0,1,1), (-AA(2).sqrt(),-AA(3).sqrt(),1), # needs sage.rings.number_field
33
+ ....: (-AA(3).sqrt(),-AA(2).sqrt(),1)])
34
+ sage: alg = StandardAlgorithm(A)
35
+ sage: alg.run().R # needs sage.rings.number_field
36
+ [(-0.4177376677004119?, 0.5822623322995881?, 0.4177376677004119?),
37
+ (-0.2411809548974793?, -0.2411809548974793?, 0.2411809548974793?),
38
+ (0.07665629029830300?, 0.07665629029830300?, 0.2411809548974793?),
39
+ (0.5822623322995881?, -0.4177376677004119?, 0.4177376677004119?)]
40
+ """
41
+
42
+ #*****************************************************************************
43
+ # Copyright (C) 2014 Volker Braun <vbraun.name@gmail.com>
44
+ # 2015 Vincent Delecroix <20100.delecroix@gmail.com>
45
+ #
46
+ # This program is free software: you can redistribute it and/or modify
47
+ # it under the terms of the GNU General Public License as published by
48
+ # the Free Software Foundation, either version 2 of the License, or
49
+ # (at your option) any later version.
50
+ # http://www.gnu.org/licenses/
51
+ #*****************************************************************************
52
+
53
+
54
+ #*****************************************************************************
55
+ # TODO
56
+ #
57
+ # The adjacency check should use caching and the "combinatorial
58
+ # criterion" instead of the "algebraic criterion", see [FP1996]
59
+ # for definition. Since coefficient arithmetic is relatively expensive
60
+ # we should avoid it as far as possible.
61
+ #
62
+ # Also, the variants of the double description algorithm described in
63
+ # [FP1996] should be implemented. The design of this module is
64
+ # such that variants of the basic algorithm should be easy to add as
65
+ # subclasses of DoubleDescriptionPair and Problem.
66
+ # *****************************************************************************
67
+
68
+
69
+ # Compare with PPL if the base ring is QQ. Can be left enabled since
70
+ # we don't use the Python fallback for polyhedra over QQ unless you
71
+ # construct one by hand.
72
+
73
+ VERIFY_RESULT = True
74
+
75
+ import itertools
76
+
77
+ from sage.misc.cachefunc import cached_method
78
+ from sage.rings.rational_field import QQ
79
+ from sage.modules.free_module_element import vector
80
+ from sage.matrix.matrix_space import MatrixSpace
81
+
82
+
83
+ def random_inequalities(d, n):
84
+ """
85
+ Random collections of inequalities for testing purposes.
86
+
87
+ INPUT:
88
+
89
+ - ``d`` -- integer; the dimension
90
+
91
+ - ``n`` -- integer; the number of random inequalities to generate
92
+
93
+ OUTPUT: a random set of inequalities as a :class:`StandardAlgorithm` instance
94
+
95
+ EXAMPLES::
96
+
97
+ sage: from sage.geometry.polyhedron.double_description import random_inequalities
98
+ sage: P = random_inequalities(5, 10)
99
+ sage: P.run().verify()
100
+ """
101
+ from sage.matrix.constructor import random_matrix
102
+ while True:
103
+ A = random_matrix(QQ, n, d)
104
+ if A.rank() == min(n, d) and not any(a == 0 for a in A.rows()):
105
+ break
106
+ return StandardAlgorithm(A)
107
+
108
+
109
+ class DoubleDescriptionPair:
110
+
111
+ def __init__(self, problem, A_rows, R_cols):
112
+ r"""
113
+ Base class for a double description pair `(A, R)`.
114
+
115
+ .. warning::
116
+
117
+ You should use the :meth:`Problem.initial_pair` or
118
+ :meth:`Problem.run` to generate double description pairs
119
+ for a set of inequalities, and not generate
120
+ ``DoubleDescriptionPair`` instances directly.
121
+
122
+ INPUT:
123
+
124
+ - ``problem`` -- instance of :class:`Problem`
125
+
126
+ - ``A_rows`` -- list of row vectors of the matrix `A`; these
127
+ encode the inequalities
128
+
129
+ - ``R_cols`` -- list of column vectors of the matrix
130
+ `R`; these encode the rays
131
+
132
+ TESTS::
133
+
134
+ sage: from sage.geometry.polyhedron.double_description import \
135
+ ....: DoubleDescriptionPair, Problem
136
+ sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
137
+ sage: alg = Problem(A)
138
+ sage: DoubleDescriptionPair(alg,
139
+ ....: [(1, 0, 1), (0, 1, 1), (-1, -1, 1)],
140
+ ....: [(2/3, -1/3, 1/3), (-1/3, 2/3, 1/3), (-1/3, -1/3, 1/3)])
141
+ Double description pair (A, R) defined by
142
+ [ 1 0 1] [ 2/3 -1/3 -1/3]
143
+ A = [ 0 1 1], R = [-1/3 2/3 -1/3]
144
+ [-1 -1 1] [ 1/3 1/3 1/3]
145
+ """
146
+ self.problem = problem
147
+ self.A = list(A_rows)
148
+ self.R = list(R_cols)
149
+ self.one = problem._field.one()
150
+ self.zero = problem._field.zero()
151
+
152
+ # a cache for scalar products (see the method zero_set)
153
+ self.zero_set_cache = {}
154
+
155
+ def _make_new(self, A_rows, R_cols):
156
+ r"""
157
+ Construct a new double description pair.
158
+
159
+ INPUT:
160
+
161
+ - ``A_rows`` -- list of row vectors of the matrix `A`; these
162
+ encode the inequalities
163
+
164
+ - ``R_cols`` -- list of column vectors of the matrix
165
+ `R`; these encode the rays
166
+
167
+ OUTPUT:
168
+
169
+ A new double description pair of the same (sub)class of
170
+ :class:`DoubleDescriptionProblem`.
171
+
172
+ EXAMPLES::
173
+
174
+ sage: from sage.geometry.polyhedron.double_description import \
175
+ ....: DoubleDescriptionPair, StandardAlgorithm
176
+ sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
177
+ sage: DD = StandardAlgorithm(A).run()
178
+ sage: DDnew = DD._make_new(DD.A, DD.R); DDnew
179
+ Double description pair (A, R) defined by
180
+ [ 1 0 1] [ 2/3 -1/3 -1/3]
181
+ A = [ 0 1 1], R = [-1/3 2/3 -1/3]
182
+ [-1 -1 1] [ 1/3 1/3 1/3]
183
+ sage: DDnew is DD
184
+ False
185
+ sage: DDnew.__class__ is DD.__class__
186
+ True
187
+ """
188
+ return self.__class__(self.problem, A_rows, R_cols)
189
+
190
+ def __repr__(self):
191
+ r"""
192
+ Return string representation.
193
+
194
+ OUTPUT: string
195
+
196
+ EXAMPLES::
197
+
198
+ sage: from sage.geometry.polyhedron.double_description import \
199
+ ....: DoubleDescriptionPair, StandardAlgorithm
200
+ sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
201
+ sage: DD = StandardAlgorithm(A).run()
202
+ sage: DD.__repr__()
203
+ 'Double description pair (A, R) defined by\n [ 1 0 1]
204
+ [ 2/3 -1/3 -1/3]\nA = [ 0 1 1], R = [-1/3 2/3 -1/3]\n
205
+ [-1 -1 1] [ 1/3 1/3 1/3]'
206
+ """
207
+ from sage.typeset.ascii_art import ascii_art
208
+ from sage.matrix.constructor import matrix
209
+ s = ascii_art('Double description pair (A, R) defined by')
210
+ A = ascii_art(matrix(self.A))
211
+ A._baseline = (len(self.A) // 2)
212
+ A = ascii_art('A = ') + A
213
+ R = ascii_art(matrix(self.R).transpose())
214
+ if len(self.R) > 0:
215
+ R._baseline = (len(self.R[0]) // 2)
216
+ else:
217
+ R._baseline = 0
218
+ R = ascii_art('R = ') + R
219
+ return str(s * (A + ascii_art(', ') + R))
220
+
221
+ def inner_product_matrix(self):
222
+ """
223
+ Return the inner product matrix between the rows of `A`
224
+ and the columns of `R`.
225
+
226
+ OUTPUT:
227
+
228
+ A matrix over the base ring. There is one row for each row of
229
+ `A` and one column for each column of `R`.
230
+
231
+ EXAMPLES::
232
+
233
+ sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
234
+ sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
235
+ sage: alg = StandardAlgorithm(A)
236
+ sage: DD, _ = alg.initial_pair()
237
+ sage: DD.inner_product_matrix()
238
+ [1 0 0]
239
+ [0 1 0]
240
+ [0 0 1]
241
+ """
242
+ from sage.matrix.constructor import matrix
243
+ return matrix(self.problem.base_ring(), [[a.inner_product(r) for r in self.R] for a in self.A])
244
+
245
+ def cone(self):
246
+ r"""
247
+ Return the cone defined by `A`.
248
+
249
+ This method is for debugging only. Assumes that the base ring
250
+ is `\QQ`.
251
+
252
+ OUTPUT:
253
+
254
+ The cone defined by the inequalities as a
255
+ :func:`~sage.geometry.polyhedron.constructor.Polyhedron`,
256
+ using the PPL backend.
257
+
258
+ EXAMPLES::
259
+
260
+ sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
261
+ sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
262
+ sage: DD, _ = StandardAlgorithm(A).initial_pair()
263
+ sage: DD.cone().Hrepresentation()
264
+ (An inequality (-1, -1, 1) x + 0 >= 0,
265
+ An inequality (0, 1, 1) x + 0 >= 0,
266
+ An inequality (1, 0, 1) x + 0 >= 0)
267
+ """
268
+ from sage.geometry.polyhedron.constructor import Polyhedron
269
+ assert self.problem.base_ring() == QQ # required for PPL backend
270
+
271
+ if not self.A:
272
+ return Polyhedron(vertices=[[0] * self.problem.dim()], backend='ppl')
273
+ else:
274
+ ieqs = [[0] + list(a) for a in self.A]
275
+ return Polyhedron(ieqs=ieqs, base_ring=self.problem.base_ring(), backend='ppl')
276
+
277
+ def verify(self):
278
+ r"""
279
+ Validate the double description pair.
280
+
281
+ This method used the PPL backend to check that the double
282
+ description pair is valid. An assertion is triggered if it is
283
+ not. Does nothing if the base ring is not `\QQ`.
284
+
285
+ EXAMPLES::
286
+
287
+ sage: from sage.geometry.polyhedron.double_description import \
288
+ ....: DoubleDescriptionPair, Problem
289
+ sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
290
+ sage: alg = Problem(A)
291
+ sage: DD = DoubleDescriptionPair(alg,
292
+ ....: [(1, 0, 3), (0, 1, 1), (-1, -1, 1)],
293
+ ....: [(2/3, -1/3, 1/3), (-1/3, 2/3, 1/3), (-1/3, -1/3, 1/3)])
294
+ sage: DD.verify()
295
+ Traceback (most recent call last):
296
+ ...
297
+ assert A_cone == R_cone
298
+ AssertionError
299
+ """
300
+ from sage.geometry.polyhedron.constructor import Polyhedron
301
+ if self.problem.base_ring() is not QQ:
302
+ return
303
+ A_cone = self.cone()
304
+ R_cone = Polyhedron(vertices=[[self.zero] * self.problem.dim()], rays=self.R,
305
+ base_ring=self.problem.base_ring(), backend='ppl')
306
+ assert A_cone == R_cone
307
+ assert A_cone.n_inequalities() <= len(self.A)
308
+ assert R_cone.n_rays() == len(self.R)
309
+
310
+ def R_by_sign(self, a):
311
+ """
312
+ Classify the rays into those that are positive, zero, and negative on `a`.
313
+
314
+ INPUT:
315
+
316
+ - ``a`` -- vector; coefficient vector of a homogeneous inequality
317
+
318
+ OUTPUT:
319
+
320
+ A triple consisting of the rays (columns of `R`) that are
321
+ positive, zero, and negative on `a`. In that order.
322
+
323
+ EXAMPLES::
324
+
325
+ sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
326
+ sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
327
+ sage: DD, _ = StandardAlgorithm(A).initial_pair()
328
+ sage: DD.R_by_sign(vector([1,-1,0]))
329
+ ([(2/3, -1/3, 1/3)], [(-1/3, -1/3, 1/3)], [(-1/3, 2/3, 1/3)])
330
+ sage: DD.R_by_sign(vector([1,1,1]))
331
+ ([(2/3, -1/3, 1/3), (-1/3, 2/3, 1/3)], [], [(-1/3, -1/3, 1/3)])
332
+ """
333
+ pos = []
334
+ nul = []
335
+ neg = []
336
+ for r in self.R:
337
+ sgn = a * r
338
+ if sgn == self.zero:
339
+ nul.append(r)
340
+ elif sgn > self.zero:
341
+ pos.append(r)
342
+ else:
343
+ neg.append(r)
344
+ return pos, nul, neg
345
+
346
+ def zero_set(self, ray):
347
+ """
348
+ Return the zero set (active set) `Z(r)`.
349
+
350
+ INPUT:
351
+
352
+ - ``ray`` -- a ray vector
353
+
354
+ OUTPUT: a set containing the inequality vectors that are zero on ``ray``
355
+
356
+ EXAMPLES::
357
+
358
+ sage: from sage.geometry.polyhedron.double_description import Problem
359
+ sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
360
+ sage: DD, _ = Problem(A).initial_pair()
361
+ sage: r = DD.R[0]; r
362
+ (2/3, -1/3, 1/3)
363
+ sage: DD.zero_set(r)
364
+ {(-1, -1, 1), (0, 1, 1)}
365
+ """
366
+ if ray not in self.zero_set_cache:
367
+ self.zero_set_cache[ray] = (0, set())
368
+ n, t = self.zero_set_cache[ray]
369
+ if n != len(self.A):
370
+ t.update(self.A[i] for i in range(n,len(self.A)) if self.A[i].inner_product(ray) == self.zero)
371
+ self.zero_set_cache[ray] = (len(self.A), t)
372
+ return t
373
+
374
+ def is_extremal(self, ray):
375
+ """
376
+ Test whether the ray is extremal.
377
+
378
+ EXAMPLES::
379
+
380
+ sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
381
+ sage: A = matrix(QQ, [(0,1,0), (1,0,0), (0,-1,1), (-1,0,1)])
382
+ sage: DD = StandardAlgorithm(A).run()
383
+ sage: DD.is_extremal(DD.R[0])
384
+ True
385
+ """
386
+ from sage.matrix.constructor import matrix
387
+ A_Zray = matrix(self.problem.base_ring(), list(self.zero_set(ray)))
388
+ return A_Zray.rank() == self.problem.dim() - 1
389
+
390
+ @cached_method
391
+ def matrix_space(self, nrows, ncols):
392
+ r"""
393
+ Return a matrix space of size ``nrows`` and ``ncols`` over the base ring
394
+ of ``self``.
395
+
396
+ These matrix spaces are cached to avoid their creation in the very
397
+ demanding :meth:`add_inequality` and more precisely :meth:`are_adjacent`.
398
+
399
+ EXAMPLES::
400
+
401
+ sage: from sage.geometry.polyhedron.double_description import Problem
402
+ sage: A = matrix(QQ, [(1,0,1), (0,1,1), (-1,-1,1)])
403
+ sage: DD, _ = Problem(A).initial_pair()
404
+ sage: DD.matrix_space(2,2)
405
+ Full MatrixSpace of 2 by 2 dense matrices over Rational Field
406
+ sage: DD.matrix_space(3,2)
407
+ Full MatrixSpace of 3 by 2 dense matrices over Rational Field
408
+
409
+ sage: # needs sage.rings.number_field
410
+ sage: K.<sqrt2> = QuadraticField(2)
411
+ sage: A = matrix([[1,sqrt2],[2,0]])
412
+ sage: DD, _ = Problem(A).initial_pair()
413
+ sage: DD.matrix_space(1,2)
414
+ Full MatrixSpace of 1 by 2 dense matrices
415
+ over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?
416
+ """
417
+ return MatrixSpace(self.problem.base_ring(), nrows, ncols)
418
+
419
+ def are_adjacent(self, r1, r2):
420
+ """
421
+ Return whether the two rays are adjacent.
422
+
423
+ INPUT:
424
+
425
+ - ``r1``, ``r2`` -- two rays
426
+
427
+ OUTPUT: boolean; whether the two rays are adjacent
428
+
429
+ EXAMPLES::
430
+
431
+ sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
432
+ sage: A = matrix(QQ, [(0,1,0), (1,0,0), (0,-1,1), (-1,0,1)])
433
+ sage: DD = StandardAlgorithm(A).run()
434
+ sage: DD.are_adjacent(DD.R[0], DD.R[1])
435
+ True
436
+ sage: DD.are_adjacent(DD.R[0], DD.R[2])
437
+ True
438
+ sage: DD.are_adjacent(DD.R[0], DD.R[3])
439
+ False
440
+ """
441
+ Z = self.zero_set(r1).intersection(self.zero_set(r2))
442
+ if not Z:
443
+ return self.problem.dim() == 2
444
+ Z = list(Z)
445
+
446
+ # here we try to create a matrix as fast as possible
447
+ # since the generic matrix constructor is very slow (trac #18231)
448
+ A_Z12 = self.matrix_space(len(Z), len(Z[0])).matrix(Z, coerce=False)
449
+ return A_Z12.rank() == self.problem.dim() - 2
450
+
451
+ def dual(self):
452
+ """
453
+ Return the dual.
454
+
455
+ OUTPUT:
456
+
457
+ For the double description pair `(A, R)` this method returns
458
+ the dual double description pair `(R^T, A^T)`
459
+
460
+ EXAMPLES::
461
+
462
+ sage: from sage.geometry.polyhedron.double_description import Problem
463
+ sage: A = matrix(QQ, [(0,1,0), (1,0,0), (0,-1,1), (-1,0,1)])
464
+ sage: DD, _ = Problem(A).initial_pair()
465
+ sage: DD
466
+ Double description pair (A, R) defined by
467
+ [ 0 1 0] [0 1 0]
468
+ A = [ 1 0 0], R = [1 0 0]
469
+ [ 0 -1 1] [1 0 1]
470
+ sage: DD.dual()
471
+ Double description pair (A, R) defined by
472
+ [0 1 1] [ 0 1 0]
473
+ A = [1 0 0], R = [ 1 0 -1]
474
+ [0 0 1] [ 0 0 1]
475
+ """
476
+ return self._make_new(self.R, self.A)
477
+
478
+ def first_coordinate_plane(self):
479
+ """
480
+ Restrict to the first coordinate plane.
481
+
482
+ OUTPUT:
483
+
484
+ A new double description pair with the constraint `x_0 = 0`
485
+ added.
486
+
487
+ EXAMPLES::
488
+
489
+ sage: A = matrix([(1, 1), (-1, 1)])
490
+ sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
491
+ sage: DD, _ = StandardAlgorithm(A).initial_pair()
492
+ sage: DD
493
+ Double description pair (A, R) defined by
494
+ A = [ 1 1], R = [ 1/2 -1/2]
495
+ [-1 1] [ 1/2 1/2]
496
+ sage: DD.first_coordinate_plane()
497
+ Double description pair (A, R) defined by
498
+ [ 1 1]
499
+ A = [-1 1], R = [ 0]
500
+ [-1 0] [1/2]
501
+ [ 1 0]
502
+ """
503
+ R = self.problem.base_ring()
504
+ d = self.problem.dim()
505
+ a_neg = vector(R, [-self.one] + [self.zero] * (d - 1))
506
+ a_pos = vector(R, [+self.one] + [self.zero] * (d - 1))
507
+ new = self._make_new(self.A, self.R)
508
+ new.add_inequality(a_neg)
509
+ new.add_inequality(a_pos)
510
+ return new
511
+
512
+
513
+ class Problem:
514
+
515
+ pair_class = DoubleDescriptionPair
516
+
517
+ def __init__(self, A):
518
+ r"""
519
+ Base class for implementations of the double description algorithm.
520
+
521
+ It does not make sense to instantiate the base class directly,
522
+ it just provides helpers for implementations.
523
+
524
+ INPUT:
525
+
526
+ - ``A`` -- a matrix; the rows of the matrix are interpreted as
527
+ homogeneous inequalities `A x \geq 0`. Must have maximal rank.
528
+
529
+ TESTS::
530
+
531
+ sage: A = matrix([(1, 1), (-1, 1)])
532
+ sage: from sage.geometry.polyhedron.double_description import Problem
533
+ sage: Problem(A)
534
+ Pointed cone with inequalities
535
+ (1, 1)
536
+ (-1, 1)
537
+ """
538
+ assert A.rank() == A.ncols() # implementation assumes maximal rank
539
+ if A.is_mutable():
540
+ A = A.__copy__()
541
+ A.set_immutable()
542
+ self._A = A
543
+ self._field = A.base_ring().fraction_field()
544
+
545
+ @cached_method
546
+ def A(self):
547
+ """
548
+ Return the rows of the defining matrix `A`.
549
+
550
+ OUTPUT: the matrix `A` whose rows are the inequalities
551
+
552
+ EXAMPLES::
553
+
554
+ sage: A = matrix([(1, 1), (-1, 1)])
555
+ sage: from sage.geometry.polyhedron.double_description import Problem
556
+ sage: Problem(A).A()
557
+ ((1, 1), (-1, 1))
558
+ """
559
+ rows = [a.change_ring(self._field) for a in self._A.rows()]
560
+ for a in rows:
561
+ a.set_immutable()
562
+ return tuple(rows)
563
+
564
+ def A_matrix(self):
565
+ """
566
+ Return the defining matrix `A`.
567
+
568
+ OUTPUT: matrix whose rows are the inequalities
569
+
570
+ EXAMPLES::
571
+
572
+ sage: A = matrix([(1, 1), (-1, 1)])
573
+ sage: from sage.geometry.polyhedron.double_description import Problem
574
+ sage: Problem(A).A_matrix()
575
+ [ 1 1]
576
+ [-1 1]
577
+ """
578
+ return self._A
579
+
580
+ def base_ring(self):
581
+ """
582
+ Return the base field.
583
+
584
+ OUTPUT: a field
585
+
586
+ EXAMPLES::
587
+
588
+ sage: A = matrix(AA, [(1, 1), (-1, 1)]) # needs sage.rings.number_field
589
+ sage: from sage.geometry.polyhedron.double_description import Problem
590
+ sage: Problem(A).base_ring() # needs sage.rings.number_field
591
+ Algebraic Real Field
592
+ """
593
+ return self._field
594
+
595
+ @cached_method
596
+ def dim(self):
597
+ """
598
+ Return the ambient space dimension.
599
+
600
+ OUTPUT: integer; the ambient space dimension of the cone
601
+
602
+ EXAMPLES::
603
+
604
+ sage: A = matrix(QQ, [(1, 1), (-1, 1)])
605
+ sage: from sage.geometry.polyhedron.double_description import Problem
606
+ sage: Problem(A).dim()
607
+ 2
608
+ """
609
+ return self._A.ncols()
610
+
611
+ def __repr__(self):
612
+ r"""
613
+ Return a string representation.
614
+
615
+ OUTPUT: string
616
+
617
+ EXAMPLES::
618
+
619
+ sage: A = matrix(QQ, [(1, 1), (-1, 1)])
620
+ sage: from sage.geometry.polyhedron.double_description import Problem
621
+ sage: Problem(A).__repr__()
622
+ 'Pointed cone with inequalities\n(1, 1)\n(-1, 1)'
623
+ """
624
+ return 'Pointed cone with inequalities\n' + '\n'.join(map(str, self.A()))
625
+
626
+ def initial_pair(self):
627
+ """
628
+ Return an initial double description pair.
629
+
630
+ Picks an initial set of rays by selecting a basis. This is
631
+ probably the most efficient way to select the initial set.
632
+
633
+ INPUT:
634
+
635
+ - ``pair_class`` -- subclass of
636
+ :class:`DoubleDescriptionPair`
637
+
638
+ OUTPUT:
639
+
640
+ A pair consisting of a :class:`DoubleDescriptionPair` instance
641
+ and the tuple of remaining unused inequalities.
642
+
643
+ EXAMPLES::
644
+
645
+ sage: A = matrix([(-1, 1), (-1, 2), (1/2, -1/2), (1/2, 2)])
646
+ sage: from sage.geometry.polyhedron.double_description import Problem
647
+ sage: DD, remaining = Problem(A).initial_pair()
648
+ sage: DD.verify()
649
+ sage: remaining
650
+ [(1/2, -1/2), (1/2, 2)]
651
+ """
652
+ pivot_rows = self.A_matrix().pivot_rows()
653
+ A0 = [self.A()[pivot] for pivot in pivot_rows]
654
+ Ac = [self.A()[i] for i in range(len(self.A())) if i not in pivot_rows]
655
+ from sage.matrix.constructor import identity_matrix, matrix
656
+ I = identity_matrix(self.base_ring(), self.dim())
657
+ R = matrix(self.base_ring(), A0).solve_right(I)
658
+ return self.pair_class(self, A0, R.columns()), list(Ac)
659
+
660
+
661
+ class StandardDoubleDescriptionPair(DoubleDescriptionPair):
662
+ """
663
+ Double description pair for the "Standard Algorithm".
664
+
665
+ See :class:`StandardAlgorithm`.
666
+
667
+ TESTS::
668
+
669
+ sage: A = matrix([(-1, 1, 0), (-1, 2, 1), (1/2, -1/2, -1)])
670
+ sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
671
+ sage: DD, _ = StandardAlgorithm(A).initial_pair()
672
+ """
673
+
674
+ def add_inequality(self, a):
675
+ """
676
+ Add the inequality ``a`` to the matrix `A` of the double description.
677
+
678
+ INPUT:
679
+
680
+ - ``a`` -- vector; an inequality
681
+
682
+ EXAMPLES::
683
+
684
+ sage: A = matrix([(-1, 1, 0), (-1, 2, 1), (1/2, -1/2, -1)])
685
+ sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
686
+ sage: DD, _ = StandardAlgorithm(A).initial_pair()
687
+ sage: DD.add_inequality(vector([1,0,0]))
688
+ sage: DD
689
+ Double description pair (A, R) defined by
690
+ [ -1 1 0] [ 1 1 0 0]
691
+ A = [ -1 2 1], R = [ 1 1 1 1]
692
+ [ 1/2 -1/2 -1] [ 0 -1 -1/2 -2]
693
+ [ 1 0 0]
694
+ """
695
+ R_pos, R_nul, R_neg = self.R_by_sign(a)
696
+ if not R_neg:
697
+ return
698
+ R_new = []
699
+ for rp, rn in itertools.product(R_pos, R_neg):
700
+ if not self.are_adjacent(rp, rn):
701
+ continue
702
+ r = a.inner_product(rp) * rn - a.inner_product(rn) * rp
703
+ r.set_immutable()
704
+ R_new.append(r)
705
+ self.R = R_pos + R_nul + R_new
706
+ self.A.append(a)
707
+
708
+
709
+ class StandardAlgorithm(Problem):
710
+ """
711
+ Standard implementation of the double description algorithm.
712
+
713
+ See [FP1996]_ for the definition of the "Standard
714
+ Algorithm".
715
+
716
+ EXAMPLES::
717
+
718
+ sage: A = matrix(QQ, [(1, 1), (-1, 1)])
719
+ sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
720
+ sage: DD = StandardAlgorithm(A).run()
721
+ sage: DD.R # the extremal rays
722
+ [(1/2, 1/2), (-1/2, 1/2)]
723
+ """
724
+ pair_class = StandardDoubleDescriptionPair
725
+
726
+ def run(self):
727
+ """
728
+ Run the Standard Algorithm.
729
+
730
+ OUTPUT:
731
+
732
+ A double description pair `(A, R)` of all inequalities as a
733
+ :class:`DoubleDescriptionPair`. By virtue of the double
734
+ description algorithm, the columns of `R` are the extremal
735
+ rays.
736
+
737
+ EXAMPLES::
738
+
739
+ sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm
740
+ sage: A = matrix(QQ, [(0,1,0), (1,0,0), (0,-1,1), (-1,0,1)])
741
+ sage: StandardAlgorithm(A).run()
742
+ Double description pair (A, R) defined by
743
+ [ 0 1 0] [0 0 1 1]
744
+ A = [ 1 0 0], R = [1 0 1 0]
745
+ [ 0 -1 1] [1 1 1 1]
746
+ [-1 0 1]
747
+ """
748
+ DD, remaining = self.initial_pair()
749
+ for a in remaining:
750
+ DD.add_inequality(a)
751
+ if VERIFY_RESULT:
752
+ DD.verify()
753
+ return DD