Skip to content

Conversation

@andrii302
Copy link
Contributor

Added a fmpz_mod_mpoly version of Buchberger algorithm used in fmpz_mod_mpoly.

Comment on lines 977 to 978
void _fmpz_mod_mpoly_vec_fmpz_mod_mpoly_to_fmpz_mpoly(fmpz_mpoly_vec_t ret, fmpz_mod_mpoly_vec_t src, fmpz_mod_mpoly_ctx_t ctx);
void _fmpz_mod_mpoly_vec_fmpz_mpoly_to_fmpz_mod_mpoly(fmpz_mod_mpoly_vec_t ret, fmpz_mpoly_vec_t src, fmpz_mod_mpoly_ctx_t ctx);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are these defined? I can't seem to find it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this file if it is unused

#endif

#include "fmpz.h"
#include "fmpz_mpoly.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this inclusion is necessary.

if (fmpz_mod_mpoly_length(poly, ctx) > poly_len_limit)
return 0;

bits = _fmpz_vec_max_bits(poly->coeffs, poly->length);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer needed.

-------------------------------------------------------------------------------

The following methods deal with ideals in `\mathbb{Z}/n\mathbb{Z}[x_1, \dots, x_m]`.
We use primitive integer polynomials as normalised generators
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The normalised generators will be monic, not primitive integer polynomials.

for (i = 0; i < n; i++)
exp[i] = FLINT_MAX(expf[i], expg[i]);

fmpz_mod_inv(c, f->coeffs, ctx->ffinfo);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can check if the leading coefficients are 1, and then you don't need to invert them and multiply by them below.

#include "fmpz_mod_mpoly.h"

void
fmpz_mod_mpoly_vec_set_monic_unique(fmpz_mod_mpoly_vec_t G, const fmpz_mod_mpoly_vec_t F, const fmpz_mod_mpoly_ctx_t ctx)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File should be renamed to match the function name.

fmpz_mod_mpoly_vec_init(H, 0, ctx);


// flint_printf("iter %ld %ld %d %d \n\n", iter, nvars, ctx->minfo->ord, m);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a comment, but you can change the format string to iter %wd %wd %d %{fmpz}

@fredrik-johansson
Copy link
Collaborator

There is maybe some bug in the algorithm.

I tried to get some bigger examples by setting

        if (nvars == 4)
            fmpz_mod_mpoly_vec_randtest_not_zero(F, state, 1 + n_randint(state, 3), 1 + n_randint(state, 3), 1 + n_randint(state, 3), ctx);
        else if (nvars == 3)
            fmpz_mod_mpoly_vec_randtest_not_zero(F, state, 1 + n_randint(state, 4), 1 + n_randint(state, 4), 1 + n_randint(state, 4), ctx);
        else
            fmpz_mod_mpoly_vec_randtest_not_zero(F, state, 1 + n_randint(state, 6), 1 + n_randint(state, 6), 1 + n_randint(state, 5), ctx);

On iteration 224 we get

iter 224   3  0    4722366482869611659327 

F = [4491077222722822274764*x1^3*x2^2*x3^3+1142989093829542840957*x1*x2*x3+161135877041952360283*x2^2*x3^2+1963195568815792903903*x3^2, 473518656873042772582*x1^3*x2^2*x3^2+538964973504606229287*x1^3*x3^3+2996428526938692536564*x1^2*x2^2*x3^2+1389613235437080610847*x1*x3]

Sage tells me

