passagemath-frobby 10.5.41__cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_frobby-10.5.41.dist-info/METADATA +99 -0
- passagemath_frobby-10.5.41.dist-info/RECORD +12 -0
- passagemath_frobby-10.5.41.dist-info/WHEEL +6 -0
- passagemath_frobby-10.5.41.dist-info/top_level.txt +1 -0
- passagemath_frobby.libs/libgmp-fc7212f6.so.10.5.0 +0 -0
- passagemath_frobby.libs/libgmpxx-85ac3a0c.so.4.7.0 +0 -0
- sage/all__sagemath_frobby.py +5 -0
- sage/interfaces/all__sagemath_frobby.py +1 -0
- sage/interfaces/frobby.py +463 -0
- sage/libs/all__sagemath_frobby.py +1 -0
- sage/libs/frobby.cpython-310-x86_64-linux-gnu.so +0 -0
- sage_wheels/bin/frobby +0 -0
@@ -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-fc7212f6.so.10.5.0,sha256=Q14RHpSHQ7TnfcPD5kFBLrgw0EiW5p_9PDHQIjdd9LE,576745
|
2
|
+
passagemath_frobby.libs/libgmpxx-85ac3a0c.so.4.7.0,sha256=jg5Idp_ITJucnwYua0TOOqRqjKKlPobai8XCj5B4yNU,68769
|
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-310-x86_64-linux-gnu.so,sha256=e-6IeSLT1idD2h_vOQztfPX9ptHRIwC1jQ5mqVRO3fI,73360
|
8
|
+
sage_wheels/bin/frobby,sha256=t_vXxszD2N0i7LWfA8iN1iNEWY3DC-qPnCp9VRmgSaI,32574008
|
9
|
+
passagemath_frobby-10.5.41.dist-info/METADATA,sha256=zD4oLqvKisuophGuT9ngyfK_g7wPGwpiw4fCyHwort4,4360
|
10
|
+
passagemath_frobby-10.5.41.dist-info/WHEEL,sha256=HeTPKmtWRHAcGMCPCdnU4FtSZuvZBNNr3hB4MNGY2JY,152
|
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 @@
|
|
1
|
+
sage
|
Binary file
|
Binary file
|
@@ -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
|
Binary file
|
sage_wheels/bin/frobby
ADDED
Binary file
|