diff --git a/Makefile.am b/Makefile.am index cb3948a8..658f6f73 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,6 +26,7 @@ checkdiff = test/diff/diff_bug-2nd-prime-bad.sh \ test/diff/diff_eco6-qq.sh \ test/diff/diff_elim-31.sh \ test/diff/diff_elim-qq.sh \ + test/diff/diff_elim-full-qq.sh \ test/diff/diff_empty-elim-qq.sh \ test/diff/diff_f4sat-31.sh \ test/diff/diff_f4sat-byone-31.sh \ diff --git a/README.md b/README.md index f3612103..e32f93d2 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,9 @@ thanks to the `-e` flag. The following command ``` will perform the Groebner basis computation eliminating the first variable. More generally, using `-e k` will eliminate the first `k` variables. +Over the rationals, only the basis of the elimination ideal is returned +by default; add the `--elim-full-basis` flag to get the full Groebner +basis w.r.t. the elimination order. # Solving over the real numbers diff --git a/configure.ac b/configure.ac index 2221b5a0..dd9079cc 100644 --- a/configure.ac +++ b/configure.ac @@ -168,6 +168,10 @@ AC_CONFIG_LINKS([ output_files/elim-qq.g2.e1.res:output_files/elim-qq.g2.e1.res output_files/elim-qq.g2.e2.res:output_files/elim-qq.g2.e2.res test/diff/diff_elim-qq.sh:test/diff/diff_elim-qq.sh + input_files/elim-full-qq.ms:input_files/elim-full-qq.ms + output_files/elim-full-qq.g2.e1.res:output_files/elim-full-qq.g2.e1.res + output_files/elim-full-qq.g2.e2.res:output_files/elim-full-qq.g2.e2.res + test/diff/diff_elim-full-qq.sh:test/diff/diff_elim-full-qq.sh input_files/empty-elim-qq.ms:input_files/empty-elim-qq.ms output_files/empty-elim-qq.g2.e1.res:output_files/empty-elim-qq.g2.e1.res output_files/empty-elim-qq.g2.e2.res:output_files/empty-elim-qq.g2.e2.res diff --git a/doc/msolve-tutorial.tex b/doc/msolve-tutorial.tex index 277358ff..c67ecdc7 100644 --- a/doc/msolve-tutorial.tex +++ b/doc/msolve-tutorial.tex @@ -631,8 +631,35 @@ \section{Computing Gr\"obner bases}\label{sec:grobner} where we see that the first $6$ polynomials are only in $w,x,y,z$, which corresponds to the elimination of the variable $t$. When the input coefficients lie in the field of rational numbers (hence, characteristic $0$), -the returned Gr\"obner basis is the one of the {\em elimination ideal}, i.e. they -have partial degree $0$ in the variables to eliminate. +the returned Gr\"obner basis is by default the one of the {\em elimination +ideal}, i.e. only the polynomials which have partial degree $0$ in the variables +to eliminate are returned. The full Gr\"obner basis with respect to the +elimination order can be obtained by adding the \verb+--elim-full-basis+ flag. +For instance, on the same system with rational coefficients, +\begin{tcolorbox} + \begin{verbatim} + ./msolve -e 1 --elim-full-basis -g 2 -f in.ms -o out.ms + \end{verbatim} +\end{tcolorbox} +returns +\begin{tcolorbox} + \begin{lstlisting} +#Reduced Groebner basis data +#--- +#field characteristic: 0 +#variable order: t, w, x, y, z +#monomial order: eliminating first variable, blocks: graded reverse lexicographical +#length of basis: 7 elements sorted by increasing leading monomials +#--- +[w*y^3-x*z^3, +x^4, +w*x^3, +w^2*x^2, +w^3*x, +w^4, +t*z-1]: + \end{lstlisting} +\end{tcolorbox} More generally, using \verb+-e k+ will eliminate the $k$ first variables. Thus, diff --git a/input_files/elim-full-qq.ms b/input_files/elim-full-qq.ms new file mode 100644 index 00000000..85046950 --- /dev/null +++ b/input_files/elim-full-qq.ms @@ -0,0 +1,5 @@ +x, y, a, b +0 +a*x^2+b*y-1/3, +b*x*y-a+2, +x^3-7/5*y^2+a*b diff --git a/output_files/elim-full-qq.g2.e1.res b/output_files/elim-full-qq.g2.e1.res new file mode 100644 index 00000000..87e0718b --- /dev/null +++ b/output_files/elim-full-qq.g2.e1.res @@ -0,0 +1,17 @@ +#Reduced Groebner basis data +#--- +#field characteristic: 0 +#variable order: x, y, a, b +#monomial order: eliminating first variable, blocks: graded reverse lexicographical +#length of basis: 10 elements sorted by increasing leading monomials +#--- +[21*y^3*a*b-15*y*a^2*b^2+15*y*a*b-30*y*b-5*a+10, +63*y^2*a^3-45*a^4*b-126*y^2*a^2+90*a^3*b+15*y^2*b^2+45*a^3-180*a^2-5*y*b+180*a, +3*y^3*b^3-y^2*b^2+3*a^3-12*a^2+12*a, +756*y^2*a^2*b^2-540*a^3*b^3-90*y^2*b^4-378*y^2*a^2*b-21*y^3*b^2+270*a^3*b^2+15*y*a*b^3+756*y^2*a*b+30*y*b^3-126*y*a^2-270*a^2*b-15*y*b^2-1080*a*b^2+252*y*a+1080*a*b-1075*b, +21*y^4*b^2-15*y^2*a*b^3+126*y^2*a^2-90*a^3*b+15*y^2*b^2-252*y^2*a+180*a^2*b+90*a^2-5*y*b-360*a+360, +2646*y^4*a^2-1350*a^4*b^2-7560*y^2*a^2*b+5400*a^3*b^2+900*y^2*b^3+3780*y^2*a^2+105*y^3*b-75*y*a*b^2-7560*y^2*a-5400*a^2*b-300*y*b^2+1350*a^2+75*y*b+10800*a*b-5400*a+5375, +15*y*a^2*b^4-7*y^2*a*b^2-15*y*a*b^3+21*a^4+30*y*b^3-84*a^3+5*a*b^2+84*a^2-10*b^2, +15*y^2*a*b^4-126*y^2*a^2*b-7*y^3*b^2+90*a^3*b^2-15*y^2*b^3+21*y*a^3+252*y^2*a*b-180*a^2*b^2-84*y*a^2-90*a^2*b+5*y*b^2+84*y*a+360*a*b-360*b, +10800*a^3*b^5+1800*y^2*b^6+900*y^2*b^5-300*y*a*b^5-30240*y^2*a*b^3-5040*y*a^2*b^3+450*y^2*b^4-150*y*a*b^4-600*y*b^5+21168*y*a^4+1890*y^2*a^2*b+105*y^3*b^2-7560*y^2*a*b^2+2520*y*a^2*b^2-1350*a^3*b^2+30380*y^2*b^3-75*y*a*b^3+5400*a^2*b^3+21600*a*b^4-84672*y*a^3-3780*y^2*a*b+1260*y*a^2*b-420*a^3*b+70*y^2*b^2+5040*y*a*b^2+2700*a^2*b^2-10800*a*b^3+85302*y*a^2-210*a^3-2520*y*a*b+3030*a^2*b-20085*y*b^2-5400*a*b^2+21500*b^3-1260*y*a+840*a^2-8760*a*b+10750*b^2-840*a+8735*b, +5*x-21*y^2*a+15*a^2*b-15*a+30]: diff --git a/output_files/elim-full-qq.g2.e2.res b/output_files/elim-full-qq.g2.e2.res new file mode 100644 index 00000000..e6ad07b6 --- /dev/null +++ b/output_files/elim-full-qq.g2.e2.res @@ -0,0 +1,22 @@ +#Reduced Groebner basis data +#--- +#field characteristic: 0 +#variable order: x, y, a, b +#monomial order: eliminating first 2 variables, blocks: graded reverse lexicographical +#length of basis: 15 elements sorted by increasing leading monomials +#--- +[30375*a^6*b^9-91125*a^5*b^8+182250*a^4*b^8-4725*a^5*b^6+91125*a^4*b^7+39690*a^7*b^3-364500*a^3*b^7-83349*a^9-158760*a^6*b^3+14175*a^4*b^5-30375*a^3*b^6+364500*a^2*b^7+666792*a^8-99225*a^6*b^2+158760*a^5*b^3-28350*a^3*b^5+182250*a^2*b^6-1125*a*b^7-2000376*a^7+595350*a^5*b^2-23625*a^3*b^4-364500*a*b^6+2667168*a^6-1190700*a^4*b^2+94500*a^2*b^4+243000*b^6-1333584*a^5+793800*a^3*b^2-94500*a*b^4+175*b^4, +315*y*a^4*b^3-1323*y*a^6+5292*y*a^5-945*y*a^3*b^2-5292*y*a^4+1890*y*a^2*b^2-75*y*b^4-675*a^5*b^5+1350*a^4*b^4-2700*a^3*b^4-675*a^3*b^3+2700*a^2*b^3+105*a^3*b-2700*a*b^3-210*a^2*b+25*b^3, +3969*y*a^6*b+225*y*a*b^6-23814*y*a^5*b+1890*y*a^3*b^3+47628*y*a^4*b-7560*y*a^2*b^3-31752*y*a^3*b+7560*y*a*b^3-35*y*b^3+2025*a^5*b^6-4050*a^4*b^6-4050*a^4*b^5+16200*a^3*b^5-315*a^4*b^3+2025*a^3*b^4-16200*a^2*b^5+1323*a^6+630*a^3*b^3-12150*a^2*b^4-7938*a^5+630*a^3*b^2+24300*a*b^4+15876*a^4-2520*a^2*b^2-16200*b^4-10584*a^3+2520*a*b^2, +1125*y*b^8+83349*y*a^7-735*y*a^3*b^4+9450*y*a^2*b^5-833490*y*a^6+3087*y*a^5*b+59535*y*a^4*b^2+238140*y*a^3*b^3-37800*y*a*b^5+2333772*y*a^5-12348*y*a^4*b-476280*y*a^3*b^2-156555*y*a^2*b^3+4725*y*a*b^4+37800*y*b^5-2000376*y*a^4+12348*y*a^3*b+714420*y*a^2*b^2-4410*y*a*b^3-28350*y*b^4+10125*a^5*b^9-20250*a^4*b^8+42525*a^6*b^5+40500*a^3*b^8-255150*a^5*b^5+10125*a^3*b^7+13230*a^6*b^3-85050*a^5*b^4-40500*a^2*b^7-27783*a^8-52920*a^5*b^3+680400*a^4*b^4+40500*a*b^7+222264*a^7-26460*a^5*b^2+95445*a^4*b^3-1020600*a^3*b^4-375*b^7-666792*a^6+158760*a^4*b^2-425250*a^3*b^3-3150*a^2*b^4+889056*a^5-6615*a^4*b-317520*a^3*b^2+1190700*a^2*b^3+12600*a*b^4-444528*a^4+52920*a^3*b+211435*a^2*b^2-1022175*a*b^3-12600*b^4-79380*a^2*b+490*a*b^2+9450*b^3, +675*y*a^2*b^6+1350*y*a*b^6-47628*y*a^5*b-5670*y*a^3*b^3-1350*y*a*b^5+23814*y*a^5+190512*y*a^4*b-22680*y*a^2*b^3-95256*y*a^4-190512*y*a^3*b+17010*y*a^2*b^2+45255*y*a*b^3+675*y*b^4+95697*y*a^3-34020*y*a*b^2-210*y*b^3-882*y*a^2+210*y*b^2-24300*a^4*b^6+12150*a^4*b^5+48600*a^3*b^5-24300*a^3*b^4-97200*a^2*b^5+945*a^4*b^2+3780*a^3*b^3+24300*a^2*b^4-15876*a^5-1890*a^3*b^2+12150*a^2*b^3+97425*a*b^4+63504*a^4-945*a^3*b-7560*a^2*b^2-48600*a*b^3-97200*b^4-63504*a^3+1890*a^2*b+15120*a*b^2+48375*b^3-35*b, +83349*y*a^8+4725*y*a^3*b^5-666792*y*a^7+59535*y*a^5*b^2-9450*y*a^2*b^5+1125*y*b^7+2000376*y*a^6-357210*y*a^4*b^2-735*y*a^3*b^3+9450*y*a^2*b^4-2664081*y*a^5+714420*y*a^3*b^2-37800*y*a*b^4+1321236*y*a^4-474810*y*a^2*b^2+37800*y*b^4+12348*y*a^3-2940*y*a*b^2+10125*a^5*b^8+42525*a^7*b^5-170100*a^6*b^5-20250*a^4*b^7-85050*a^6*b^4+170100*a^5*b^5+40500*a^3*b^7+510300*a^5*b^4+10125*a^3*b^6+6615*a^6*b^2+42525*a^5*b^3-1020600*a^4*b^4-40500*a^2*b^6-26460*a^5*b^2-340200*a^4*b^3+680400*a^3*b^4+40500*a*b^6-13230*a^5*b+26460*a^4*b^2+1020600*a^3*b^3-375*b^6+79380*a^4*b-1363950*a^2*b^3-158760*a^3*b+693000*a*b^3+105595*a^2*b-12600*b^3+490*a*b, +5*x*b^2-45*y*a^2*b^4+45*y*a*b^3-90*y*b^3+15*a^2*b^3-63*a^4+252*a^3-30*a*b^2-252*a^2+60*b^2, +147*x*a^2-294*x*a-4050*y*a*b^7+142884*y*a^5*b^2-17010*y*a^3*b^4-571536*y*a^4*b^2+102060*y*a^2*b^4+4050*y*b^6+571536*y*a^3*b^2+17010*y*a^2*b^3-135765*y*a*b^4-68040*y*a*b^3+630*y*b^4-2646*y*a^2*b+67725*y*b^3+5292*y*a*b-49*y*b+72900*a^4*b^7-145800*a^3*b^6+291600*a^2*b^6-11340*a^3*b^4+72900*a^2*b^5+47628*a^5*b-291600*a*b^5-23814*a^5-190512*a^4*b+22680*a^2*b^3+290250*b^5+142884*a^4+190512*a^3*b-11340*a^2*b^2-45360*a*b^3-285327*a^3+45360*a*b^2+188748*a^2-45255*b^2+1764*a, +21*y^2*a-5*x-15*a^2*b+15*a-30, +49*y^2*b^2+1350*y*a*b^7-47628*y*a^5*b^2+5670*y*a^3*b^4+190512*y*a^4*b^2-34020*y*a^2*b^4-1350*y*b^6-190512*y*a^3*b^2-5670*y*a^2*b^3+45255*y*a*b^4+22680*y*a*b^3-210*y*b^4+882*y*a^2*b-22575*y*b^3-1764*y*a*b-24300*a^4*b^7+48600*a^3*b^6-97200*a^2*b^6+3780*a^3*b^4-24300*a^2*b^5-15876*a^5*b+97200*a*b^5+7938*a^5+63504*a^4*b-7560*a^2*b^3-96750*b^5-47628*a^4-63504*a^3*b+3780*a^2*b^2+15120*a*b^3+95109*a^3-15120*a*b^2-62916*a^2+15085*b^2-588*a, +x*y*b-a+2, +35*x^2*b-105*x*a*b+210*x*b-225*y*a*b^6+7938*y*a^5*b-31752*y*a^4*b+3780*y*a^2*b^3+225*y*b^5+31752*y*a^3*b-7560*y*a*b^3+35*y*b^3-147*y*a^2+294*y*a+4050*a^4*b^6-8100*a^3*b^5+16200*a^2*b^5-630*a^3*b^3+4050*a^2*b^4+2646*a^5-315*a^3*b^2-16200*a*b^4-10584*a^4+1890*a^2*b^2+16125*b^4+10584*a^3-2520*a*b^2, +3*x^2*a+3*y*b-1, +21*y^3*b+30*x^2-15*y*a*b^2+15*y*b-5, +5*x^3-7*y^2+5*a*b]: diff --git a/src/msolve/duplicate.c b/src/msolve/duplicate.c index 0bddb533..ebf411c5 100644 --- a/src/msolve/duplicate.c +++ b/src/msolve/duplicate.c @@ -396,7 +396,7 @@ static inline void duplicate_data_mthread_gbtrace(int nthreads, trace_t **btrace){ - const len_t len = num_gb[0] * (st->nvars - st->nev); + const len_t len = num_gb[0] * lifted_nvars(st); for(int i = 0; i < nthreads; i++){ leadmons_current[i] = (int32_t *)calloc(len, sizeof(int32_t)); diff --git a/src/msolve/lifting-gb.c b/src/msolve/lifting-gb.c index bda35a8b..8aa9c1cc 100644 --- a/src/msolve/lifting-gb.c +++ b/src/msolve/lifting-gb.c @@ -692,6 +692,17 @@ static inline int32_t compute_num_gb(int32_t *bexp_lm, int32_t len, int nv, int return len; } +/* returns 1 if only the basis of the elimination ideal is lifted, i.e. the + * eliminated variables are dropped, else returns 0 */ +static inline int lift_elim_ideal_only(const md_t *st){ + return st->nev > 0 && !st->elim_full_basis; +} + +/* returns the number of variables of the lifted leading monomials */ +static inline int lifted_nvars(const md_t *st){ + return lift_elim_ideal_only(st) ? st->nvars - st->nev : st->nvars; +} + static int32_t gb_modular_trace_learning(gb_modpoly_t modgbs, int32_t *mgb, int32_t *num_gb, @@ -737,9 +748,11 @@ static int32_t gb_modular_trace_learning(gb_modpoly_t modgbs, leadmons[0] = bexp_lm; int32_t len = bs->lml; - num_gb[0] = compute_num_gb(bexp_lm, len, bht->nv, st->nev); + const int nvl = lifted_nvars(st); + num_gb[0] = compute_num_gb(bexp_lm, len, bht->nv, + lift_elim_ideal_only(st) ? st->nev : 0); int32_t *bexp_lm2 = NULL; - if(st->nev){ + if(lift_elim_ideal_only(st)){ bexp_lm2 = calloc(num_gb[0]*(bht->nv - st->nev), sizeof(int32_t)); for(int32_t i = 0; i < num_gb[0]; i++){ for(int j = 0; j < bht->nv - st->nev; j++){ @@ -762,13 +775,13 @@ static int32_t gb_modular_trace_learning(gb_modpoly_t modgbs, /************************************************/ - int32_t *lens = array_of_lengths(leadmons[0], num_gb[0], bs, bht->nv - st->nev); + int32_t *lens = array_of_lengths(leadmons[0], num_gb[0], bs, nvl); if(truncate_lifting != 0 && truncate_lifting < num_gb[0]){ - gb_modpoly_init(modgbs, 2, lens, bs, bht->nv - st->nev, truncate_lifting, leadmons[0], st); + gb_modpoly_init(modgbs, 2, lens, bs, nvl, truncate_lifting, leadmons[0], st); } else{ - gb_modpoly_init(modgbs, 2, lens, bs, bht->nv - st->nev, num_gb[0], leadmons[0], st); + gb_modpoly_init(modgbs, 2, lens, bs, nvl, num_gb[0], leadmons[0], st); } free(lens); modpgbs_set(modgbs, bs, bht, fc, start, st->nev); @@ -827,7 +840,16 @@ static void gb_modular_trace_application(gb_modpoly_t modgbs, int32_t error = 0; bs = core_gba(bs_qq, st, &error, lp->p[0]); *stf4 = realtime()-rt; + if (bs == NULL) { + bad_primes[0] = 1; + return; + } ht_t **bht = &(bs->ht); + if(bs->lml < modgbs->ld){ + bad_primes[0] = 2; + free_basis_and_only_local_hash_table_data(&bs); + return; + } for(len_t i = 0; i < modgbs->ld; i++){ if(modgbs->modpolys[i]->len < bs->hm[bs->lmps[i]][LENGTH]-1){ bad_primes[0] = 2; @@ -840,12 +862,8 @@ static void gb_modular_trace_application(gb_modpoly_t modgbs, return; } } - if (bs == NULL) { - bad_primes[0] = 1; - return; - } int32_t lml = bs->lml; - if (st->nev > 0) { + if (lift_elim_ideal_only(st)) { int32_t j = 0; for (len_t i = 0; i < bs->lml; ++i) { if ((*bht)->ev[bs->hm[bs->lmps[i]][OFFSET]][0] == 0) { @@ -864,7 +882,7 @@ static void gb_modular_trace_application(gb_modpoly_t modgbs, return; } - if(st->nev){ + if(lift_elim_ideal_only(st)){ get_lm_from_bs_trace_elim(bs, bht[0], leadmons_current[0], num_gb[0]); } else{ @@ -872,7 +890,7 @@ static void gb_modular_trace_application(gb_modpoly_t modgbs, } if(!equal_staircase(leadmons_current[0], leadmons_ori[0], - num_gb[0], num_gb[0], bht[0]->nv - st->nev)){ + num_gb[0], num_gb[0], lifted_nvars(st))){ bad_primes[0] = 1; } @@ -1381,7 +1399,7 @@ gb_modpoly_t *core_groebner_qq( if(!dlinit){ int nb = 0; int32_t *ldeg = array_nbdegrees((*msd->leadmons_ori), msd->num_gb[0], - bs->ht->nv - st->nev, &nb); + lifted_nvars(st), &nb); data_lift_init(dlift, (*modgbsp)->ld, ldeg, nb); choose_coef_to_lift((*modgbsp), dlift); free(ldeg); @@ -1790,6 +1808,7 @@ gb_modpoly_t *groebner_qq( fprintf(ERRSTREAM,"Bad input data, stopped computation.\n"); exit(1); } + md->elim_full_basis = gens->elim_full_basis; initialize_mstrace(msd, md, bs); int err = 0; @@ -1856,7 +1875,15 @@ void print_msolve_gbtrace_qq(data_gens_ff_t *gens, fprintf(ofile, "%s, ", gens->vnames[i]); } fprintf(ofile, "%s\n", gens->vnames[gens->nvars-1]); - fprintf(ofile, "#monomial order: graded reverse lexicographical\n"); + if (gens->elim_full_basis && flags->elim_block_len > 0) { + if (flags->elim_block_len == 1) { + fprintf(ofile, "#monomial order: eliminating first variable, blocks: graded reverse lexicographical\n"); + } else { + fprintf(ofile, "#monomial order: eliminating first %d variables, blocks: graded reverse lexicographical\n", flags->elim_block_len); + } + } else { + fprintf(ofile, "#monomial order: graded reverse lexicographical\n"); + } if ((*modgbsp)->ld == 1) { fprintf(ofile, "#length of basis: 1 element\n"); } else { diff --git a/src/msolve/main.c b/src/msolve/main.c index 1a90b2d2..13fe0946 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -136,6 +136,12 @@ static inline void display_help(char *str){ display_option_help_noopt("between 1 and #variables-1, and gives the number of\n"); display_option_help_noopt("eliminated variables. The basis with the first block of\n"); display_option_help_noopt("ELIM variables eliminated is then computed.\n"); + display_option_help_noopt("Over the rationals, only the elements of the basis\n"); + display_option_help_noopt("which do not involve the eliminated variables are\n"); + display_option_help_noopt("returned by default (see --elim-full-basis).\n"); + display_option_help(0, "elim-full-basis", "", "Over the rationals, combined with -e, return the\n"); + display_option_help_noopt("full Groebner basis w.r.t. the elimination order\n"); + display_option_help_noopt("instead of the basis of the elimination ideal only.\n"); display_option_help('I', "isolate", "ISOL", "Isolates the real roots (provided some univariate data)\n"); display_option_help_noopt("without re-computing a Gröbner basis\n"); display_option_help_noopt("0 - no (default).\n"); @@ -201,6 +207,7 @@ static void getoptions( int32_t *nthreads, int32_t *max_pairs, int32_t *elim_block_len, + int32_t *elim_full_basis, int32_t *linear_algebra, int32_t *use_signatures, int32_t *update_ht, @@ -236,12 +243,14 @@ static void getoptions( see https://cgit.git.savannah.gnu.org/cgit/coreutils.git/tree/src/ls.c */ enum { RANDOM_SEED_OPTION = CHAR_MAX + 1, + ELIM_FULL_BASIS_OPTION, /* Below is the template for the next long option with * no equivalent short option */ /* NEXT_OPTION */ }; struct option long_options[] = { {"elimination", required_argument, NULL, 'e'}, + {"elim-full-basis", no_argument, NULL, ELIM_FULL_BASIS_OPTION}, {"file", required_argument, NULL, 'f'}, {"groebner-basis", required_argument, NULL, 'g'}, {"help", no_argument, NULL, 'h'}, @@ -410,6 +419,9 @@ static void getoptions( case RANDOM_SEED_OPTION: *seed = strtoll(optarg, NULL, 10); break; + case ELIM_FULL_BASIS_OPTION: + *elim_full_basis = 1; + break; /* Below is the template for the next long option with * no equivalent short option */ /* case NEXT_OPTION: */ @@ -452,6 +464,7 @@ int main(int argc, char **argv){ int32_t initial_hts = 17; int32_t max_pairs = 0; int32_t elim_block_len = 0; + int32_t elim_full_basis = 0; int32_t update_ht = 0; int32_t generate_pbm = 0; int32_t reduce_gb = 1; @@ -478,7 +491,7 @@ int main(int argc, char **argv){ files->out_file = NULL; files->bin_out_file = NULL; getoptions(argc, argv, &initial_hts, &nr_threads, &max_pairs, - &elim_block_len, &la_option, &use_signatures, &update_ht, + &elim_block_len, &elim_full_basis, &la_option, &use_signatures, &update_ht, &reduce_gb, &print_gb, &truncate_lifting, &genericity_handling, &unstable_staircase, &saturate, &colon, &normal_form, &normal_form_matrix, &is_gb, &lift_matrix, &get_param, @@ -545,7 +558,10 @@ int main(int argc, char **argv){ gens->rand_linear = 0; gens->random_linear_form = malloc(sizeof(int32_t)*(nr_vars)); - gens->elim = elim_block_len; + /* over QQ, the eliminated variables are dropped from the output + * unless the full basis is requested */ + gens->elim_full_basis = elim_full_basis; + gens->elim = elim_full_basis ? 0 : elim_block_len; if(0 < field_char && field_char < pow(2, 15) && la_option > 2){ if(info_level){ diff --git a/src/msolve/msolve-data.h b/src/msolve/msolve-data.h index ff224a41..7e6b2e84 100644 --- a/src/msolve/msolve-data.h +++ b/src/msolve/msolve-data.h @@ -54,7 +54,12 @@ typedef int64_t bits_t; typedef struct{ nvars_t nvars; + /* number of eliminated variables which are dropped from the output + * (characteristic 0 only) */ nvars_t elim; + /* over QQ with an elimination order: if nonzero, the full basis is + * computed, otherwise only the basis of the elimination ideal */ + int32_t elim_full_basis; int32_t ngens; int32_t nterms; int32_t field_char; diff --git a/src/msolve/msolve.c b/src/msolve/msolve.c index c3276d6d..5a6038bf 100644 --- a/src/msolve/msolve.c +++ b/src/msolve/msolve.c @@ -35,6 +35,7 @@ static inline void duplicate_data_mthread_gbtrace(int nthreads, int32_t **leadmons_ori, int32_t **leadmons_current, trace_t **btrace); +static inline int lifted_nvars(const md_t *st); static inline mpz_t *allocate_crt_linear_forms(int nlins, int nv, uint32_t **lineqs_ptr); @@ -333,6 +334,7 @@ data_gens_ff_t *allocate_data_gens() { gens->random_linear_form = NULL; gens->elim = 0; + gens->elim_full_basis = 0; return gens; } diff --git a/src/neogb/data.h b/src/neogb/data.h index 4dc09bf2..ebaaa259 100644 --- a/src/neogb/data.h +++ b/src/neogb/data.h @@ -430,6 +430,9 @@ struct md_t int32_t print_gb; int32_t truncate_lifting; + /* over QQ with an elimination order: if nonzero, the full basis is + * lifted, otherwise only the basis of the elimination ideal */ + int32_t elim_full_basis; /* for f4sat */ uint32_t new_multipliers; diff --git a/test/diff/diff_elim-full-qq.sh b/test/diff/diff_elim-full-qq.sh new file mode 100755 index 00000000..e218b41d --- /dev/null +++ b/test/diff/diff_elim-full-qq.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +file=elim-full-qq + +source test/diff/diff_source.sh + +# full Groebner basis w.r.t. an elimination order over the rationals, +# not only the basis of the elimination ideal +for e in 1 2; do + for t in 1 2; do + for l in 2 44; do + $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.$e.$t.$l.res \ + --random-seed $seed \ + -e $e --elim-full-basis -g 2 -l $l -t $t + if [ $? -gt 0 ]; then + print_exit 1 + fi + + diff test/diff/$file.$e.$t.$l.res output_files/$file.g2.e$e.res + if [ $? -gt 0 ]; then + print_exit 2 + fi + + rm test/diff/$file.$e.$t.$l.res + done + done +done + +normal_exit