passagemath-polyhedra 10.6.31rc3__cp314-cp314-macosx_13_0_arm64.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 (205) hide show
  1. passagemath_polyhedra-10.6.31rc3.dist-info/METADATA +368 -0
  2. passagemath_polyhedra-10.6.31rc3.dist-info/METADATA.bak +371 -0
  3. passagemath_polyhedra-10.6.31rc3.dist-info/RECORD +205 -0
  4. passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +6 -0
  5. passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
  6. passagemath_polyhedra.dylibs/libgmp.10.dylib +0 -0
  7. sage/all__sagemath_polyhedra.py +50 -0
  8. sage/game_theory/all.py +8 -0
  9. sage/game_theory/catalog.py +6 -0
  10. sage/game_theory/catalog_normal_form_games.py +923 -0
  11. sage/game_theory/cooperative_game.py +844 -0
  12. sage/game_theory/matching_game.py +1181 -0
  13. sage/game_theory/normal_form_game.py +2697 -0
  14. sage/game_theory/parser.py +275 -0
  15. sage/geometry/all__sagemath_polyhedra.py +22 -0
  16. sage/geometry/cone.py +6940 -0
  17. sage/geometry/cone_catalog.py +847 -0
  18. sage/geometry/cone_critical_angles.py +1027 -0
  19. sage/geometry/convex_set.py +1119 -0
  20. sage/geometry/fan.py +3743 -0
  21. sage/geometry/fan_isomorphism.py +389 -0
  22. sage/geometry/fan_morphism.py +1884 -0
  23. sage/geometry/hasse_diagram.py +202 -0
  24. sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
  25. sage/geometry/hyperplane_arrangement/all.py +1 -0
  26. sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
  27. sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
  28. sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
  29. sage/geometry/hyperplane_arrangement/library.py +825 -0
  30. sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
  31. sage/geometry/hyperplane_arrangement/plot.py +520 -0
  32. sage/geometry/integral_points.py +35 -0
  33. sage/geometry/integral_points_generic_dense.cpython-314-darwin.so +0 -0
  34. sage/geometry/integral_points_generic_dense.pyx +7 -0
  35. sage/geometry/lattice_polytope.py +5894 -0
  36. sage/geometry/linear_expression.py +773 -0
  37. sage/geometry/newton_polygon.py +767 -0
  38. sage/geometry/point_collection.cpython-314-darwin.so +0 -0
  39. sage/geometry/point_collection.pyx +1008 -0
  40. sage/geometry/polyhedral_complex.py +2616 -0
  41. sage/geometry/polyhedron/all.py +8 -0
  42. sage/geometry/polyhedron/backend_cdd.py +460 -0
  43. sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
  44. sage/geometry/polyhedron/backend_field.py +347 -0
  45. sage/geometry/polyhedron/backend_normaliz.py +2503 -0
  46. sage/geometry/polyhedron/backend_number_field.py +168 -0
  47. sage/geometry/polyhedron/backend_polymake.py +765 -0
  48. sage/geometry/polyhedron/backend_ppl.py +582 -0
  49. sage/geometry/polyhedron/base.py +1206 -0
  50. sage/geometry/polyhedron/base0.py +1444 -0
  51. sage/geometry/polyhedron/base1.py +886 -0
  52. sage/geometry/polyhedron/base2.py +812 -0
  53. sage/geometry/polyhedron/base3.py +1845 -0
  54. sage/geometry/polyhedron/base4.py +1262 -0
  55. sage/geometry/polyhedron/base5.py +2700 -0
  56. sage/geometry/polyhedron/base6.py +1741 -0
  57. sage/geometry/polyhedron/base7.py +997 -0
  58. sage/geometry/polyhedron/base_QQ.py +1258 -0
  59. sage/geometry/polyhedron/base_RDF.py +98 -0
  60. sage/geometry/polyhedron/base_ZZ.py +934 -0
  61. sage/geometry/polyhedron/base_mutable.py +215 -0
  62. sage/geometry/polyhedron/base_number_field.py +122 -0
  63. sage/geometry/polyhedron/cdd_file_format.py +155 -0
  64. sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
  65. sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-darwin.so +0 -0
  66. sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
  67. sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
  68. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-darwin.so +0 -0
  69. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
  70. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
  71. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-darwin.so +0 -0
  72. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
  73. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
  74. sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
  75. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-darwin.so +0 -0
  76. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
  77. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
  78. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-darwin.so +0 -0
  79. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
  80. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
  81. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-darwin.so +0 -0
  82. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
  83. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
  84. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-darwin.so +0 -0
  85. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
  86. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
  87. sage/geometry/polyhedron/constructor.py +773 -0
  88. sage/geometry/polyhedron/double_description.py +753 -0
  89. sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
  90. sage/geometry/polyhedron/face.py +1060 -0
  91. sage/geometry/polyhedron/generating_function.py +1810 -0
  92. sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
  93. sage/geometry/polyhedron/library.py +3502 -0
  94. sage/geometry/polyhedron/misc.py +121 -0
  95. sage/geometry/polyhedron/modules/all.py +1 -0
  96. sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
  97. sage/geometry/polyhedron/palp_database.py +447 -0
  98. sage/geometry/polyhedron/parent.py +1279 -0
  99. sage/geometry/polyhedron/plot.py +1986 -0
  100. sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
  101. sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
  102. sage/geometry/polyhedron/representation.py +1723 -0
  103. sage/geometry/pseudolines.py +515 -0
  104. sage/geometry/relative_interior.py +445 -0
  105. sage/geometry/toric_plotter.py +1103 -0
  106. sage/geometry/triangulation/all.py +2 -0
  107. sage/geometry/triangulation/base.cpython-314-darwin.so +0 -0
  108. sage/geometry/triangulation/base.pyx +963 -0
  109. sage/geometry/triangulation/data.h +147 -0
  110. sage/geometry/triangulation/data.pxd +4 -0
  111. sage/geometry/triangulation/element.py +914 -0
  112. sage/geometry/triangulation/functions.h +10 -0
  113. sage/geometry/triangulation/functions.pxd +4 -0
  114. sage/geometry/triangulation/point_configuration.py +2256 -0
  115. sage/geometry/triangulation/triangulations.h +49 -0
  116. sage/geometry/triangulation/triangulations.pxd +7 -0
  117. sage/geometry/voronoi_diagram.py +319 -0
  118. sage/interfaces/all__sagemath_polyhedra.py +1 -0
  119. sage/interfaces/polymake.py +2028 -0
  120. sage/numerical/all.py +13 -0
  121. sage/numerical/all__sagemath_polyhedra.py +11 -0
  122. sage/numerical/backends/all.py +1 -0
  123. sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
  124. sage/numerical/backends/cvxopt_backend.cpython-314-darwin.so +0 -0
  125. sage/numerical/backends/cvxopt_backend.pyx +1006 -0
  126. sage/numerical/backends/cvxopt_backend_test.py +19 -0
  127. sage/numerical/backends/cvxopt_sdp_backend.cpython-314-darwin.so +0 -0
  128. sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
  129. sage/numerical/backends/cvxpy_backend.cpython-314-darwin.so +0 -0
  130. sage/numerical/backends/cvxpy_backend.pxd +41 -0
  131. sage/numerical/backends/cvxpy_backend.pyx +934 -0
  132. sage/numerical/backends/cvxpy_backend_test.py +13 -0
  133. sage/numerical/backends/generic_backend_test.py +24 -0
  134. sage/numerical/backends/interactivelp_backend.cpython-314-darwin.so +0 -0
  135. sage/numerical/backends/interactivelp_backend.pxd +36 -0
  136. sage/numerical/backends/interactivelp_backend.pyx +1231 -0
  137. sage/numerical/backends/interactivelp_backend_test.py +12 -0
  138. sage/numerical/backends/logging_backend.py +391 -0
  139. sage/numerical/backends/matrix_sdp_backend.cpython-314-darwin.so +0 -0
  140. sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
  141. sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
  142. sage/numerical/backends/ppl_backend.cpython-314-darwin.so +0 -0
  143. sage/numerical/backends/ppl_backend.pyx +1126 -0
  144. sage/numerical/backends/ppl_backend_test.py +13 -0
  145. sage/numerical/backends/scip_backend.cpython-314-darwin.so +0 -0
  146. sage/numerical/backends/scip_backend.pxd +22 -0
  147. sage/numerical/backends/scip_backend.pyx +1289 -0
  148. sage/numerical/backends/scip_backend_test.py +13 -0
  149. sage/numerical/interactive_simplex_method.py +5338 -0
  150. sage/numerical/knapsack.py +665 -0
  151. sage/numerical/linear_functions.cpython-314-darwin.so +0 -0
  152. sage/numerical/linear_functions.pxd +31 -0
  153. sage/numerical/linear_functions.pyx +1648 -0
  154. sage/numerical/linear_tensor.py +470 -0
  155. sage/numerical/linear_tensor_constraints.py +448 -0
  156. sage/numerical/linear_tensor_element.cpython-314-darwin.so +0 -0
  157. sage/numerical/linear_tensor_element.pxd +6 -0
  158. sage/numerical/linear_tensor_element.pyx +459 -0
  159. sage/numerical/mip.cpython-314-darwin.so +0 -0
  160. sage/numerical/mip.pxd +40 -0
  161. sage/numerical/mip.pyx +3667 -0
  162. sage/numerical/sdp.cpython-314-darwin.so +0 -0
  163. sage/numerical/sdp.pxd +39 -0
  164. sage/numerical/sdp.pyx +1433 -0
  165. sage/rings/all__sagemath_polyhedra.py +3 -0
  166. sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
  167. sage/rings/polynomial/omega.py +982 -0
  168. sage/schemes/all__sagemath_polyhedra.py +2 -0
  169. sage/schemes/toric/all.py +10 -0
  170. sage/schemes/toric/chow_group.py +1248 -0
  171. sage/schemes/toric/divisor.py +2082 -0
  172. sage/schemes/toric/divisor_class.cpython-314-darwin.so +0 -0
  173. sage/schemes/toric/divisor_class.pyx +322 -0
  174. sage/schemes/toric/fano_variety.py +1606 -0
  175. sage/schemes/toric/homset.py +650 -0
  176. sage/schemes/toric/ideal.py +451 -0
  177. sage/schemes/toric/library.py +1322 -0
  178. sage/schemes/toric/morphism.py +1958 -0
  179. sage/schemes/toric/points.py +1032 -0
  180. sage/schemes/toric/sheaf/all.py +1 -0
  181. sage/schemes/toric/sheaf/constructor.py +302 -0
  182. sage/schemes/toric/sheaf/klyachko.py +921 -0
  183. sage/schemes/toric/toric_subscheme.py +905 -0
  184. sage/schemes/toric/variety.py +3460 -0
  185. sage/schemes/toric/weierstrass.py +1078 -0
  186. sage/schemes/toric/weierstrass_covering.py +457 -0
  187. sage/schemes/toric/weierstrass_higher.py +288 -0
  188. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
  189. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
  190. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
  191. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
  192. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
  193. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
  194. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
  195. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
  196. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
  197. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
  198. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
  199. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
  200. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
  201. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
  202. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
  203. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
  204. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
  205. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
