passagemath-latte-4ti2 10.6.30__cp311-cp311-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-latte-4ti2 might be problematic. Click here for more details.

Files changed (81) hide show
  1. passagemath_latte_4ti2-10.6.30.dist-info/METADATA +156 -0
  2. passagemath_latte_4ti2-10.6.30.dist-info/RECORD +81 -0
  3. passagemath_latte_4ti2-10.6.30.dist-info/WHEEL +6 -0
  4. passagemath_latte_4ti2-10.6.30.dist-info/top_level.txt +2 -0
  5. passagemath_latte_4ti2.dylibs/lib4ti2common.0.dylib +0 -0
  6. passagemath_latte_4ti2.dylibs/lib4ti2gmp.0.dylib +0 -0
  7. passagemath_latte_4ti2.dylibs/lib4ti2int32.0.dylib +0 -0
  8. passagemath_latte_4ti2.dylibs/lib4ti2int64.0.dylib +0 -0
  9. passagemath_latte_4ti2.dylibs/lib4ti2util.0.dylib +0 -0
  10. passagemath_latte_4ti2.dylibs/libLiDIA.0.dylib +0 -0
  11. passagemath_latte_4ti2.dylibs/libcddgmp.0.dylib +0 -0
  12. passagemath_latte_4ti2.dylibs/libgf2x.3.dylib +0 -0
  13. passagemath_latte_4ti2.dylibs/libglpk.40.dylib +0 -0
  14. passagemath_latte_4ti2.dylibs/libgmp.10.dylib +0 -0
  15. passagemath_latte_4ti2.dylibs/libgmpxx.4.dylib +0 -0
  16. passagemath_latte_4ti2.dylibs/liblatte.0.dylib +0 -0
  17. passagemath_latte_4ti2.dylibs/libnormalize.0.dylib +0 -0
  18. passagemath_latte_4ti2.dylibs/libntl.44.dylib +0 -0
  19. passagemath_latte_4ti2.dylibs/libzsolve.0.dylib +0 -0
  20. sage/all__sagemath_latte_4ti2.py +4 -0
  21. sage/interfaces/all__sagemath_latte_4ti2.py +1 -0
  22. sage/interfaces/four_ti_2.py +531 -0
  23. sage/interfaces/latte.py +632 -0
  24. sage/libs/all__sagemath_latte_4ti2.py +1 -0
  25. sage/libs/latte_int.cpython-311-darwin.so +0 -0
  26. sage/libs/latte_int.pyx +1 -0
  27. sage_wheels/bin/4ti2gmp +0 -0
  28. sage_wheels/bin/4ti2int32 +0 -0
  29. sage_wheels/bin/4ti2int64 +0 -0
  30. sage_wheels/bin/ConvertCDDextToLatte +0 -0
  31. sage_wheels/bin/ConvertCDDextToLatte.bin +0 -0
  32. sage_wheels/bin/ConvertCDDineToLatte +0 -0
  33. sage_wheels/bin/ConvertCDDineToLatte.bin +0 -0
  34. sage_wheels/bin/circuits +64 -0
  35. sage_wheels/bin/count +0 -0
  36. sage_wheels/bin/count-linear-forms-from-polynomial +0 -0
  37. sage_wheels/bin/count-linear-forms-from-polynomial.bin +0 -0
  38. sage_wheels/bin/count.bin +0 -0
  39. sage_wheels/bin/ehrhart +0 -0
  40. sage_wheels/bin/ehrhart.bin +0 -0
  41. sage_wheels/bin/ehrhart3 +0 -0
  42. sage_wheels/bin/ehrhart3.bin +0 -0
  43. sage_wheels/bin/genmodel +0 -0
  44. sage_wheels/bin/gensymm +0 -0
  45. sage_wheels/bin/graver +17 -0
  46. sage_wheels/bin/groebner +64 -0
  47. sage_wheels/bin/hilbert +17 -0
  48. sage_wheels/bin/hilbert-from-rays +0 -0
  49. sage_wheels/bin/hilbert-from-rays-symm +0 -0
  50. sage_wheels/bin/hilbert-from-rays-symm.bin +0 -0
  51. sage_wheels/bin/hilbert-from-rays.bin +0 -0
  52. sage_wheels/bin/integrate +0 -0
  53. sage_wheels/bin/integrate.bin +0 -0
  54. sage_wheels/bin/latte-maximize +0 -0
  55. sage_wheels/bin/latte-maximize.bin +0 -0
  56. sage_wheels/bin/latte-minimize +0 -0
  57. sage_wheels/bin/latte-minimize.bin +0 -0
  58. sage_wheels/bin/latte2ext +0 -0
  59. sage_wheels/bin/latte2ext.bin +0 -0
  60. sage_wheels/bin/latte2ine +0 -0
  61. sage_wheels/bin/latte2ine.bin +0 -0
  62. sage_wheels/bin/markov +64 -0
  63. sage_wheels/bin/minimize +64 -0
  64. sage_wheels/bin/normalform +64 -0
  65. sage_wheels/bin/output +0 -0
  66. sage_wheels/bin/polyhedron-to-cones +0 -0
  67. sage_wheels/bin/polyhedron-to-cones.bin +0 -0
  68. sage_wheels/bin/ppi +0 -0
  69. sage_wheels/bin/qsolve +64 -0
  70. sage_wheels/bin/rays +64 -0
  71. sage_wheels/bin/top-ehrhart-knapsack +0 -0
  72. sage_wheels/bin/top-ehrhart-knapsack.bin +0 -0
  73. sage_wheels/bin/triangulate +0 -0
  74. sage_wheels/bin/triangulate.bin +0 -0
  75. sage_wheels/bin/walk +64 -0
  76. sage_wheels/bin/zbasis +64 -0
  77. sage_wheels/bin/zsolve +0 -0
  78. sage_wheels/share/latte-int/m-knapsack.mpl +1245 -0
  79. sage_wheels/share/latte-int/simplify.add +7 -0
  80. sage_wheels/share/latte-int/simplify2.add +9 -0
  81. sage_wheels/share/latte-int/simplify3.add +13 -0