sage: R.<x1,x2,x3> = PolynomialRing(GF(4722366482869611659327))
sage: F = [4491077222722822274764*x1^3*x2^2*x3^3+1142989093829542840957*x1*x2*x3+161135877041952360283*x2^2*x3^2+1963195568815792903903*x3^2, 473518656873042772582*x1^3*x2^2*x3^2+538964973504606229287*x1^3*x3^3+
....: 2996428526938692536564*x1^2*x2^2*x3^2+1389613235437080610847*x1*x3]
sage: Ideal(F).groebner_basis()
[x2^6*x3^3 + 712996795176620819850*x1^3*x2^4*x3 + 2991372772035270063807*x2^6*x3^2 + 2232673190335890371919*x1^3*x2*x3^4 + 4622290847937109124679*x2^4*x3^4 + 2232118258695245099135*x1*x2^2*x3^5 + 1337247136055595098177*x1^2*x2^4*x3 + 3809242543601178032643*x1*x2^5*x3 + 2255749836307100781426*x1^2*x2^3*x3^2 + 3522766432234796391146*x1^3*x2*x3^3 + 674045606485042985327*x1*x2^3*x3^3 + 144410032056534803816*x2^4*x3^3 + 3742288888964036579985*x1^3*x3^4 + 3806698843246029539861*x1^2*x2*x3^4 + 1261854264738708411457*x1*x2^2*x3^4 + 3174422527955615953712*x1^2*x2^3*x3 + 1309130462284157687072*x1^2*x2^2*x3^2 + 511509324830378656330*x1*x2^3*x3^2 + 3843146600048663289891*x2^4*x3^2 + 1426607345279955621580*x1^3*x3^3 + 2931203426717357998872*x1^2*x2*x3^3 + 3765559273451236887495*x1^2*x3^4 + 1800815570161933110697*x2^2*x3^4 + 4362577392138830451491*x1*x3^5 + 1749266203946741954616*x1*x2^3*x3 + 603762769168935094984*x1^2*x2*x3^2 + 802440712834424206579*x1*x2^2*x3^2 + 2312779589572324370120*x2^3*x3^2 + 2862441150645602461203*x1*x2*x3^3 + 2301513304013421389416*x2^2*x3^3 + 3830223109782334087895*x1*x3^4 + 1845529563375065208582*x1*x2^2*x3 + 3916000751915517880153*x1*x2*x3^2 + 4454114546813219238110*x2^2*x3^2 + 1771132791807173937207*x1*x3^3 + 19748604038564336348*x3^4 + 2619902816384677653484*x1*x2*x3 + 1629376223837254477255*x1*x3^2 + 2341798583917537710307*x2*x3^2 + 452050843028990228886*x3^3 + 3302703954367051778374*x1*x3 + 852676813439846411794*x3^2,
 x1^4*x2^3*x3 + 1426516598602069476079*x1^3*x2^3*x3 + 100075634932502534648*x1^4*x2*x3^2 + 1540191522950982634971*x1^4*x3^3 + 2181333662874204585127*x1^2*x2^2*x3^2 + 2254146332524917002871*x1^3*x3^3 + 1821799783765970911452*x1*x2^2*x3 + 2808277818627968062792*x1^2*x3 + 2504251270690830754814*x1*x3,
 x1^4*x3^4 + 1446493953846792653206*x1*x2^2*x3^2 + 2888952530396186513897*x1^2*x2*x3 + 12295073657520105697*x1^2*x3^2 + 991501011636667918886*x2^2*x3^2 + 1777109014141401984424*x1*x2*x3 + 2577407212188895213663*x1*x3^2 + 172392630374498717073*x3^2,
 x1^3*x3^5 + 1134726875404767220728*x1^2*x2^3*x3^2 + 232381224220883413991*x2^4*x3^3 + 4445847190008855697024*x1^3*x3^4 + 4432758092541225535985*x1*x2^2*x3^4 + 1046038837962674726577*x1*x2^3*x3^2 + 2657044711577393369498*x2^4*x3^2 + 1075309877823930528429*x1^2*x2*x3^3 + 2261868349800318839345*x1^2*x3^4 + 1394206333302585142984*x1*x2^3*x3 + 1698811328637074417449*x1*x2^2*x3^2 + 115279397433147445704*x2^2*x3^3 + 74882451101184199473*x1*x3^4 + 1055538577922761368467*x1*x2*x3^2 + 507487343683842385767*x2^2*x3^2 + 12295073657520105697*x1*x3^3 + 3080264025967845729397*x1*x2*x3 + 2697119451786508761151*x1*x3^2 + 432447941508178767999*x3^3 + 2571238725551279090344*x3^2,
 x1^3*x2^2*x3^2 + 1426516598602069476079*x1^2*x2^2*x3^2 + 100075634932502534648*x1^3*x3^3 + 4035834253805165078146*x1*x3,
 x1*x2^4*x3^2 + 4108625839513552360366*x1^2*x2^3*x3 + 3202032657719516531780*x1^2*x2^2*x3^2 + 1426516598602069476079*x2^4*x3^2 + 100075634932502534648*x1*x2^2*x3^3 + 2503195822188664255580*x1*x2^3*x3 + 4048320876384568674000*x1^2*x2*x3^2 + 898560334578367526013*x1*x2^2*x3^2 + 2945259352879771335346*x2^2*x3^2 + 384260550207056090205*x1*x3^3,
 x1^2*x2^2*x3^3 + 4271013918249353011579*x1^3*x3^4 + 2786951067681631733096*x2^2*x3^2 + 1709684415700564492299*x1*x2*x3 + 2045591994075599314921*x1*x3^2 + 4461913745913676329068*x3^2]

