# sympy/sympy

### Subversion checkout URL

You can clone with
or
.

Merged
merged 3 commits into from
+323 −30

### 3 participants

FGLM converts Gröbner bases of zero-dimensional ideals from one term order to another. This could benefit SymPy with `solve` for polynomial systems, where we need a Gröbner basis wrt lex (which often much more expensive to compute than grlex or grevlex).

Example:

``````In [1]: F=[x**2-3*y-x+1, y**2-2*x+y-1]
In [2]: G=groebner(F, x, y, order="grevlex")
In [3]: fglm(G, "grevlex", x, y)  # the default target order is lex
Out[3]:
⎡       2           4      3      2           ⎤
⎣2⋅x - y  - y + 1, y  + 2⋅y  - 3⋅y  - 16⋅y + 7⎦
In [4]: groebner(F, x, y, order="lex")
Out[4]:
⎡       2           4      3      2           ⎤
⎣2⋅x - y  - y + 1, y  + 2⋅y  - 3⋅y  - 16⋅y + 7⎦
``````

On the implementation: I don't use matrices, as they don't use mpqs, which is very important for performance (the matrix `P` tends to have very complicated entries). The construction of the representing matrices of the map that maps a monomial `m` to `x_i * m` is not done very efficiently but I'd expect the computation of the Gröbner basis to be infeasible before this causes trouble. If it were done more efficiently, FGLM would take O((number of variables) * (number of solutions)**3) field operations, where "number of solutions" is counted with multiplicity.

 Jeremias Yehdegho `Add FGLM` ```FGLM converts a Groebner basis of a zero-dimensional ideal from one term order to another. The current implementation loses some speed when constructing the matrices which represent multiplication by a variable. The actual conversion takes O(#variables * #solutions^3), where the number of solutions counts multiplicity. It uses lists of lists instead of matrices because mpqs become sympy.core.numbers.Rational in a Matrix but mpqs are crucial for speed as the entries in P tend to become very complicated. Examples: >>> F = [x**2 - x - 3*y + 1, y**2 - 2*x + y - 1] >>> G = groebner(F, x, y, order='lex') >>> fglm(G, 'lex', 'grlex', x, y) [x**2 - x - 3*y + 1, -2*x + y**2 + y - 1] >>> groebner(G, x, y, order='grlex') [x**2 - x - 3*y + 1, -2*x + y**2 + y - 1] To give an impression why this could be useful, consider cyclic5: >>> a, b, c, d, e = symbols('a b c d e') >>> F = [a + b + c + d + e, a*b + b*c + c*d + d*e + e*a, a*b*c + b*c*d + c*d*e + d*e*a + e*a*b, a*b*c*d + b*c*d*e + c*d*e*a + d*e*a*b + e*a*b*c, a*b*c*d*e - 1] >>> %timeit groebner(F, a, b, c, d, e, order='lex') 1 loops, best of 3: 42.2 s per loop >>> %timeit G = groebner(F, a, b, c, d, e, order='grlex'); fglm(G, 'grlex', 'lex', a, b, c, d, e) 1 loops, best of 3: 2.99 s per loop``` `b2fc24a` Jeremias Yehdegho `Change syntax for fglm` ```Instead of fglm(G, 'grevlex', 'lex', x, y, z) use fglm(G, ('grevlex', 'lex', x, y, z) or fglm(G, 'grevlex', x, y, z) (the default to_order is 'lex') (or fglm(G, ('grevlex'), x, y, z)).``` `592affa` Jeremias Yehdegho `Merge branch 'master' into matrix-fglm3` ```Conflicts: sympy/polys/groebnertools.py sympy/polys/polytools.py sympy/polys/tests/test_groebnertools.py``` `9fc9a20`
Collaborator

Test results html report: http://pastehtml.com/view/b3ijhbrm4.html

Automatic review by sympy-bot.

Collaborator

This looks good, +1.

@Jerryy: can you summarize this and other algorithms you implemented in SymPy's documentation (`doc/src/modules/polys`) so that new users have clear view on what SymPy can do in the area of Groebner bases (of course on in this pull request)? Put together short descriptions, interesting examples, some benchmarks and discussion from your weekly reports.