@@ -0,0 +1,632 @@
1
+ # sage_setup: distribution = sagemath-latte-4ti2
2
+ # sage.doctest: optional - latte_int
3
+ r"""
4
+ Interface to LattE integrale programs
5
+ """
6
+ # ****************************************************************************
7
+ # Copyright (C) 2017 Vincent Delecroix <vincent.delecroix@gmail.com>
8
+ #
9
+ # This program is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 2 of the License, or
12
+ # (at your option) any later version.
13
+ # https://www.gnu.org/licenses/
14
+ # ****************************************************************************
15
+
16
+
17
+ from sage.cpython.string import str_to_bytes, bytes_to_str
18
+
19
+ from subprocess import Popen, PIPE
20
+ from sage.rings.integer import Integer
21
+ from sage.features.latte import Latte_count, Latte_integrate
22
+
23
+
24
+ def count(arg, ehrhart_polynomial=False, multivariate_generating_function=False, raw_output=False, verbose=False, **kwds):
25
+ r"""
26
+ Call to the program count from LattE integrale.
27
+
28
+ INPUT:
29
+
30
+ - ``arg`` -- a cdd or LattE description string
31
+
32
+ - ``ehrhart_polynomial``, ``multivariate_generating_function`` -- to
33
+ compute Ehrhart polynomial or multivariate generating function instead of
34
+ just counting points
35
+
36
+ - ``raw_output`` -- if ``True`` then return directly the output string from LattE
37
+
38
+ - For all other options of the count program, consult the LattE manual
39
+
40
+ - ``name`` -- -- (default: ``'y'``) a string
41
+
42
+ The variable names of the Laurent polynomial ring of the multivariate_generating_function
43
+
44
+ - ``Factorization_sort`` (default: ``False``) and
45
+ ``Factorization_simplify`` (default: ``False``) -- booleans
46
+
47
+ These are passed on to
48
+ :class:`sage.structure.factorization.Factorization` when creating
49
+ the result.
50
+
51
+ OUTPUT:
52
+
53
+ Either a string (if ``raw_output`` if set to ``True``) or an integer (when
54
+ counting points), or a polynomial (if ``ehrhart_polynomial`` is set to
55
+ ``True``) or a tuple of ``Factorization`` objects
56
+ :class:`~sage.structure.factorization.Factorization` whose factors are Laurent polynomials
57
+ (if ``multivariate_generating_function`` is set to ``True``)
58
+
59
+ EXAMPLES::
60
+
61
+ sage: from sage.interfaces.latte import count
62
+ sage: P = 2 * polytopes.cube()
63
+
64
+ Counting integer points from either the H or V representation::
65
+
66
+ sage: count(P.cdd_Hrepresentation(), cdd=True) # optional - latte_int
67
+ 125
68
+ sage: count(P.cdd_Vrepresentation(), cdd=True) # optional - latte_int
69
+ 125
70
+
71
+ Ehrhart polynomial::
72
+
73
+ sage: count(P.cdd_Hrepresentation(), cdd=True, # optional - latte_int
74
+ ....: ehrhart_polynomial=True)
75
+ 64*t^3 + 48*t^2 + 12*t + 1
76
+
77
+ Returning a string of the multivariate generating function when ``raw_output=True``.
78
+ Returning the summands of the multivariate generating function in a tuple of ``Factorization`` objects
79
+ with the same format as
80
+ :meth:`sage.geometry.polyhedron.generating_function.generating_function_of_integral_points`
81
+ does when ``result_as_tuple=True``::
82
+
83
+ sage: opts = {'cdd': True,
84
+ ....: 'multivariate_generating_function': True,
85
+ ....: 'raw_output': True}
86
+ sage: cddin = P.cdd_Hrepresentation()
87
+ sage: print(count(cddin, **opts)) # optional - latte_int
88
+ x[0]^2*x[1]^(-2)*x[2]^(-2)/((1-x[1])*(1-x[2])*(1-x[0]^(-1)))
89
+ + x[0]^(-2)*x[1]^(-2)*x[2]^(-2)/((1-x[1])*(1-x[2])*(1-x[0]))
90
+ + x[0]^2*x[1]^(-2)*x[2]^2/((1-x[1])*(1-x[2]^(-1))*(1-x[0]^(-1)))
91
+ + x[0]^(-2)*x[1]^(-2)*x[2]^2/((1-x[1])*(1-x[0])*(1-x[2]^(-1)))
92
+ + x[0]^2*x[1]^2*x[2]^(-2)/((1-x[2])*(1-x[1]^(-1))*(1-x[0]^(-1)))
93
+ + x[0]^(-2)*x[1]^2*x[2]^(-2)/((1-x[2])*(1-x[0])*(1-x[1]^(-1)))
94
+ + x[0]^2*x[1]^2*x[2]^2/((1-x[2]^(-1))*(1-x[1]^(-1))*(1-x[0]^(-1)))
95
+ + x[0]^(-2)*x[1]^2*x[2]^2/((1-x[0])*(1-x[2]^(-1))*(1-x[1]^(-1)))
96
+ sage: count(cddin, cdd=True, multivariate_generating_function=True) # optional - latte_int
97
+ ((y0^2*y1^-2*y2^-2) * (-y1 + 1)^-1 * (-y2 + 1)^-1 * (1 - y0^-1)^-1,
98
+ (y0^-2*y1^-2*y2^-2) * (-y1 + 1)^-1 * (-y2 + 1)^-1 * (-y0 + 1)^-1,
99
+ (y0^2*y1^-2*y2^2) * (-y1 + 1)^-1 * (1 - y2^-1)^-1 * (1 - y0^-1)^-1,
100
+ (y0^-2*y1^-2*y2^2) * (-y1 + 1)^-1 * (-y0 + 1)^-1 * (1 - y2^-1)^-1,
101
+ (y0^2*y1^2*y2^-2) * (-y2 + 1)^-1 * (1 - y1^-1)^-1 * (1 - y0^-1)^-1,
102
+ (y0^-2*y1^2*y2^-2) * (-y2 + 1)^-1 * (-y0 + 1)^-1 * (1 - y1^-1)^-1,
103
+ y0^2*y1^2*y2^2 * (1 - y2^-1)^-1 * (1 - y1^-1)^-1 * (1 - y0^-1)^-1,
104
+ (y0^-2*y1^2*y2^2) * (-y0 + 1)^-1 * (1 - y2^-1)^-1 * (1 - y1^-1)^-1)
105
+
106
+ TESTS:
107
+
108
+ Testing raw output::
109
+
110
+ sage: from sage.interfaces.latte import count
111
+ sage: P = polytopes.cuboctahedron()
112
+ sage: cddin = P.cdd_Vrepresentation()
113
+ sage: count(cddin, cdd=True, raw_output=True) # optional - latte_int
114
+ '19'
115
+ sage: count(cddin, cdd=True, raw_output=True, ehrhart_polynomial=True) # optional - latte_int
116
+ ' + 1 * t^0 + 10/3 * t^1 + 8 * t^2 + 20/3 * t^3'
117
+ sage: count(cddin, cdd=True, raw_output=True, # optional - latte_int
118
+ ....: multivariate_generating_function=True)
119
+ 'x[0]^(-1)*x[1]^(-1)/((1-x[0]*x[2])*(1-x[0]^(-1)*x[1])*(1-x[2]^(-1)))\n + x[0]^(-1)*x[1]^(-1)/((1-x[2])*(1-x[0]^(-1)*x[1])*(1-x[0]*x[2]^(-1)))\n + ... + x[0]*x[1]/((1-x[0]^(-1)*x[2])*(1-x[0]*x[1]^(-1))*(1-x[2]^(-1)))\n + x[0]*x[1]/((1-x[2])*(1-x[0]*x[1]^(-1))*(1-x[0]^(-1)*x[2]^(-1)))\n'
120
+
121
+ Testing multivariate generating function::
122
+
123
+ sage: from sage.interfaces.latte import count # optional - latte_int
124
+ sage: P = polytopes.cuboctahedron()
125
+ sage: cddin = P.cdd_Vrepresentation()
126
+ sage: count(cddin, cdd=True, multivariate_generating_function=True) # optional - latte_int
127
+ ((y0^-1*y1^-1) * (-y0*y2 + 1)^-1 * (1 - y0^-1*y1)^-1 * (1 - y2^-1)^-1,
128
+ (y0^-1*y1^-1) * (-y2 + 1)^-1 * (1 - y0^-1*y1)^-1 * (-y0*y2^-1 + 1)^-1,
129
+ ...
130
+ y0*y1 * (1 - y0^-1*y2)^-1 * (-y0*y1^-1 + 1)^-1 * (1 - y2^-1)^-1,
131
+ y0*y1 * (-y2 + 1)^-1 * (-y0*y1^-1 + 1)^-1 * (1 - y0^-1*y2^-1)^-1)
132
+
133
+ sage: P = Polyhedron(rays=[[0,1], [1,0]])
134
+ sage: cddin = P.cdd_Hrepresentation()
135
+ sage: count(cddin, cdd=True, raw_output=True, # optional - latte_int
136
+ ....: multivariate_generating_function=True)
137
+ '1/((1-x[1])*(1-x[0]))\n'
138
+ sage: count(cddin, cdd=True, multivariate_generating_function=True) # optional - latte_int
139
+ (1 * (-y1 + 1)^-1 * (-y0 + 1)^-1,)
140
+
141
+ Testing the ``verbose`` option::
142
+
143
+ sage: from sage.interfaces.latte import count
144
+ sage: P = polytopes.cuboctahedron()
145
+ sage: cddin = P.cdd_Vrepresentation()
146
+ sage: n = count(cddin, cdd=True, verbose=True, raw_output=True) # optional - latte_int
147
+ This is LattE integrale ...
148
+ ...
149
+ Invocation: ...count... '--redundancy-check=none' --cdd /dev/stdin
150
+ ...
151
+ Total Unimodular Cones: ...
152
+ Maximum number of simplicial cones in memory at once: ...
153
+ <BLANKLINE>
154
+ **** The number of lattice points is: ****
155
+ Total time: ... sec
156
+
157
+ Trivial input for which LattE's preprocessor does all the work::
158
+
159
+ sage: P = Polyhedron(vertices=[[0,0,0]])
160
+ sage: cddin = P.cdd_Hrepresentation()
161
+ sage: count(cddin, cdd=True, raw_output=False) # optional - latte_int
162
+ 1
163
+
164
+ Testing the runtime error::
165
+
166
+ sage: P = Polyhedron(rays=[[0,1], [1,0]])
167
+ sage: cddin = P.cdd_Hrepresentation()
168
+ sage: count(cddin, cdd=True, raw_output=False) # optional - latte_int
169
+ Traceback (most recent call last):
170
+ ...
171
+ RuntimeError: LattE integrale program failed (exit code 1):
172
+ This is LattE integrale ...
173
+ ...
174
+ The polyhedron is unbounded.
175
+ """
176
+ arg = str_to_bytes(arg)
177
+
178
+ args = [Latte_count().absolute_filename()]
179
+ if ehrhart_polynomial and multivariate_generating_function:
180
+ raise ValueError
181
+ if ehrhart_polynomial:
182
+ args.append('--ehrhart-polynomial')
183
+ elif multivariate_generating_function:
184
+ args.append('--multivariate-generating-function')
185
+
186
+ if 'redundancy_check' not in kwds:
187
+ args.append('--redundancy-check=none')
188
+
189
+ mgf_kwds = {}
190
+ for key,value in kwds.items():
191
+ if key in ["name", "Factorization_sort", "Factorization_simplify", "sort_factors"]:
192
+ mgf_kwds[key] = value
193
+ continue
194
+ if value is None or value is False:
195
+ continue
196
+
197
+ key = key.replace('_', '-')
198
+ if value is True:
199
+ args.append(f'--{key}')
200
+ else:
201
+ args.append(f'--{key}={value}')
202
+
203
+ if multivariate_generating_function:
204
+ from sage.misc.temporary_file import tmp_filename
205
+ filename = tmp_filename()
206
+ with open(filename, 'w') as f:
207
+ f.write(bytes_to_str(arg))
208
+ args += [filename]
209
+ else:
210
+ args += ['/dev/stdin']
211
+
212
+ # The cwd argument is needed because latte
213
+ # always produces diagnostic output files.
214
+ import tempfile
215
+ tempd = tempfile.TemporaryDirectory()
216
+
217
+ latte_proc = Popen(args,
218
+ stdin=PIPE, stdout=PIPE,
219
+ stderr=(None if verbose else PIPE),
220
+ cwd=tempd.name)
221
+
222
+ ans, err = latte_proc.communicate(arg)
223
+ if err:
224
+ err = bytes_to_str(err)
225
+ ret_code = latte_proc.poll()
226
+ if ret_code:
227
+ if err is None:
228
+ err = ", see error message above"
229
+ else:
230
+ err = ":\n" + err
231
+ raise RuntimeError("LattE integrale program failed (exit code {})".format(ret_code) + err.strip())
232
+
233
+ ans = bytes_to_str(ans)
234
+
235
+ # There's an error handler below that uses the numOfLatticePoints
236
+ # file created by latte, so we can't cleanup() the temporary
237
+ # directory here. Instead we have to clean it up before the
238
+ # (several) return statements.
239
+ if ehrhart_polynomial:
240
+ ans = ans.splitlines()[-2]
241
+ if raw_output:
242
+ tempd.cleanup()
243
+ return ans
244
+ else:
245
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
246
+ from sage.rings.rational_field import QQ
247
+ R = PolynomialRing(QQ, 't')
248
+ tempd.cleanup()
249
+ return R(ans)
250
+ elif multivariate_generating_function:
251
+ with open(filename + '.rat') as f:
252
+ ans = f.read()
253
+ if raw_output:
254
+ tempd.cleanup()
255
+ return ans
256
+ else:
257
+ tempd.cleanup()
258
+ return str_to_multivariate_generating_function(ans, **mgf_kwds)
259
+ else:
260
+ if ans: # Sometimes (when LattE's preproc does the work), no output appears on stdout.
261
+ ans = ans.splitlines()[-1]
262
+ if not ans:
263
+ # opening a file is slow (30e-6s), so we read the file
264
+ # numOfLatticePoints only in case of a IndexError above
265
+ with open(tempd.name + '/numOfLatticePoints') as f:
266
+ ans = f.read()
267
+
268
+ if raw_output:
269
+ tempd.cleanup()
270
+ return ans
271
+ else:
272
+ tempd.cleanup()
273
+ return Integer(ans)
274
+
275
+
276
+ def str_to_multivariate_generating_function(raw_output_str, name=None, **kwds):
277
+ r"""
278
+ Helper function for :func:`count` if ``multivariate_generating_function`` is set to ``True``
279
+ which preprocess the raw output string to a tuple of summands.
280
+
281
+ TESTS:
282
+
283
+ sage: from sage.interfaces.latte import count, str_to_multivariate_generating_function
284
+ sage: P = Polyhedron(ieqs=[(0, 1, 0, 0), (0, -1, 1, 0)], eqns=[(0, -1, -1, 2)])
285
+ sage: cddin = P.cdd_Hrepresentation()
286
+ sage: raw_output_str = count(cddin, cdd=True, raw_output=True,
287
+ ....: multivariate_generating_function=True)
288
+ sage: str_to_multivariate_generating_function(raw_output_str, name='xi')
289
+ (1 * (-xi0*xi1*xi2 + 1)^-1 * (-xi1^2*xi2 + 1)^-1,)
290
+ """
291
+ from sage.rings.integer_ring import ZZ
292
+ from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing
293
+ import re
294
+
295
+ indices_regex = re.compile(r'(?<=\[)(\d*)(?=\])')
296
+ indices = range(max(ZZ(index) for index in indices_regex.findall(raw_output_str)) + 1)
297
+ if name is None:
298
+ name = 'y'
299
+
300
+ B = LaurentPolynomialRing(ZZ,
301
+ tuple(name + str(k) for k in indices),
302
+ len(indices))
303
+ raw_output_list = raw_output_str[:-1].split('\n + ')
304
+ return tuple(_str_to_multivariate_generating_function(a, B, **kwds) for a in raw_output_list)
305
+
306
+
307
+ def _str_to_multivariate_generating_function(summand, B=None,
308
+ Factorization_sort=False, Factorization_simplify=False,
309
+ sort_factors=False):
310
+ r"""
311
+ Helper function for :func:`str_to_multivariate_generating_function`
312
+ which convert a summand string to a ``Factorization`` object.
313
+
314
+ Each summand is in the format
315
+ .. MATH::
316
+
317
+ (\sum_{k\in K}y^{s_0}*y^{v_k}})\prod_{j\in J}(1 - y^{v_j})^{-1}.
318
+
319
+ TESTS::
320
+
321
+ sage: from sage.interfaces.latte import _str_to_multivariate_generating_function
322
+ sage: B = LaurentPolynomialRing(ZZ, 'y', 3)
323
+ sage: _str_to_multivariate_generating_function(
324
+ ....: '(-1)*x[0]^(-1)*x[2]/((1-x[0]^(-1)*x[1]^(-1))*(1-x[0]^(-1)*x[2]^(-1))*(1-x[0]))', B)
325
+ (-y0^-1*y2) * (1 - y0^-1*y1^-1)^-1 * (1 - y0^-1*y2^-1)^-1 * (-y0 + 1)^-1
326
+ sage: _str_to_multivariate_generating_function('(-1)/((1-x[0]*x[1]*x[2])*(1-x[1]^2*x[2]))\n', B)
327
+ (-1) * (-y0*y1*y2 + 1)^-1 * (-y1^2*y2 + 1)^-1
328
+ sage: _str_to_multivariate_generating_function(
329
+ ....: '((-1)*x[0]*x[2]^2 + x[1]^(-2)*x[2])/((1-x[0]*x[1]*x[2])*(1-x[1]^2*x[2]))', B)
330
+ (-y0*y2^2 + y1^-2*y2) * (-y0*y1*y2 + 1)^-1 * (-y1^2*y2 + 1)^-1
331
+ """
332
+ from sage.rings.integer_ring import ZZ
333
+ from sage.structure.factorization import Factorization
334
+ import re
335
+
336
+ numerator_str, denominator_str = summand.split('/')
337
+
338
+ gen_regex = re.compile(r'(?<=\[)(\d*)(?=\])')
339
+ exponent_regex = re.compile(r'([\d|-]+)')
340
+
341
+ def str_to_laurent_monomial(monomial_str, B):
342
+ result = 1
343
+ for gen_str in monomial_str.split('*'):
344
+ gen_exponent = gen_str.split('^')
345
+ if len(gen_exponent) == 1:
346
+ result *= B.gens()[ZZ(gen_regex.findall(gen_exponent[0])[0])]
347
+ else:
348
+ result *= B.gens()[ZZ(gen_regex.findall(gen_exponent[0])[0])] ** ZZ(exponent_regex.findall(gen_exponent[1])[0])
349
+ return result
350
+
351
+ def str_to_coef_times_laurent_monomial(monomial_str, B):
352
+ if 'x' not in monomial_str:
353
+ if '*' in monomial_str:
354
+ aa, bb = monomial_str.split('*')
355
+ return ZZ(aa.replace('(','').replace(')',''))*ZZ(bb.replace('(','').replace(')',''))
356
+ else:
357
+ return ZZ(monomial_str.replace('(','').replace(')',''))
358
+ elif 'x' in monomial_str.split('*',1)[0]:
359
+ return str_to_laurent_monomial(monomial_str, B)
360
+ else:
361
+ return ZZ(monomial_str.split('*',1)[0].replace('(','').replace(')',''))*str_to_laurent_monomial(monomial_str.split('*',1)[1],B)
362
+
363
+ numerator = sum(str_to_coef_times_laurent_monomial(a, B) for a in numerator_str.split('+'))
364
+
365
+ term_regex = re.compile(r'(?<=1-)(.+?)(?=$|\)$|\)\*\()')
366
+ terms = (str_to_laurent_monomial(a, B) for a in term_regex.findall(denominator_str[1:-1]))
367
+ if sort_factors:
368
+ def key(t):
369
+ D = t.dict().popitem()[0]
370
+ return (-sum(abs(d) for d in D), D)
371
+ terms = sorted(terms, key=key, reverse=True)
372
+ return Factorization([(numerator, 1)] +
373
+ [(1-t, -1) for t in terms],
374
+ sort=Factorization_sort,
375
+ simplify=Factorization_simplify)
376
+
377
+
378
+ def integrate(arg, polynomial=None, algorithm='triangulate', raw_output=False, verbose=False, **kwds):
379
+ r"""
380
+ Call to the function integrate from LattE integrale.
381
+
382
+ INPUT:
383
+
384
+ - ``arg`` -- a cdd or LattE description string
385
+
386
+ - ``polynomial`` -- multivariate polynomial or valid LattE polynomial description string
387
+ If given, the valuation parameter of LattE is set to integrate, and is set to volume otherwise
388
+
389
+ - ``algorithm`` -- (default: ``'triangulate'``) the integration method; use 'triangulate' for
390
+ polytope triangulation or 'cone-decompose' for tangent cone decomposition method
391
+
392
+ - ``raw_output`` -- if ``True`` then return directly the output string from LattE
393
+
394
+ - ``verbose`` -- if ``True`` then return directly verbose output from LattE
395
+
396
+ - For all other options of the integrate program, consult the LattE manual
397
+
398
+ OUTPUT: either a string (if ``raw_output`` if set to ``True``) or a rational
399
+
400
+ EXAMPLES::
401
+
402
+ sage: from sage.interfaces.latte import integrate
403
+ sage: P = 2 * polytopes.cube()
404
+ sage: x, y, z = polygen(QQ, 'x, y, z')
405
+
406
+ Integrating over a polynomial over a polytope in either the H or V representation::
407
+
408
+ sage: integrate(P.cdd_Hrepresentation(), x^2*y^2*z^2, cdd=True) # optional - latte_int
409
+ 4096/27
410
+ sage: integrate(P.cdd_Vrepresentation(), x^2*y^2*z^2, cdd=True) # optional - latte_int
411
+ 4096/27
412
+
413
+ Computing the volume of a polytope in either the H or V representation::
414
+
415
+ sage: integrate(P.cdd_Hrepresentation(), cdd=True) # optional - latte_int
416
+ 64
417
+ sage: integrate(P.cdd_Vrepresentation(), cdd=True) # optional - latte_int
418
+ 64
419
+
420
+ Polynomials given as a string in LattE description are also accepted::
421
+
422
+ sage: integrate(P.cdd_Hrepresentation(), '[[1,[2,2,2]]]', cdd=True) # optional - latte_int
423
+ 4096/27
424
+
425
+ TESTS:
426
+
427
+ Testing raw output::
428
+
429
+ sage: from sage.interfaces.latte import integrate
430
+ sage: P = polytopes.cuboctahedron()
431
+ sage: cddin = P.cdd_Vrepresentation()
432
+ sage: x, y, z = polygen(QQ, 'x, y, z')
433
+ sage: f = 3*x^2*y^4*z^6 + 7*y^3*z^5
434
+ sage: integrate(cddin, f, cdd=True, raw_output=True) # optional - latte_int
435
+ '629/47775'
436
+
437
+ Testing the ``verbose`` option to integrate over a polytope::
438
+
439
+ sage: ans = integrate(cddin, f, cdd=True, verbose=True, # optional - latte_int
440
+ ....: raw_output=True)
441
+ This is LattE integrale ...
442
+ ...
443
+ Invocation: ...integrate... --valuation=integrate --triangulate --redundancy-check=none --cdd --monomials=... /dev/stdin
444
+ ...
445
+
446
+ Testing triangulate algorithm::
447
+
448
+ sage: from sage.interfaces.latte import integrate
449
+ sage: P = polytopes.cuboctahedron()
450
+ sage: cddin = P.cdd_Vrepresentation()
451
+ sage: integrate(cddin, algorithm='triangulate', cdd=True) # optional - latte_int
452
+ 20/3
453
+
454
+ Testing convex decomposition algorithm::
455
+
456
+ sage: from sage.interfaces.latte import integrate
457
+ sage: P = polytopes.cuboctahedron()
458
+ sage: cddin = P.cdd_Vrepresentation()
459
+ sage: integrate(cddin, algorithm='cone-decompose', cdd=True) # optional - latte_int
460
+ 20/3
461
+
462
+ Testing raw output::
463
+
464
+ sage: from sage.interfaces.latte import integrate
465
+ sage: P = polytopes.cuboctahedron()
466
+ sage: cddin = P.cdd_Vrepresentation()
467
+ sage: integrate(cddin, cdd=True, raw_output=True) # optional - latte_int
468
+ '20/3'
469
+
470
+ Testing polynomial given as a string in LattE description::
471
+
472
+ sage: from sage.interfaces.latte import integrate
473
+ sage: P = polytopes.cuboctahedron()
474
+ sage: integrate(P.cdd_Hrepresentation(), # optional - latte_int
475
+ ....: '[[3,[2,4,6]],[7,[0, 3, 5]]]', cdd=True)
476
+ 629/47775
477
+
478
+ Testing the ``verbose`` option to compute the volume of a polytope::
479
+
480
+ sage: from sage.interfaces.latte import integrate
481
+ sage: P = polytopes.cuboctahedron()
482
+ sage: cddin = P.cdd_Vrepresentation()
483
+ sage: ans = integrate(cddin, cdd=True, raw_output=True, verbose=True) # optional - latte_int
484
+ This is LattE integrale ...
485
+ ...
486
+ Invocation: ...integrate... --valuation=volume --triangulate --redundancy-check=none --cdd /dev/stdin
487
+ ...
488
+
489
+ Testing the runtime error::
490
+
491
+ sage: P = Polyhedron(rays=[[1,0],[0,1]])
492
+ sage: P._volume_latte() # optional - latte_int
493
+ Traceback (most recent call last):
494
+ ...
495
+ RuntimeError: LattE integrale program failed (exit code -6):
496
+ This is LattE integrale ...
497
+ ...
498
+ determinant: nonsquare matrix
499
+ """
500
+ arg = str_to_bytes(arg)
501
+
502
+ from sage.rings.rational import Rational
503
+
504
+ args = [Latte_integrate().absolute_filename()]
505
+
506
+ got_polynomial = bool(polynomial is not None)
507
+
508
+ if got_polynomial:
509
+ args.append('--valuation=integrate')
510
+ else:
511
+ args.append('--valuation=volume')
512
+
513
+ if algorithm == 'triangulate':
514
+ args.append('--triangulate')
515
+ elif algorithm == 'cone-decompose':
516
+ args.append('--cone-decompose')
517
+
518
+ if 'redundancy_check' not in kwds:
519
+ args.append('--redundancy-check=none')
520
+
521
+ for key, value in kwds.items():
522
+ if value is None or value is False:
523
+ continue
524
+
525
+ key = key.replace('_', '-')
526
+ if value is True:
527
+ args.append(f'--{key}')
528
+ else:
529
+ args.append(f'--{key}={value}')
530
+
531
+ if got_polynomial:
532
+ if not isinstance(polynomial, str):
533
+ # transform polynomial to LattE description
534
+ monomials_list = to_latte_polynomial(polynomial)
535
+ else:
536
+ monomials_list = str(polynomial)
537
+
538
+ from sage.misc.temporary_file import tmp_filename
539
+ filename_polynomial = tmp_filename()
540
+
541
+ with open(filename_polynomial, 'w') as f:
542
+ f.write(monomials_list)
543
+ args += ['--monomials=' + filename_polynomial]
544
+
545
+ args += ['/dev/stdin']
546
+
547
+ # The cwd argument is needed because latte
548
+ # always produces diagnostic output files.
549
+ import tempfile
550
+ tempd = tempfile.TemporaryDirectory()
551
+
552
+ latte_proc = Popen(args,
553
+ stdin=PIPE, stdout=PIPE,
554
+ stderr=(None if verbose else PIPE),
555
+ cwd=tempd.name)
556
+
557
+ ans, err = latte_proc.communicate(arg)
558
+ if err:
559
+ err = bytes_to_str(err)
560
+ ret_code = latte_proc.poll()
561
+ if ret_code:
562
+ if err is None:
563
+ err = ", see error message above"
564
+ else:
565
+ err = ":\n" + err
566
+ raise RuntimeError("LattE integrale program failed (exit code {})".format(ret_code) + err.strip())
567
+
568
+ ans = bytes_to_str(ans)
569
+ ans = ans.splitlines()
570
+ ans = ans[-5].split()
571
+ assert ans[0] == 'Answer:'
572
+ ans = ans[1]
573
+
574
+ tempd.cleanup()
575
+ if raw_output:
576
+ return ans
577
+ else:
578
+ return Rational(ans)
579
+
580
+
581
+ def to_latte_polynomial(polynomial):
582
+ r"""
583
+ Helper function to transform a polynomial to its LattE description.
584
+
585
+ INPUT:
586
+
587
+ - ``polynomial`` -- a multivariate polynomial
588
+
589
+ OUTPUT: string that describes the monomials list and exponent vectors
590
+
591
+ TESTS:
592
+
593
+ Testing a polynomial in three variables::
594
+
595
+ sage: from sage.interfaces.latte import to_latte_polynomial
596
+ sage: x, y, z = polygens(QQ, 'x, y, z')
597
+ sage: f = 3*x^2*y^4*z^6 + 7*y^3*z^5
598
+ sage: to_latte_polynomial(f)
599
+ '[[3, [2, 4, 6]], [7, [0, 3, 5]]]'
600
+
601
+ sage: to_latte_polynomial(x.parent().zero())
602
+ '[]'
603
+
604
+ Testing a univariate polynomial::
605
+
606
+ sage: x = polygen(QQ, 'x')
607
+ sage: to_latte_polynomial((x-1)^2)
608
+ '[[1, [0]], [-2, [1]], [1, [2]]]'
609
+
610
+ sage: to_latte_polynomial(x.parent().zero())
611
+ '[]'
612
+ """
613
+ if polynomial == 0:
614
+ return str([])
615
+
616
+ from sage.rings.polynomial.polydict import ETuple
617
+
618
+ coefficients_list = polynomial.coefficients()
619
+
620
+ # transform list of exponents into a list of lists.
621
+ # this branch handles the multivariate/univariate case
622
+ if isinstance(polynomial.exponents()[0], ETuple):
623
+ exponents_list = [list(exponent_vector_i) for exponent_vector_i in polynomial.exponents()]
624
+ else:
625
+ exponents_list = [[exponent_vector_i] for exponent_vector_i in polynomial.exponents()]
626
+
627
+ # assuming that the order in coefficients() and exponents() methods match
628
+ monomials_list = [list(monomial_i)
629
+ for monomial_i
630
+ in zip(coefficients_list, exponents_list)]
631
+
632
+ return str(monomials_list)
@@ -0,0 +1 @@
1
+ # sage_setup: distribution = sagemath-latte-4ti2
@@ -0,0 +1 @@
1
+ # sage_setup: distribution = sagemath-latte-4ti2
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file