passagemath-frobby 10.5.41__cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.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.
@@ -0,0 +1,99 @@
1
+ Metadata-Version: 2.4
2
+ Name: passagemath-frobby
3
+ Version: 10.5.41
4
+ Summary: passagemath: Computations on monomial ideals with Frobby
5
+ Author-email: The Sage Developers <sage-support@googlegroups.com>
6
+ Maintainer: Matthias Köppe, passagemath contributors
7
+ License-Expression: GPL-2.0-or-later
8
+ Project-URL: release notes, https://github.com/passagemath/passagemath/releases
9
+ Project-URL: repo (upstream), https://github.com/sagemath/sage
10
+ Project-URL: repo, https://github.com/passagemath/passagemath
11
+ Project-URL: documentation, https://doc.sagemath.org
12
+ Project-URL: homepage (upstream), https://www.sagemath.org
13
+ Project-URL: discourse, https://passagemath.discourse.group
14
+ Project-URL: tracker (upstream), https://github.com/sagemath/sage/issues
15
+ Project-URL: tracker, https://github.com/passagemath/passagemath/issues
16
+ Classifier: Development Status :: 6 - Mature
17
+ Classifier: Intended Audience :: Education
18
+ Classifier: Intended Audience :: Science/Research
19
+ Classifier: Operating System :: POSIX
20
+ Classifier: Operating System :: MacOS :: MacOS X
21
+ Classifier: Programming Language :: Python :: 3 :: Only
22
+ Classifier: Programming Language :: Python :: 3.9
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Programming Language :: Python :: 3.13
27
+ Classifier: Programming Language :: Python :: Implementation :: CPython
28
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
29
+ Requires-Python: <3.14,>=3.9
30
+ Description-Content-Type: text/x-rst
31
+ Requires-Dist: cysignals!=1.12.0,>=1.11.2
32
+ Requires-Dist: passagemath-environment~=10.5.41.0
33
+ Requires-Dist: passagemath-categories~=10.5.41.0
34
+ Provides-Extra: test
35
+ Requires-Dist: passagemath-graphs; extra == "test"
36
+ Requires-Dist: passagemath-repl; extra == "test"
37
+ Requires-Dist: passagemath-singular; extra == "test"
38
+
39
+ ========================================================
40
+ passagemath: Computations on monomial ideals with Frobby
41
+ ========================================================
42
+
43
+ `passagemath <https://github.com/passagemath/passagemath>`__ is open
44
+ source mathematical software in Python, released under the GNU General
45
+ Public Licence GPLv2+.
46
+
47
+ It is a fork of `SageMath <https://www.sagemath.org/>`__, which has been
48
+ developed 2005-2025 under the motto “Creating a Viable Open Source
49
+ Alternative to Magma, Maple, Mathematica, and MATLAB”.
50
+
51
+ The passagemath fork was created in October 2024 with the following
52
+ goals:
53
+
54
+ - providing modularized installation with pip, thus completing a `major
55
+ project started in 2020 in the Sage
56
+ codebase <https://github.com/sagemath/sage/issues/29705>`__,
57
+ - establishing first-class membership in the scientific Python
58
+ ecosystem,
59
+ - giving `clear attribution of upstream
60
+ projects <https://groups.google.com/g/sage-devel/c/6HO1HEtL1Fs/m/G002rPGpAAAJ>`__,
61
+ - providing independently usable Python interfaces to upstream
62
+ libraries,
63
+ - providing `platform portability and integration testing
64
+ services <https://github.com/passagemath/passagemath/issues/704>`__
65
+ to upstream projects,
66
+ - inviting collaborations with upstream projects,
67
+ - `building a professional, respectful, inclusive
68
+ community <https://groups.google.com/g/sage-devel/c/xBzaINHWwUQ>`__,
69
+ - developing a port to `Pyodide <https://pyodide.org/en/stable/>`__ for
70
+ serverless deployment with Javascript,
71
+ - developing a native Windows port.
72
+
73
+ `Full documentation <https://doc.sagemath.org/html/en/index.html>`__ is
74
+ available online.
75
+
76
+ passagemath attempts to support all major Linux distributions and recent versions of
77
+ macOS. Use on Windows currently requires the use of Windows Subsystem for Linux or
78
+ virtualization.
79
+
80
+ Complete sets of binary wheels are provided on PyPI for Python versions 3.9.x-3.12.x.
81
+ Python 3.13.x is also supported, but some third-party packages are still missing wheels,
82
+ so compilation from source is triggered for those.
83
+
84
+
85
+ About this pip-installable distribution package
86
+ -----------------------------------------------
87
+
88
+ This pip-installable source distribution ``passagemath-frobby`` provides an interface to Frobby,
89
+ the package for computations on monomial ideals.
90
+
91
+
92
+ Examples
93
+ --------
94
+
95
+ A quick way to try it out interactively::
96
+
97
+ $ pipx run --pip-args="--prefer-binary" --spec "passagemath-frobby[test]" ipython
98
+
99
+ In [1]: from sage.all__sagemath_frobby import *
@@ -0,0 +1,12 @@
1
+ passagemath_frobby.libs/libgmp-b7bc6ccf.so.10.5.0,sha256=wWj9DTad9TDc7qK_-TCSchoWOhjzylvaWDAA_hwYDbA,666681
2
+ passagemath_frobby.libs/libgmpxx-39778ba9.so.4.7.0,sha256=RWCLC1cph7ZjZFzSWFUMjV_YkrIAd7RhjuSHY52Ci9E,400545
3
+ sage/all__sagemath_frobby.py,sha256=ZZLIxeb2nBT4yQeA2DJP-RAv4cu-U6uMgxlMwzt1H2c,172
4
+ sage/interfaces/all__sagemath_frobby.py,sha256=8Gs1smRLFdGXCb2uKk6xy0wkdR8twjy7TlbvxQXV1gc,45
5
+ sage/interfaces/frobby.py,sha256=NAXJL2ybODNM3V1EyjMW_C2KKjt0b9wRVrWLWO5ePnI,16693
6
+ sage/libs/all__sagemath_frobby.py,sha256=8Gs1smRLFdGXCb2uKk6xy0wkdR8twjy7TlbvxQXV1gc,45
7
+ sage/libs/frobby.cpython-311-aarch64-linux-gnu.so,sha256=Q0wRwckFV-qx-dagfwlkoyGEk2V-qVRMdya1ImXjut0,255632
8
+ sage_wheels/bin/frobby,sha256=otfT5wu4b_S95FbhxyU6hWLWQziX2bXlK_NoWxI8chQ,32420016
9
+ passagemath_frobby-10.5.41.dist-info/METADATA,sha256=zD4oLqvKisuophGuT9ngyfK_g7wPGwpiw4fCyHwort4,4360
10
+ passagemath_frobby-10.5.41.dist-info/WHEEL,sha256=kd1DLlG2bxeAxn5uI-koj2s6omEUi3sgz5Bccpa-idw,154
11
+ passagemath_frobby-10.5.41.dist-info/top_level.txt,sha256=hibFyzQHiLOMK68qL1OWsNKaXOmSXqZjeLTBem6Yy7I,5
12
+ passagemath_frobby-10.5.41.dist-info/RECORD,,
@@ -0,0 +1,6 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: false
4
+ Tag: cp311-cp311-manylinux_2_24_aarch64
5
+ Tag: cp311-cp311-manylinux_2_28_aarch64
6
+
@@ -0,0 +1,5 @@
1
+ # sage_setup: distribution = sagemath-frobby
2
+
3
+ from sage.all__sagemath_categories import *
4
+ from sage.all__sagemath_graphs import *
5
+ from sage.all__sagemath_singular import *
@@ -0,0 +1 @@
1
+ # sage_setup: distribution = sagemath-frobby
@@ -0,0 +1,463 @@
1
+ # sage_setup: distribution = sagemath-frobby
2
+ r"""
3
+ Interface to Frobby for fast computations on monomial ideals.
4
+
5
+ The software package Frobby provides a number of computations on
6
+ monomial ideals. The current main feature is the socle of a monomial
7
+ ideal, which is largely equivalent to computing the maximal standard
8
+ monomials, the Alexander dual or the irreducible decomposition.
9
+
10
+ Operations on monomial ideals are much faster than algorithms designed
11
+ for ideals in general, which is what makes a specialized library for
12
+ these operations on monomial ideals useful.
13
+
14
+ AUTHORS:
15
+
16
+ - Bjarke Hammersholt Roune (2008-04-25): Wrote the Frobby C++
17
+ program and the initial version of the Python interface.
18
+
19
+ .. NOTE::
20
+
21
+ The official source for Frobby is <https://www.broune.com/frobby>,
22
+ which also has documentation and papers describing the algorithms used.
23
+ """
24
+
25
+ from subprocess import Popen, PIPE
26
+ from sage.misc.misc_c import prod
27
+
28
+ from sage.cpython.string import bytes_to_str, str_to_bytes
29
+ from sage.features.frobby import Frobby as frobby_executable
30
+
31
+
32
+ class Frobby:
33
+ def __call__(self, action, input=None, options=[], verbose=False):
34
+ r"""
35
+ This function calls Frobby as a command line program using streams
36
+ for input and output. Strings passed as part of the command get
37
+ broken up at whitespace. This is not done to the data passed
38
+ via the streams.
39
+
40
+ INPUT:
41
+
42
+ - ``action`` -- string telling Frobby what to do
43
+ - ``input`` -- ``None`` or string that is passed to Frobby as standard in
44
+ - ``options`` -- list of options without the dash in front
45
+ - ``verbose`` -- boolean (default: ``False``); print detailed information
46
+
47
+ OUTPUT: string; what Frobby wrote to the standard output stream
48
+
49
+ EXAMPLES:
50
+
51
+ We compute the lcm of an ideal provided in Monos format. ::
52
+
53
+ sage: frobby("analyze", input="vars x,y,z;[x^2,x*y];", # optional - frobby
54
+ ....: options=["lcm", "iformat monos", "oformat 4ti2"])
55
+ ' 2 1 0\n\n2 generators\n3 variables\n'
56
+
57
+
58
+ We get an exception if frobby reports an error. ::
59
+
60
+ sage: frobby("do_dishes") # optional - frobby
61
+ Traceback (most recent call last):
62
+ ...
63
+ RuntimeError: Frobby reported an error:
64
+ ERROR: No action has the prefix "do_dishes".
65
+
66
+ AUTHOR:
67
+
68
+ - Bjarke Hammersholt Roune (2008-04-27)
69
+ """
70
+ command = [frobby_executable().absolute_filename()] + action.split()
71
+ for option in options:
72
+ command += ('-' + option.strip()).split()
73
+
74
+ if verbose:
75
+ print("Frobby action: ", action)
76
+ print("Frobby options: ", repr(options))
77
+ print("Frobby command: ", repr(command))
78
+ print("Frobby input:\n", input)
79
+
80
+ process = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
81
+ if input:
82
+ frinput = str_to_bytes(input)
83
+ else:
84
+ frinput = None
85
+ output, err = process.communicate(input=frinput)
86
+ output = bytes_to_str(output)
87
+ err = bytes_to_str(err)
88
+
89
+ if verbose:
90
+ print("Frobby output:\n", output)
91
+ print("Frobby error:\n", err)
92
+ if process.poll() != 0:
93
+ raise RuntimeError("Frobby reported an error:\n" + err)
94
+
95
+ return output
96
+
97
+ def alexander_dual(self, monomial_ideal):
98
+ r"""
99
+ This function computes the Alexander dual of the passed-in
100
+ monomial ideal. This ideal is the one corresponding to the
101
+ simplicial complex whose faces are the complements of the
102
+ nonfaces of the simplicial complex corresponding to the input
103
+ ideal.
104
+
105
+ INPUT:
106
+
107
+ - ``monomial_ideal`` -- the monomial ideal to decompose
108
+
109
+ OUTPUT: the monomial corresponding to the Alexander dual
110
+
111
+ EXAMPLES:
112
+
113
+ This is a simple example of computing irreducible decomposition. ::
114
+
115
+ sage: # optional - frobby
116
+ sage: (a, b, c, d) = QQ['a,b,c,d'].gens()
117
+ sage: id = ideal(a * b, b * c, c * d, d * a)
118
+ sage: alexander_dual = frobby.alexander_dual(id)
119
+ sage: true_alexander_dual = ideal(b * d, a * c)
120
+ sage: alexander_dual == true_alexander_dual # use sets to ignore order
121
+ True
122
+
123
+ We see how it is much faster to compute this with frobby than the built-in
124
+ procedure for simplicial complexes::
125
+
126
+ sage: # optional - frobby
127
+ sage: t=simplicial_complexes.PoincareHomologyThreeSphere()
128
+ sage: R=PolynomialRing(QQ,16,'x')
129
+ sage: I=R.ideal([prod([R.gen(i-1) for i in a]) for a in t.facets()])
130
+ sage: len(frobby.alexander_dual(I).gens())
131
+ 643
132
+ """
133
+ frobby_input = self._ideal_to_string(monomial_ideal)
134
+ frobby_output = self('alexdual', input=frobby_input)
135
+ return self._parse_ideals(frobby_output, monomial_ideal.ring())[0]
136
+
137
+ def hilbert(self, monomial_ideal):
138
+ r"""
139
+ Compute the multigraded Hilbert-Poincaré series of the input
140
+ ideal. Use the -univariate option to get the univariate series.
141
+
142
+ The Hilbert-Poincaré series of a monomial ideal is the sum of all
143
+ monomials not in the ideal. This sum can be written as a (finite)
144
+ rational function with `(x_1-1)(x_2-1)...(x_n-1)` in the denominator,
145
+ assuming the variables of the ring are `x_1,x2,...,x_n`. This action
146
+ computes the polynomial in the numerator of this fraction.
147
+
148
+ INPUT:
149
+
150
+ - ``monomial_ideal`` -- a monomial ideal
151
+
152
+ OUTPUT:
153
+
154
+ A polynomial in the same ring as the ideal.
155
+
156
+ EXAMPLES::
157
+
158
+ sage: R.<d,b,c>=QQ[] # optional - frobby
159
+ sage: I=[d*b*c,b^2*c,b^10,d^10]*R # optional - frobby
160
+ sage: frobby.hilbert(I) # optional - frobby
161
+ d^10*b^10*c + d^10*b^10 + d^10*b*c + b^10*c + d^10 + b^10 + d*b^2*c + d*b*c + b^2*c + 1
162
+ """
163
+ frobby_input = self._ideal_to_string(monomial_ideal)
164
+ frobby_output = self('hilbert', input=frobby_input)
165
+ ring = monomial_ideal.ring()
166
+ lines = frobby_output.split('\n')
167
+ if lines[-1] == '':
168
+ lines.pop(-1)
169
+ if lines[-1] == '(coefficient)':
170
+ lines.pop(-1)
171
+ lines.pop(0)
172
+ resul = 0
173
+ for l in lines:
174
+ lis = [int(_) for _ in l.split()]
175
+ resul += lis[0]+prod([ring.gen(i)**lis[i+1] for i in range(len(lis)-1)])
176
+ return resul
177
+
178
+ def associated_primes(self, monomial_ideal):
179
+ r"""
180
+ This function computes the associated primes of the passed-in
181
+ monomial ideal.
182
+
183
+ INPUT:
184
+
185
+ - ``monomial_ideal`` -- the monomial ideal to decompose
186
+
187
+ OUTPUT:
188
+
189
+ A list of the associated primes of the monomial ideal. These ideals
190
+ are constructed in the same ring as monomial_ideal is.
191
+
192
+ EXAMPLES::
193
+
194
+ sage: R.<d,b,c>=QQ[] # optional - frobby
195
+ sage: I=[d*b*c,b^2*c,b^10,d^10]*R # optional - frobby
196
+ sage: frobby.associated_primes(I) # optional - frobby
197
+ [Ideal (d, b) of Multivariate Polynomial Ring in d, b, c over Rational Field,
198
+ Ideal (d, b, c) of Multivariate Polynomial Ring in d, b, c over Rational Field]
199
+ """
200
+ frobby_input = self._ideal_to_string(monomial_ideal)
201
+ frobby_output = self('assoprimes', input=frobby_input)
202
+ lines = frobby_output.split('\n')
203
+ lines.pop(0)
204
+ if lines[-1] == '':
205
+ lines.pop(-1)
206
+ lists = [[int(_) for _ in a.split()] for a in lines]
207
+
208
+ def to_monomial(exps):
209
+ return [v ** e for v, e in zip(monomial_ideal.ring().gens(), exps) if e != 0]
210
+ return [monomial_ideal.ring().ideal(to_monomial(a)) for a in lists]
211
+
212
+ def dimension(self, monomial_ideal):
213
+ r"""
214
+ This function computes the dimension of the passed-in
215
+ monomial ideal.
216
+
217
+ INPUT:
218
+
219
+ - ``monomial_ideal`` -- the monomial ideal to decompose
220
+
221
+ OUTPUT: the dimension of the zero set of the ideal
222
+
223
+ EXAMPLES::
224
+
225
+ sage: R.<d,b,c>=QQ[] # optional - frobby
226
+ sage: I=[d*b*c,b^2*c,b^10,d^10]*R # optional - frobby
227
+ sage: frobby.dimension(I) # optional - frobby
228
+ 1
229
+ """
230
+ frobby_input = self._ideal_to_string(monomial_ideal)
231
+ frobby_output = self('dimension', input=frobby_input)
232
+ return int(frobby_output)
233
+
234
+ def irreducible_decomposition(self, monomial_ideal):
235
+ r"""
236
+ This function computes the irreducible decomposition of the passed-in
237
+ monomial ideal. I.e. it computes the unique minimal list of
238
+ irreducible monomial ideals whose intersection equals monomial_ideal.
239
+
240
+ INPUT:
241
+
242
+ - ``monomial_ideal`` -- the monomial ideal to decompose
243
+
244
+ OUTPUT:
245
+
246
+ A list of the unique irredundant irreducible components of
247
+ monomial_ideal. These ideals are constructed in the same ring
248
+ as monomial_ideal is.
249
+
250
+ EXAMPLES:
251
+
252
+ This is a simple example of computing irreducible decomposition. ::
253
+
254
+ sage: # optional - frobby
255
+ sage: (x, y, z) = QQ['x,y,z'].gens()
256
+ sage: id = ideal(x ** 2, y ** 2, x * z, y * z)
257
+ sage: decom = frobby.irreducible_decomposition(id)
258
+ sage: true_decom = [ideal(x, y), ideal(x ** 2, y ** 2, z)]
259
+ sage: set(decom) == set(true_decom) # use sets to ignore order
260
+ True
261
+
262
+ We now try the special case of the zero ideal in different rings.
263
+
264
+ We should also try PolynomialRing(QQ, names=[]), but it has a bug
265
+ which makes that impossible (see :issue:`3028`). ::
266
+
267
+ sage: # optional - frobby
268
+ sage: rings = [ZZ['x'], CC['x,y']]
269
+ sage: allOK = True
270
+ sage: for ring in rings:
271
+ ....: id0 = ring.ideal(0)
272
+ ....: decom0 = frobby.irreducible_decomposition(id0)
273
+ ....: allOK = allOK and decom0 == [id0]
274
+ sage: allOK
275
+ True
276
+
277
+ Finally, we try the ideal that is all of the ring in different
278
+ rings. ::
279
+
280
+ sage: # optional - frobby
281
+ sage: rings = [ZZ['x'], CC['x,y']]
282
+ sage: allOK = True
283
+ sage: for ring in rings:
284
+ ....: id1 = ring.ideal(1)
285
+ ....: decom1 = frobby.irreducible_decomposition(id1)
286
+ ....: allOK = allOK and decom1 == [id1]
287
+ sage: allOK
288
+ True
289
+ """
290
+ frobby_input = self._ideal_to_string(monomial_ideal)
291
+ frobby_output = self('irrdecom', input=frobby_input)
292
+ return self._parse_ideals(frobby_output, monomial_ideal.ring())
293
+
294
+ def _parse_ideals(self, string, ring):
295
+ r"""
296
+ This function parses a list of irreducible monomial ideals in 4ti2
297
+ format and constructs them within the passed-in ring.
298
+
299
+ INPUT:
300
+
301
+ - ``string`` -- the string to be parsed
302
+ - ``ring`` -- the ring within which to construct the irreducible
303
+ monomial ideals within
304
+
305
+ OUTPUT:
306
+
307
+ A list of the monomial ideals in the order they are listed
308
+ in the string.
309
+
310
+ EXAMPLES::
311
+
312
+ sage: # optional - frobby
313
+ sage: ring = QQ['x,y,z']
314
+ sage: (x, y, z) = ring.gens()
315
+ sage: string = '2 3\n1 2 3\n0 5 0\n2 3\n1 2 3\n4 5 6'
316
+ sage: frobby._parse_ideals(string, ring)
317
+ [Ideal (x*y^2*z^3, y^5) of Multivariate Polynomial Ring in x, y, z over Rational Field,
318
+ Ideal (x*y^2*z^3, x^4*y^5*z^6) of Multivariate Polynomial Ring in x, y, z over Rational Field]
319
+ """
320
+ lines = string.split('\n')
321
+ if lines[-1] == '':
322
+ lines.pop(-1)
323
+ matrices = []
324
+ while lines:
325
+ if lines[0].split()[1] == 'ring':
326
+ lines.pop(0)
327
+ lines.pop(0)
328
+ matrices.append('1 '+str(ring.ngens())+'\n'+'0 '*ring.ngens()+'\n')
329
+ else:
330
+ nrows = int(lines[0].split()[0])
331
+ nmatrix = lines.pop(0)+'\n'
332
+ for i in range(nrows):
333
+ nmatrix += lines.pop(0)+'\n'
334
+ matrices.append(nmatrix)
335
+
336
+ def to_ideal(exps):
337
+ if len(exps) == 0:
338
+ return ring.zero_ideal()
339
+ gens = [prod([v ** e for v, e in zip(ring.gens(), expo) if e != 0]) for expo in exps]
340
+ return ring.ideal(gens or ring(1))
341
+ return [to_ideal(self._parse_4ti2_matrix(a)) for a in matrices] or [ring.ideal()]
342
+
343
+ def _parse_4ti2_matrix(self, string):
344
+ r"""
345
+ Parses a string of a matrix in 4ti2 format into a nested list
346
+ representation.
347
+
348
+ INPUT:
349
+
350
+ - ``string`` -- the string to be parsed
351
+
352
+ OUTPUT:
353
+
354
+ A list of rows of the matrix, where each row is represented as
355
+ a list of integers.
356
+
357
+ EXAMPLES:
358
+
359
+ The format is straight-forward, as this example shows. ::
360
+
361
+ sage: # optional - frobby
362
+ sage: string = '2 3\n1 2 3\n 0 5 0'
363
+ sage: parsed_matrix = frobby._parse_4ti2_matrix(string)
364
+ sage: reference_matrix = [[1, 2, 3], [0, 5, 0]]
365
+ sage: parsed_matrix == reference_matrix
366
+ True
367
+
368
+ A number of syntax errors lead to exceptions. ::
369
+
370
+ sage: string = '1 1\n one' # optional - frobby
371
+ sage: frobby._parse_4ti2_matrix(string) # optional - frobby
372
+ Traceback (most recent call last):
373
+ ...
374
+ RuntimeError: Format error: encountered non-number.
375
+ """
376
+ try:
377
+ ints = [int(_) for _ in string.split()]
378
+ except ValueError:
379
+ raise RuntimeError("Format error: encountered non-number.")
380
+ if len(ints) < 2:
381
+ raise RuntimeError("Format error: " +
382
+ "matrix dimensions not specified.")
383
+
384
+ term_count = ints[0]
385
+ var_count = ints[1]
386
+ ints = ints[2:]
387
+
388
+ if term_count * var_count != len(ints):
389
+ raise RuntimeError("Format error: incorrect matrix dimensions.")
390
+
391
+ exponents = []
392
+ for i in range(term_count):
393
+ exponents.append(ints[:var_count])
394
+ ints = ints[var_count:]
395
+ return exponents
396
+
397
+ def _ideal_to_string(self, monomial_ideal):
398
+ r"""
399
+ This function formats the passed-in monomial ideal in 4ti2 format.
400
+
401
+ INPUT:
402
+
403
+ - ``monomial_ideal`` -- the monomial ideal to be formatted as a string
404
+
405
+ OUTPUT: string in ``4ti2`` format representing the ideal
406
+
407
+ EXAMPLES::
408
+
409
+ sage: # optional - frobby
410
+ sage: ring = QQ['x,y,z']
411
+ sage: (x, y, z) = ring.gens()
412
+ sage: id = ring.ideal(x ** 2, x * y * z)
413
+ sage: frobby._ideal_to_string(id) == "2 3\n2 0 0\n1 1 1\n"
414
+ True
415
+ """
416
+ # There is no exponent vector that represents zero as a generator, so
417
+ # we take care that the zero ideal gets represented correctly in the
418
+ # 4ti2 format; as an ideal with no generators.
419
+ if monomial_ideal.is_zero():
420
+ gens = []
421
+ else:
422
+ gens = monomial_ideal.gens()
423
+ var_count = monomial_ideal.ring().ngens()
424
+ first_row = str(len(gens)) + ' ' + str(var_count) + '\n'
425
+ rows = [self._monomial_to_string(_) for _ in gens]
426
+ return first_row + "".join(rows)
427
+
428
+ def _monomial_to_string(self, monomial):
429
+ r"""
430
+ This function formats the exponent vector of a monomial as a string
431
+ containing a space-delimited list of integers.
432
+
433
+ INPUT:
434
+
435
+ - ``monomial`` -- the monomial whose exponent vector is to be formatted
436
+
437
+ OUTPUT: string representing the exponent vector of monomial
438
+
439
+ EXAMPLES::
440
+
441
+ sage: # optional - frobby
442
+ sage: ring = QQ['x,y,z']
443
+ sage: (x, y, z) = ring.gens()
444
+ sage: monomial = x * x * z
445
+ sage: frobby._monomial_to_string(monomial) == '2 0 1\n'
446
+ True
447
+ """
448
+ exponents = monomial.exponents()
449
+ if len(exponents) != 1:
450
+ raise RuntimeError(str(monomial) + " is not a monomial.")
451
+ exponents = exponents[0]
452
+
453
+ # for a multivariate ring exponents will be an ETuple, while
454
+ # for a univariate ring exponents will be just an int. To get
455
+ # this to work we make the two cases look alike.
456
+ if isinstance(exponents, int):
457
+ exponents = [exponents]
458
+ strings = [str(exponents[var]) for var in range(len(exponents))]
459
+ return ' '.join(strings) + '\n'
460
+
461
+
462
+ # This singleton instance is what should be used outside this file.
463
+ frobby = Frobby()
@@ -0,0 +1 @@
1
+ # sage_setup: distribution = sagemath-frobby
sage_wheels/bin/frobby ADDED
Binary file