Owner

Test results html report: http://pastehtml.com/view/b3ix76ie5.html

Summary: There do not appear to be any problems.

Please double check this against the test report given above before merging with master.

Automatic review by sympy-bot.

merged commit `9fc9a20` into sympy:master
Collaborator

I also run tests without gmpy to make sure that no tests hang.

Owner

So does this make solve() use this now, or is that patch still forthcoming?

I'm a bit hesitant after the problem with test_czichowski without gmpy. Should this be done with

``````if HAS_GMPY:
G = groebner(..., order='grevlex')
G = fglm(G, 'grevlex'...)
else:
G = groebner(G, ..., order='lex')
``````

?

Collaborator

You meant `G = fglm(G, 'lex', ...)`?

No, 'lex' is the default target order. The more explicit version would be `fglm(G, ('grevlex', 'lex'), ...)`.

Collaborator

Oh, I see. I though this was done the other way. The current approach seems logical, because usually we will convert from a total degree ordering to lex, but there will be a problem when `GroebnerBasis` is implemented.

Well, I'm not sure if this `if` branch is necessary. `test_czichowski` was simply too large for pure Python and Buchberger's algorithm. Did you make any observation that `fglm()` is even more intensive on ground domain computations than `groebner()`?

Yes, for instance for cyclic5. groebner (f5b) takes about 14.5 seconds to compute a Gröbner basis wrt lex, groebner + fglm take about 40 seconds when converting from grevlex to lex. With gmpy, it takes about three seconds if I recall correctly.

The problem are the coefficients in P, which are often very complicated.

Collaborator

Actually it seems logical (if I understand the use of matrices in Groebner bases algorithms). In this case we will have to use this `if` branch.

Commits on Aug 10, 2011
1. Jeremias Yehdegho authored
```FGLM converts a Groebner basis of a zero-dimensional ideal from one term
order to another. The current implementation loses some speed when
constructing the matrices which represent multiplication by a variable.
The actual conversion takes O(#variables * #solutions^3), where the
number of solutions counts multiplicity.
It uses lists of lists instead of matrices because mpqs become
sympy.core.numbers.Rational in a Matrix but mpqs are crucial for speed
as the entries in P tend to become very complicated.

Examples:
>>> F = [x**2 - x - 3*y + 1, y**2 - 2*x + y - 1]
>>> G = groebner(F, x, y, order='lex')
>>> fglm(G, 'lex', 'grlex', x, y)
[x**2 - x - 3*y + 1, -2*x + y**2 + y - 1]
>>> groebner(G, x, y, order='grlex')
[x**2 - x - 3*y + 1, -2*x + y**2 + y - 1]

To give an impression why this could be useful, consider cyclic5:
>>> a, b, c, d, e = symbols('a b c d e')
>>> F =  [a + b + c + d + e,
a*b + b*c + c*d + d*e + e*a,
a*b*c + b*c*d + c*d*e + d*e*a + e*a*b,
a*b*c*d + b*c*d*e + c*d*e*a + d*e*a*b + e*a*b*c,
a*b*c*d*e - 1]
>>> %timeit groebner(F, a, b, c, d, e, order='lex')
1 loops, best of 3: 42.2 s per loop
>>> %timeit G = groebner(F, a, b, c, d, e, order='grlex');
fglm(G, 'grlex', 'lex', a, b, c, d, e)
1 loops, best of 3: 2.99 s per loop```
2. Jeremias Yehdegho authored
```Instead of fglm(G, 'grevlex', 'lex', x, y, z) use fglm(G, ('grevlex',
'lex', x, y, z) or fglm(G, 'grevlex', x, y, z) (the default to_order is
'lex') (or fglm(G, ('grevlex'), x, y, z)).```
Commits on Aug 11, 2011
1. Jeremias Yehdegho authored
```Conflicts:
sympy/polys/groebnertools.py
sympy/polys/polytools.py
sympy/polys/tests/test_groebnertools.py```