But the vector H computed by fmpz_mod_mpoly_buchberger_naive + fmpz_mod_mpoly_vec_autoreduction_groebner here is something much bigger.

I guess one can find a much smaller bad case; I just took the first really big one I saw that looked suspect.

@fredrik-johansson
Copy link
Collaborator

More manageable example:

3 variables, mod 17

F = [6*x1^2*x2+14*x2*x3^2+6, 3*x1^2*x2^2*x3+4*x1*x2+3*x3^2, 15*x1^2*x3+2*x1*x2^2+4*x3^2]
H = [x3^21+x3^20+11*x3^19+16*x3^18+8*x3^16+x3^15+6*x3^14+16*x3^13+11*x3^12+4*x3^11+7*x3^10+3*x3^9+16*x3^8+8*x3^7+13*x3^6+5*x3^5+8*x3^3+15*x3^2+10, x1+5*x3^20+6*x3^18+16*x3^17+9*x3^16+10*x3^15+6*x3^14+13*x3^13+16*x3^12+10*x3^11+8*x3^10+4*x3^9+6*x3^8+16*x3^7+6*x3^6+12*x3^4+9*x3^2+7*x3+12, x2+16*x3^20+4*x3^19+14*x3^18+6*x3^17+11*x3^16+9*x3^15+12*x3^14+4*x3^13+8*x3^12+15*x3^11+14*x3^10+12*x3^9+14*x3^8+15*x3^7+15*x3^6+3*x3^5+7*x3^4+16*x3^3+9*x3^2+3*x3+10]

Sage says that H is not a Groebner basis.

@fredrik-johansson
Copy link
Collaborator

Oh wait, I'm stupid. I forgot about term orders! SageMath doesn't use lex ordering by default. The H is indeed a lex Groebner basis. So I think there's no problem.

@fredrik-johansson
Copy link
Collaborator

fredrik-johansson commented Oct 29, 2025

Fun fact: I tried

sage: R.<x1,x2,x3> = PolynomialRing(GF(4722366482869611659327), order="lex")
sage: 
....: F = [4491077222722822274764*x1^3*x2^2*x3^3+1142989093829542840957*x1*x2*x3+161135877041952360283*x2^2*x3^2+1963195568815792903903*x3^2, 473518656873042772582*x1^3*x2^2*x3^2+538964973504606229287*x1^3*x3^3+
....: 2996428526938692536564*x1^2*x2^2*x3^2+1389613235437080610847*x1*x3]
....: 
sage: %time G = Ideal(F).groebner_basis()

and it's still going after 20 minutes. FLINT did this one in 14 seconds. Is this Singular being slow, Sage doing something bad, or FLINT being fast?