@@ -0,0 +1,1008 @@
1
+ # sage_setup: distribution = sagemath-polyhedra
2
+ r"""
3
+ Point collections
4
+
5
+ This module was designed as a part of framework for toric varieties
6
+ (:mod:`~sage.schemes.toric.variety`,
7
+ :mod:`~sage.schemes.toric.fano_variety`).
8
+
9
+ AUTHORS:
10
+
11
+ - Andrey Novoseltsev (2011-04-25): initial version, based on cone module.
12
+
13
+ - Andrey Novoseltsev (2012-03-06): additions and doctest changes while
14
+ switching cones to use point collections.
15
+
16
+ EXAMPLES:
17
+
18
+ The idea behind :class:`point collections <PointCollection>` is to have a
19
+ container for points of the same space that
20
+
21
+ * behaves like a tuple *without significant performance penalty*::
22
+
23
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
24
+ sage: c[1]
25
+ N(1, 0, 1)
26
+ sage: for point in c: point
27
+ N(0, 0, 1)
28
+ N(1, 0, 1)
29
+ N(0, 1, 1)
30
+ N(1, 1, 1)
31
+
32
+ * prints in a convenient way and with clear indication of the ambient space::
33
+
34
+ sage: c
35
+ N(0, 0, 1),
36
+ N(1, 0, 1),
37
+ N(0, 1, 1),
38
+ N(1, 1, 1)
39
+ in 3-d lattice N
40
+
41
+ * allows (cached) access to alternative representations::
42
+
43
+ sage: c.set()
44
+ frozenset({N(0, 0, 1), N(0, 1, 1), N(1, 0, 1), N(1, 1, 1)})
45
+
46
+ * allows introduction of additional methods::
47
+
48
+ sage: c.basis()
49
+ N(0, 0, 1),
50
+ N(1, 0, 1),
51
+ N(0, 1, 1)
52
+ in 3-d lattice N
53
+
54
+ Examples of natural point collections include ray and line generators of cones,
55
+ vertices and points of polytopes, normals to facets, their subcollections, etc.
56
+
57
+ Using this class for all of the above cases allows for unified interface *and*
58
+ cache sharing. Suppose that `\Delta` is a reflexive polytope. Then the same
59
+ point collection can be linked as
60
+
61
+ #. vertices of `\Delta`;
62
+ #. facet normals of its polar `\Delta^\circ`;
63
+ #. ray generators of the face fan of `\Delta`;
64
+ #. ray generators of the normal fan of `\Delta`.
65
+
66
+ If all these objects are in use and, say, a matrix representation was computed
67
+ for one of them, it becomes available to all others as well, eliminating the
68
+ need to spend time and memory four times.
69
+ """
70
+
71
+ # ***************************************************************************
72
+ # Copyright (C) 2012 Andrey Novoseltsev <novoselt@gmail.com>
73
+ #
74
+ # Distributed under the terms of the GNU General Public License (GPL)
75
+ # as published by the Free Software Foundation; either version 2 of
76
+ # the License, or (at your option) any later version.
77
+ # https://www.gnu.org/licenses/
78
+ # ***************************************************************************
79
+
80
+ from sage.structure.sage_object cimport SageObject
81
+ from sage.structure.richcmp cimport richcmp_not_equal, richcmp
82
+
83
+ from sage.geometry.toric_lattice import ToricLattice
84
+ from sage.matrix.constructor import matrix
85
+ from sage.misc.latex import latex
86
+
87
+
88
+ def is_PointCollection(x):
89
+ r"""
90
+ Check if ``x`` is a :class:`point collection <PointCollection>`.
91
+
92
+ INPUT:
93
+
94
+ - ``x`` -- anything
95
+
96
+ OUTPUT: ``True`` if ``x`` is a point collection and ``False`` otherwise
97
+
98
+ EXAMPLES::
99
+
100
+ sage: from sage.geometry.point_collection import PointCollection
101
+ sage: isinstance(1, PointCollection)
102
+ False
103
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)])
104
+ sage: isinstance(c.rays(), PointCollection)
105
+ True
106
+ """
107
+ from sage.misc.superseded import deprecation_cython
108
+ deprecation_cython(38126,
109
+ "The function is_PointCollection is deprecated; "
110
+ "use 'isinstance(..., PointCollection)' instead.")
111
+ return isinstance(x, PointCollection)
112
+
113
+
114
+ _output_format = "default"
115
+
116
+
117
+ cdef class PointCollection(SageObject):
118
+ r"""
119
+ Create a point collection.
120
+
121
+ .. WARNING::
122
+
123
+ No correctness check or normalization is performed on the input data.
124
+ This class is designed for internal operations and you probably should
125
+ not use it directly.
126
+
127
+ Point collections are immutable, but cache most of the returned values.
128
+
129
+ INPUT:
130
+
131
+ - ``points`` -- an iterable structure of immutable elements of ``module``,
132
+ if ``points`` are already accessible to you as a :class:`tuple`, it is
133
+ preferable to use it for speed and memory consumption reasons;
134
+
135
+ - ``module`` -- an ambient module for ``points``. If ``None`` (the default),
136
+ it will be determined as :func:`parent` of the first point. Of course, this
137
+ cannot be done if there are no points, so in this case you must give an
138
+ appropriate ``module`` directly.
139
+
140
+ OUTPUT:
141
+
142
+ - a point collection.
143
+ """
144
+
145
+ cdef:
146
+ tuple _points
147
+ object _module
148
+ # cache attributes
149
+ PointCollection _basis
150
+ object _matrix
151
+ frozenset _set
152
+
153
+ def __init__(self, points, module=None):
154
+ r"""
155
+ See :class:`PointCollection` for documentation.
156
+
157
+ TESTS::
158
+
159
+ sage: from sage.geometry.point_collection import PointCollection
160
+ sage: v = vector([1,0])
161
+ sage: v.set_immutable()
162
+ sage: c = PointCollection([v], ZZ^2)
163
+ sage: c.module()
164
+ Ambient free module of rank 2
165
+ over the principal ideal domain Integer Ring
166
+ sage: c = PointCollection([v], None)
167
+ sage: c.module() # Determined automatically
168
+ Ambient free module of rank 2
169
+ over the principal ideal domain Integer Ring
170
+ sage: TestSuite(c).run()
171
+ """
172
+ super().__init__()
173
+ self._points = tuple(points)
174
+ self._module = self._points[0].parent() if module is None else module
175
+
176
+ def _sage_input_(self, sib, coerced):
177
+ r"""
178
+ Return Sage command to reconstruct ``self``.
179
+
180
+ See :mod:`sage.misc.sage_input` for details.
181
+
182
+ EXAMPLES::
183
+
184
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
185
+ sage: sage_input(c, verify=True)
186
+ # Verified
187
+ sage.geometry.point_collection.PointCollection((vector(ZZ, [0, 0, 1]), vector(ZZ, [1, 0, 1]), vector(ZZ, [0, 1, 1]), vector(ZZ, [1, 1, 1])))
188
+
189
+ sage: c = sage.geometry.point_collection.PointCollection([], ToricLattice(2, 'U'))
190
+ sage: sage_input(c, verify=True)
191
+ # Verified
192
+ sage.geometry.point_collection.PointCollection((), ToricLattice(2, 'U', 'U*', 'U', 'U^*'))
193
+ """
194
+ args = [sib(self._points)]
195
+ if not self._points or self._module is not self._points[0].parent():
196
+ args.append(sib(self._module))
197
+ return sib.name('sage.geometry.point_collection.PointCollection')(*args)
198
+
199
+ def __add__(left, right):
200
+ r"""
201
+ Return the joint point collection.
202
+
203
+ INPUT:
204
+
205
+ - ``left`` -- a :class:`PointCollection`;
206
+
207
+ - ``right`` -- a :class:`PointCollection`
208
+
209
+ OUTPUT: a :class:`PointCollection`
210
+
211
+ TESTS::
212
+
213
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
214
+ sage: c + c
215
+ N(0, 0, 1),
216
+ N(1, 0, 1),
217
+ N(0, 1, 1),
218
+ N(1, 1, 1),
219
+ N(0, 0, 1),
220
+ N(1, 0, 1),
221
+ N(0, 1, 1),
222
+ N(1, 1, 1)
223
+ in 3-d lattice N
224
+ """
225
+ if not (isinstance(left, PointCollection) and
226
+ isinstance(right, PointCollection)):
227
+ raise NotImplementedError
228
+ cdef PointCollection left_pc = left
229
+ cdef PointCollection right_pc = right
230
+ if left_pc._module is not right_pc._module:
231
+ raise NotImplementedError
232
+ return PointCollection(left_pc._points + right_pc._points,
233
+ left_pc._module)
234
+
235
+ def __call__(self, *args):
236
+ r"""
237
+ Return a subcollection of ``self``.
238
+
239
+ INPUT:
240
+
241
+ - a list of integers (as a single or many arguments).
242
+
243
+ OUTPUT: a :class:`point collection <PointCollection>`
244
+
245
+ TESTS::
246
+
247
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
248
+ sage: c()
249
+ Empty collection
250
+ in 3-d lattice N
251
+ sage: c(2,1)
252
+ N(0, 1, 1),
253
+ N(1, 0, 1)
254
+ in 3-d lattice N
255
+ sage: c(range(4)) == c
256
+ True
257
+ """
258
+ if len(args) == 1:
259
+ try:
260
+ args = tuple(args[0])
261
+ except TypeError:
262
+ pass
263
+ # Avoid creating a copy of self
264
+ if len(args) == len(self) and args == tuple(range(len(self))):
265
+ return self
266
+ else:
267
+ return PointCollection([self[i] for i in args], self._module)
268
+
269
+ def __richcmp__(self, right, op):
270
+ r"""
271
+ Compare ``self`` and ``right`` according to the operator ``op``.
272
+
273
+ INPUT:
274
+
275
+ - ``right`` -- another PointCollection
276
+
277
+ OUTPUT: boolean
278
+
279
+ First compare according to the underlying :meth:`module`
280
+ and then according to the list of points.
281
+
282
+ TESTS::
283
+
284
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
285
+ sage: d = Cone([(0,1,2), (1,0,1), (0,1,1), (1,1,1)]).rays()
286
+ sage: c == c
287
+ True
288
+ sage: c == d
289
+ False
290
+ """
291
+ cdef PointCollection left_pc, right_pc
292
+ try:
293
+ left_pc = <PointCollection?>self
294
+ right_pc = <PointCollection?>right
295
+ except TypeError:
296
+ return NotImplemented
297
+
298
+ left_m = left_pc._module
299
+ right_m = right_pc._module
300
+ if left_m != right_m:
301
+ return richcmp_not_equal(left_m, right_m, op)
302
+ return richcmp(left_pc._points, right_pc._points, op)
303
+
304
+ def __getitem__(self, n):
305
+ r"""
306
+ Return the ``n``-th point of ``self``.
307
+
308
+ INPUT:
309
+
310
+ - ``n`` -- integer
311
+
312
+ OUTPUT: a point, an element of the ambient :meth:`module` of ``self``
313
+
314
+ EXAMPLES::
315
+
316
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
317
+ sage: c[0]
318
+ N(0, 0, 1)
319
+ """
320
+ return self._points[n]
321
+
322
+ def __hash__(self):
323
+ r"""
324
+ Return the hash of ``self``.
325
+
326
+ OUTPUT: integer
327
+
328
+ TESTS::
329
+
330
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
331
+ sage: hash(c) == hash(c)
332
+ True
333
+ """
334
+ return hash(self._points)
335
+
336
+ def __iter__(self):
337
+ r"""
338
+ Return an iterator over points of ``self``.
339
+
340
+ OUTPUT: an iterator
341
+
342
+ TESTS::
343
+
344
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
345
+ sage: for point in c: print(point)
346
+ N(0, 0, 1)
347
+ N(1, 0, 1)
348
+ N(0, 1, 1)
349
+ N(1, 1, 1)
350
+ """
351
+ return iter(self._points)
352
+
353
+ def __len__(self):
354
+ r"""
355
+ Return the number of points in ``self``.
356
+
357
+ OUTPUT: integer
358
+
359
+ EXAMPLES::
360
+
361
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
362
+ sage: len(c)
363
+ 4
364
+ """
365
+ return len(self._points)
366
+
367
+ def __list__(self):
368
+ r"""
369
+ Return a list of points of ``self``.
370
+
371
+ OUTPUT: list
372
+
373
+ TESTS::
374
+
375
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
376
+ sage: list(c)
377
+ [N(0, 0, 1), N(1, 0, 1), N(0, 1, 1), N(1, 1, 1)]
378
+ """
379
+ return list(self._points)
380
+
381
+ def __mul__(left, right):
382
+ r"""
383
+ Return the product ``left * right``.
384
+
385
+ INPUT:
386
+
387
+ - a :class:`point collection <PointCollection>` and something that can
388
+ act both on ``self.module().zero()`` and either ``self.matrix()`` from
389
+ the right or ``self.column_matrix()`` from the left.
390
+
391
+ OUTPUT:
392
+
393
+ - the result of ``self.matrix() * right``, provided that
394
+ ``self.module().zero() * right`` can be computed.
395
+
396
+ The idea of this method is to provide a shortcut for matrix
397
+ multiplication with appropriate type checks, in particular, it is not
398
+ possible to multiply by a point of the same toric lattice as elements of
399
+ ``self``.
400
+
401
+ TESTS::
402
+
403
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
404
+ sage: c.matrix()
405
+ [0 0 1]
406
+ [1 0 1]
407
+ [0 1 1]
408
+ [1 1 1]
409
+ sage: c * c[0]
410
+ Traceback (most recent call last):
411
+ ...
412
+ TypeError: elements of the same toric lattice cannot be multiplied!
413
+
414
+ If you really need such a product, state it explicitly::
415
+
416
+ sage: c.matrix() * c[0]
417
+ (1, 1, 1, 1)
418
+
419
+ Multiplication by matrices works as well::
420
+
421
+ sage: c * c.column_matrix()
422
+ [1 1 1 1]
423
+ [1 2 1 2]
424
+ [1 1 2 2]
425
+ [1 2 2 3]
426
+ """
427
+ cdef PointCollection pc
428
+ if isinstance(left, PointCollection):
429
+ pc = left
430
+ # Check that it is possible to act on points.
431
+ pc._module.zero() * right
432
+ return pc.matrix() * right
433
+ if isinstance(right, PointCollection):
434
+ pc = right
435
+ # Check that it is possible to act on points.
436
+ left * pc._module.zero()
437
+ return left * pc.column_matrix()
438
+ raise NotImplementedError
439
+
440
+ def __reduce__(self):
441
+ r"""
442
+ Prepare ``self`` for pickling.
443
+
444
+ OUTPUT:
445
+
446
+ - a tuple, currently the class name and a tuple consisting of points
447
+ and the ambient module.
448
+
449
+ TESTS::
450
+
451
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
452
+ sage: loads(dumps(c))
453
+ N(0, 0, 1),
454
+ N(1, 0, 1),
455
+ N(0, 1, 1),
456
+ N(1, 1, 1)
457
+ in 3-d lattice N
458
+ sage: loads(dumps(c)) == c
459
+ True
460
+ """
461
+ return (PointCollection, (self._points, self._module))
462
+
463
+ def __tuple__(self):
464
+ r"""
465
+ Return the tuple of points of ``self``.
466
+
467
+ OUTPUT: a tuple
468
+
469
+ TESTS::
470
+
471
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
472
+ sage: tuple(c)
473
+ (N(0, 0, 1), N(1, 0, 1), N(0, 1, 1), N(1, 1, 1))
474
+ """
475
+ return self._points
476
+
477
+ def _latex_(self):
478
+ r"""
479
+ Return a LaTeX representation of ``self``.
480
+
481
+ OUTPUT: string
482
+
483
+ TESTS::
484
+
485
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
486
+ sage: print(c._latex_())
487
+ \left(\left(0,\,0,\,1\right)_{N}, \left(1,\,0,\,1\right)_{N},
488
+ \left(0,\,1,\,1\right)_{N}, \left(1,\,1,\,1\right)_{N}\right)_{N}
489
+ """
490
+ global _output_format
491
+ if _output_format in ["default", "tuple"]:
492
+ r = latex(tuple(self))
493
+ elif _output_format == "matrix":
494
+ r = latex(self.matrix())
495
+ elif _output_format == "column matrix":
496
+ r = latex(self.column_matrix())
497
+ elif _output_format == "separated column matrix":
498
+ r = latex(self.column_matrix())
499
+ r = r.replace("r" * len(self), "|".join("r" * len(self)))
500
+ return r"%s_{%s}" % (r, latex(self.module()))
501
+
502
+ def _matrix_(self, ring=None):
503
+ r"""
504
+ Return a matrix whose rows are points of ``self``.
505
+
506
+ INPUT:
507
+
508
+ - ``ring`` -- a base ring for the returned matrix (default: base ring of
509
+ :meth:`module` of ``self``)
510
+
511
+ OUTPUT: a :class:`matrix <Matrix>`
512
+
513
+ EXAMPLES::
514
+
515
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
516
+ sage: matrix(c) # indirect doctest
517
+ [0 0 1]
518
+ [1 0 1]
519
+ [0 1 1]
520
+ [1 1 1]
521
+ """
522
+ if ring is None:
523
+ return self.matrix()
524
+ else:
525
+ return self.matrix().change_ring(ring)
526
+
527
+ def _repr_(self):
528
+ r"""
529
+ Return a string representation of ``self``.
530
+
531
+ OUTPUT: string
532
+
533
+ TESTS::
534
+
535
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
536
+ sage: print(c._repr_())
537
+ N(0, 0, 1),
538
+ N(1, 0, 1),
539
+ N(0, 1, 1),
540
+ N(1, 1, 1)
541
+ in 3-d lattice N
542
+ """
543
+ global _output_format
544
+ if _output_format == "default":
545
+ r = map(repr, self)
546
+ r = [point.split(",") for point in r]
547
+ if not r:
548
+ r = "Empty collection"
549
+ else:
550
+ if "(" in r[0][0]:
551
+ delimiter = "("
552
+ elif "[" in r[0][0]:
553
+ delimiter = "["
554
+ else:
555
+ raise ValueError("cannot parse point representation!")
556
+ heads = []
557
+ for point in r:
558
+ head, point[0] = point[0].rsplit(delimiter, 1)
559
+ heads.append(head + delimiter)
560
+ format = "{{:<{}}}".format(max(map(len, heads)))
561
+ widths = [0] * len(r[0])
562
+ for point in r:
563
+ for i, coordinate in enumerate(point):
564
+ widths[i] = max(widths[i], len(coordinate))
565
+ format += ",".join("{{:>{}}}".format(width) for width in widths)
566
+ r = ",\n".join(format.format(head, *point)
567
+ for head, point in zip(heads, r))
568
+ elif _output_format == "tuple":
569
+ r = tuple(self)
570
+ elif _output_format == "matrix":
571
+ r = self.matrix()
572
+ else:
573
+ r = self.column_matrix()
574
+ return "{}\nin {}".format(r, self.module())
575
+
576
+ def basis(self):
577
+ r"""
578
+ Return a linearly independent subset of points of ``self``.
579
+
580
+ OUTPUT:
581
+
582
+ - a :class:`point collection <PointCollection>` giving a random (but
583
+ fixed) choice of an `\RR`-basis for the vector space spanned by the
584
+ points of ``self``.
585
+
586
+ EXAMPLES::
587
+
588
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
589
+ sage: c.basis()
590
+ N(0, 0, 1),
591
+ N(1, 0, 1),
592
+ N(0, 1, 1)
593
+ in 3-d lattice N
594
+
595
+ Calling this method twice will always return *exactly the same* point
596
+ collection::
597
+
598
+ sage: c.basis().basis() is c.basis()
599
+ True
600
+ """
601
+ if self._basis is None:
602
+ self._basis = self(self.matrix().pivot_rows())
603
+ return self._basis
604
+
605
+ def cardinality(self):
606
+ r"""
607
+ Return the number of points in ``self``.
608
+
609
+ OUTPUT: integer
610
+
611
+ EXAMPLES::
612
+
613
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
614
+ sage: c.cardinality()
615
+ 4
616
+ """
617
+ return len(self._points)
618
+
619
+ def cartesian_product(self, other, module=None):
620
+ r"""
621
+ Return the Cartesian product of ``self`` with ``other``.
622
+
623
+ INPUT:
624
+
625
+ - ``other`` -- a :class:`point collection <PointCollection>`;
626
+
627
+ - ``module`` -- (optional) the ambient module for the result. By
628
+ default, the direct sum of the ambient modules of ``self`` and
629
+ ``other`` is constructed.
630
+
631
+ OUTPUT: a :class:`point collection <PointCollection>`
632
+
633
+ EXAMPLES::
634
+
635
+ sage: c = Cone([(0,0,1), (1,1,1)]).rays()
636
+ sage: c.cartesian_product(c)
637
+ N+N(0, 0, 1, 0, 0, 1),
638
+ N+N(1, 1, 1, 0, 0, 1),
639
+ N+N(0, 0, 1, 1, 1, 1),
640
+ N+N(1, 1, 1, 1, 1, 1)
641
+ in 6-d lattice N+N
642
+ """
643
+ assert isinstance(other, PointCollection)
644
+ if module is None:
645
+ module = self._module.direct_sum(other.module())
646
+ P = [list(p) for p in self]
647
+ Q = [list(q) for q in other]
648
+ PQ = [module(p + q) for q in Q for p in P]
649
+ for pq in PQ:
650
+ pq.set_immutable()
651
+ return PointCollection(PQ, module)
652
+
653
+ def column_matrix(self):
654
+ r"""
655
+ Return a matrix whose columns are points of ``self``.
656
+
657
+ OUTPUT: a :class:`matrix <Matrix>`
658
+
659
+ EXAMPLES::
660
+
661
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
662
+ sage: c.column_matrix()
663
+ [0 1 0 1]
664
+ [0 0 1 1]
665
+ [1 1 1 1]
666
+ """
667
+ return self.matrix().transpose()
668
+
669
+ def dimension(self):
670
+ r"""
671
+ Return the dimension of the space spanned by points of ``self``.
672
+
673
+ .. NOTE:: You can use either :meth:`dim` or :meth:`dimension`.
674
+
675
+ OUTPUT: integer
676
+
677
+ EXAMPLES::
678
+
679
+ sage: c = Cone([(0,0,1), (1,1,1)]).rays()
680
+ sage: c.dimension()
681
+ 2
682
+ sage: c.dim()
683
+ 2
684
+ """
685
+ return self.matrix().rank()
686
+
687
+ dim = dimension
688
+
689
+ def dual_module(self):
690
+ r"""
691
+ Return the dual of the ambient module of ``self``.
692
+
693
+ OUTPUT:
694
+
695
+ - a :class:`module <FreeModule_generic>`. If possible (that is, if the
696
+ ambient :meth:`module` `M` of ``self`` has a ``dual()`` method), the
697
+ dual module is returned. Otherwise, `R^n` is returned, where `n` is
698
+ the dimension of `M` and `R` is its base ring.
699
+
700
+ EXAMPLES::
701
+
702
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
703
+ sage: c.dual_module()
704
+ 3-d lattice M
705
+ """
706
+ M = self._module
707
+ try:
708
+ return M.dual()
709
+ except AttributeError:
710
+ # TODO: add support for torsion modules as well?
711
+ return M.base_ring() ** M.dimension()
712
+
713
+ def index(self, *args):
714
+ r"""
715
+ Return the index of the first occurrence of ``point`` in ``self``.
716
+
717
+ INPUT:
718
+
719
+ - ``point`` -- a point of ``self``
720
+
721
+ - ``start`` -- (optional) an integer, if given, the search will start
722
+ at this position
723
+
724
+ - ``stop`` -- (optional) an integer, if given, the search will stop
725
+ at this position
726
+
727
+ OUTPUT: an integer if ``point`` is in ``self[start:stop]``, otherwise a
728
+ :exc:`ValueError` exception is raised
729
+
730
+ EXAMPLES::
731
+
732
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
733
+ sage: c.index((0,1,1))
734
+ Traceback (most recent call last):
735
+ ...
736
+ ValueError: tuple.index(x): x not in tuple
737
+
738
+ Note that this was not a mistake: the *tuple* ``(0,1,1)`` is *not* a
739
+ point of ``c``! We need to pass actual element of the ambient module of
740
+ ``c`` to get their indices::
741
+
742
+ sage: N = c.module()
743
+ sage: c.index(N(0,1,1))
744
+ 2
745
+ sage: c[2]
746
+ N(0, 1, 1)
747
+ """
748
+ return self._points.index(*args)
749
+
750
+ def matrix(self):
751
+ r"""
752
+ Return a matrix whose rows are points of ``self``.
753
+
754
+ OUTPUT: a :class:`matrix <Matrix>`
755
+
756
+ EXAMPLES::
757
+
758
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
759
+ sage: c.matrix()
760
+ [0 0 1]
761
+ [1 0 1]
762
+ [0 1 1]
763
+ [1 1 1]
764
+ """
765
+ if self._matrix is None:
766
+ M = matrix(self._module.base_ring(), len(self._points),
767
+ self._module.degree(), self._points)
768
+ M.set_immutable()
769
+ self._matrix = M
770
+ return self._matrix
771
+
772
+ def module(self):
773
+ r"""
774
+ Return the ambient module of ``self``.
775
+
776
+ OUTPUT: a :class:`module <FreeModule_generic>`
777
+
778
+ EXAMPLES::
779
+
780
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
781
+ sage: c.module()
782
+ 3-d lattice N
783
+ """
784
+ return self._module
785
+
786
+ @staticmethod
787
+ def output_format(format=None):
788
+ r"""
789
+ Return or set the output format for **ALL** point collections.
790
+
791
+ INPUT:
792
+
793
+ - ``format`` -- (optional) if given, must be one of the strings
794
+ * "default" -- output one point per line with vertical alignment of
795
+ coordinates in text mode, same as "tuple" for LaTeX;
796
+ * "tuple" -- output ``tuple(self)`` with lattice information;
797
+ * "matrix" -- output :meth:`matrix` with lattice information;
798
+ * "column matrix" -- output :meth:`column_matrix` with lattice
799
+ information;
800
+ * "separated column matrix" -- same as "column matrix" for text
801
+ mode, for LaTeX separate columns by lines (not shown by jsMath).
802
+
803
+ OUTPUT:
804
+
805
+ - a string with the current format (only if ``format`` was omitted).
806
+
807
+ This function affects both regular and LaTeX output.
808
+
809
+ EXAMPLES::
810
+
811
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
812
+ sage: c
813
+ N(0, 0, 1),
814
+ N(1, 0, 1),
815
+ N(0, 1, 1),
816
+ N(1, 1, 1)
817
+ in 3-d lattice N
818
+ sage: c.output_format()
819
+ 'default'
820
+ sage: c.output_format("tuple")
821
+ sage: c
822
+ (N(0, 0, 1), N(1, 0, 1), N(0, 1, 1), N(1, 1, 1))
823
+ in 3-d lattice N
824
+ sage: c.output_format("matrix")
825
+ sage: c
826
+ [0 0 1]
827
+ [1 0 1]
828
+ [0 1 1]
829
+ [1 1 1]
830
+ in 3-d lattice N
831
+ sage: c.output_format("column matrix")
832
+ sage: c
833
+ [0 1 0 1]
834
+ [0 0 1 1]
835
+ [1 1 1 1]
836
+ in 3-d lattice N
837
+ sage: c.output_format("separated column matrix")
838
+ sage: c
839
+ [0 1 0 1]
840
+ [0 0 1 1]
841
+ [1 1 1 1]
842
+ in 3-d lattice N
843
+
844
+ Note that the last two outputs are identical, separators are only
845
+ inserted in the LaTeX mode::
846
+
847
+ sage: latex(c)
848
+ \left(\begin{array}{r|r|r|r}
849
+ 0 & 1 & 0 & 1 \\
850
+ 0 & 0 & 1 & 1 \\
851
+ 1 & 1 & 1 & 1
852
+ \end{array}\right)_{N}
853
+
854
+ Since this is a static method, you can call it for the class directly::
855
+
856
+ sage: from sage.geometry.point_collection import PointCollection
857
+ sage: PointCollection.output_format("default")
858
+ sage: c
859
+ N(0, 0, 1),
860
+ N(1, 0, 1),
861
+ N(0, 1, 1),
862
+ N(1, 1, 1)
863
+ in 3-d lattice N
864
+ """
865
+ global _output_format
866
+ if format is None:
867
+ return _output_format
868
+ assert format in ["default", "tuple", "matrix", "column matrix",
869
+ "separated column matrix"]
870
+ _output_format = format
871
+
872
+ def set(self):
873
+ r"""
874
+ Return points of ``self`` as a :class:`frozenset`.
875
+
876
+ OUTPUT: a :class:`frozenset`
877
+
878
+ EXAMPLES::
879
+
880
+ sage: c = Cone([(0,0,1), (1,0,1), (0,1,1), (1,1,1)]).rays()
881
+ sage: c.set()
882
+ frozenset({N(0, 0, 1), N(0, 1, 1), N(1, 0, 1), N(1, 1, 1)})
883
+ """
884
+ if self._set is None:
885
+ self._set = frozenset(self._points)
886
+ return self._set
887
+
888
+ def write_for_palp(self, f):
889
+ r"""
890
+ Write ``self`` into an open file ``f`` in PALP format.
891
+
892
+ INPUT:
893
+
894
+ - ``f`` -- a file opened for writing
895
+
896
+ EXAMPLES::
897
+
898
+ sage: o = lattice_polytope.cross_polytope(3)
899
+ sage: from io import StringIO
900
+ sage: f = StringIO()
901
+ sage: o.vertices().write_for_palp(f)
902
+ sage: print(f.getvalue())
903
+ 6 3
904
+ 1 0 0
905
+ 0 1 0
906
+ 0 0 1
907
+ -1 0 0
908
+ 0 -1 0
909
+ 0 0 -1
910
+ """
911
+ f.write('{} {}\n'.format(len(self), self._module.rank()))
912
+ f.write('\n'.join(' '.join(str(c) for c in p) for p in self))
913
+ f.write('\n')
914
+
915
+
916
+ def read_palp_point_collection(f, lattice=None, permutation=False):
917
+ r"""
918
+ Read and return a point collection from an opened file.
919
+
920
+ Data must be in PALP format:
921
+
922
+ * the first input line starts with two integers `m` and `n`, the number
923
+ of points and the number of components of each;
924
+
925
+ * the rest of the first line may contain a permutation;
926
+
927
+ * the next `m` lines contain `n` numbers each.
928
+
929
+ .. NOTE::
930
+
931
+ If `m` < `n`, it is assumed (for compatibility with PALP) that the
932
+ matrix is transposed, i.e. that each column is a point.
933
+
934
+ INPUT:
935
+
936
+ - ``f`` -- an opened file with PALP output
937
+
938
+ - ``lattice`` -- the lattice for points. If not given, the
939
+ :class:`toric lattice <sage.geometry.toric_lattice.ToricLatticeFactory>`
940
+ `M` of dimension `n` will be used.
941
+
942
+ - ``permutation`` -- boolean (default: ``False``); if ``True``, try to retrieve
943
+ the permutation. This parameter makes sense only when PALP computed the
944
+ normal form of a lattice polytope.
945
+
946
+ OUTPUT:
947
+
948
+ - a :class:`point collection <PointCollection>`, optionally followed by
949
+ a permutation. ``None`` if EOF is reached.
950
+
951
+ EXAMPLES::
952
+
953
+ sage: data = "3 2 regular\n1 2\n3 4\n5 6\n2 3 transposed\n1 2 3\n4 5 6"
954
+ sage: print(data)
955
+ 3 2 regular
956
+ 1 2
957
+ 3 4
958
+ 5 6
959
+ 2 3 transposed
960
+ 1 2 3
961
+ 4 5 6
962
+ sage: from io import StringIO
963
+ sage: f = StringIO(data)
964
+ sage: from sage.geometry.point_collection \
965
+ ....: import read_palp_point_collection
966
+ sage: read_palp_point_collection(f)
967
+ M(1, 2),
968
+ M(3, 4),
969
+ M(5, 6)
970
+ in 2-d lattice M
971
+ sage: read_palp_point_collection(f)
972
+ M(1, 4),
973
+ M(2, 5),
974
+ M(3, 6)
975
+ in 2-d lattice M
976
+ sage: read_palp_point_collection(f) is None
977
+ True
978
+ """
979
+ cdef int i, j, m, n
980
+ first_line = f.readline()
981
+ if first_line == "":
982
+ return None
983
+ first_line = first_line.split()
984
+ m = int(first_line[0])
985
+ n = int(first_line[1])
986
+ if m >= n:
987
+ # Typical situation: a point on each line
988
+ lattice = lattice or ToricLattice(n).dual()
989
+ points = [lattice.element_class(lattice, f.readline().split())
990
+ for i in range(m)]
991
+ else:
992
+ # Also may appear as PALP output, e.g. points of 3-d polytopes
993
+ lattice = lattice or ToricLattice(m).dual()
994
+ data = [f.readline().split() for j in range(m)]
995
+ points = [lattice.element_class(lattice, [data[j][i] for j in range(m)])
996
+ for i in range(n)]
997
+ for p in points:
998
+ p.set_immutable()
999
+ pc = PointCollection(points, lattice)
1000
+ if permutation:
1001
+ last_piece = first_line[-1].split('=')
1002
+ if last_piece[0] != 'perm':
1003
+ raise ValueError('permutation was requested but not found')
1004
+ from sage.geometry.lattice_polytope import _palp_convert_permutation
1005
+ p = _palp_convert_permutation(last_piece[1])
1006
+ return (pc, p)
1007
+ else:
1008
+ return pc