Edit: Sage (Singular?) was killed by the OS after about 30 minutes.

{
fmpz_t c;
fmpz_mod_inv(c, f->coeffs, ctx->ffinfo);
fmpz_init(c);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fmpz_init needs to be moved one line up. Same in the block below.

@guyomes
Copy link

guyomes commented Oct 29, 2025

= PolynomialRing(GF(4722366482869611659327), order="lex")

One way that seems to work more efficiently in Sage is to use the transformed_basis function, that computes a lex Gröbner basis using Gröbner walk. It returns whithin a second on my laptop.

R.<x1,x2,x3>  = PolynomialRing(GF(4722366482869611659327), order='lex')
F = [4491077222722822274764*x1^3*x2^2*x3^3+1142989093829542840957*x1*x2*x3+161135877041952360283*x2^2*x3^2+1963195568815792903903*x3^2, 473518656873042772582*x1^3*x2^2*x3^2+538964973504606229287*x1^3*x3^3+ 2996428526938692536564*x1^2*x2^2*x3^2+1389613235437080610847*x1*x3]

S = R.change_ring(order='degrevlex')
G = (S*F).transformed_basis()

Edit: this basis does not seem reduced though. Reducing it took around 9 seconds on my laptop, and can be done as follows.

Gred = (R*G).groebner_basis()

@fredrik-johansson
Copy link
Collaborator

Output from FLINT: GB.txt

@edgarcosta
Copy link
Member

Magma converts between orders "automatically", I do not know the details.

> R<x1,x2,x3> := PolynomialRing(GF(4722366482869611659327), 3, "grevlex");
> F := [4491077222722822274764*x1^3*x2^2*x3^3+1142989093829542840957*x1*x2*x3+161135877041952360283*x2^2*x3^2+1963195568815792903903*x3^2, 473518656873042772582*x1^3*x2^2*x3^2+538964973\
504606229287*x1^3*x3^3+2996428526938692536564*x1^2*x2^2*x3^2+1389613235437080610847*x1*x3];
> time GB := GroebnerBasis(ideal<R|F>);
Time: 0.000
> R<x1,x2,x3> := PolynomialRing(GF(4722366482869611659327), 3, "lex");
> F := [4491077222722822274764*x1^3*x2^2*x3^3+1142989093829542840957*x1*x2*x3+161135877041952360283*x2^2*x3^2+1963195568815792903903*x3^2, 473518656873042772582*x1^3*x2^2*x3^2+538964973\
504606229287*x1^3*x3^3+2996428526938692536564*x1^2*x2^2*x3^2+1389613235437080610847*x1*x3];
> time GB := GroebnerBasis(ideal<R|F>);
Time: 0.030
> R<x1,x2,x3> := PolynomialRing(GF(4722366482869611659327), 3, "lex");
> F := [4491077222722822274764*x1^3*x2^2*x3^3+1142989093829542840957*x1*x2*x3+161135877041952360283*x2^2*x3^2+1963195568815792903903*x3^2, 473518656873042772582*x1^3*x2^2*x3^2+538964973\
> 504606229287*x1^3*x3^3+2996428526938692536564*x1^2*x2^2*x3^2+1389613235437080610847*x1*x3];
> time GB := GroebnerBasis(ideal<R|F> : Al:="Direct");
^C
[Interrupted]
Total time: 688.460 seconds, Total memory usage: 1774.78MB

@fredrik-johansson
Copy link
Collaborator

Naming:

fmpz_mod_mpoly_from_fmpz_mpoly -> fmpz_mod_mpoly_set_fmpz_mpoly
fmpz_mod_mpoly_to_fmpz_mpoly -> fmpz_mod_mpoly_get_fmpz_mpoly

@fredrik-johansson
Copy link
Collaborator

Can you undo the changes to fmpz_mpoly/test/t-buchberger_naive.c. Other than that, looks good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants