From d647349e21094a8b5b800c0277aa62ef7c5ab382 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 1 Sep 2023 17:12:46 +0100 Subject: [PATCH 01/13] started to address the bug --- lib/grobner.gi | 50 +++++++++++++++++++++++++++++++++++++++++------- lib/occurtree.gi | 5 ++++- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/lib/grobner.gi b/lib/grobner.gi index 9f7fd13..b168059 100644 --- a/lib/grobner.gi +++ b/lib/grobner.gi @@ -627,8 +627,9 @@ end);; ### GBNP.ReducePol2:=function(arg) -local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT; +local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT,done,one; G:=arg[1]; + one:=One(G[1][2][1]); if Length(arg)>=2 then GLOT:=arg[2]; lts:=LMonsNP(G); @@ -650,13 +651,37 @@ local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT; SortParallel(lts,G,LtNP); GBNP.SortParallelLOT(temp,GLOT,LtNP); else - for i in [1..Length(G)] do - G[i]:=GBNP.ReduceCancellation(G[i]); - od; - lts:=LMonsNP(G); - SortParallel(lts,G,LtNP); + done := false; + while not done do + for i in [1..Length(G)] do + G[i]:=GBNP.ReduceCancellation(G[i]); + od; + lts:=LMonsNP(G); + SortParallel(lts,G,LtNP); + done := true; + for i in Reversed( [1..Length(lts)-1] ) do + if ( lts[i] = lts[i+1] ) then + done := false; +## Print( "G[i],G[i+1] = ", G[i], G[i+1], "\n" ); + G[i+1] := CleanNP(AddNP(G[i+1],G[i],one,-one)); +## Print( "new G[i+1] = ", G[i+1], "\n" ); + fi; + od; + if not done then + ## need to resort G + lts:=LMonsNP(G); + SortParallel(lts,G,LtNP); +## Print( "resorted lts and G:\n", lts, "\n", G, "\n" ); + fi; + od; + +## Print( "after SortParallel G and lts =:\n", G, "\n", lts, "\n" ); + GLOT:=GBNP.CreateOccurTreePTSLR(lts,GBNP.CalculatePGlts(lts),true); fi; + +## Print( "initial GLOT:\n", GLOT, "\n" ); + lans:=Length(lts); ind:=[1..lans]; @@ -665,6 +690,9 @@ local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT; RemoveSet(ind,i); j:=i+1; while j <= lans do + +## Print( "[i,j] = ", [i,j], "\n" ); + if #IsSubsetBlist(Gset[j],Gset[i]) and GBNP.Occur(G[i][1][1],G[j][1][1]) <> 0 # XXX can this occur be removed @@ -897,7 +925,9 @@ Grobner,function(arg) local tt,todo,G, funcs,KI,loop, withpair; else G:= GBNP.ReducePol(KI); fi; - + +## Print( "here is the resulting G\n", G, "\n" ); + # only call GBNP.CalculatePG after reduction funcs.pg:=GBNP.CalculatePG(G); @@ -1308,11 +1338,17 @@ end);; GBNP.StrongNormalForm2TS:=function(G,j,GLOT) local g,h,il,i1,l,dr,ga,tt,lth,iid; + +## Print( "in StrongNormalForm2TS G[j] = ", G[j], "\n" ); + h:=StructuralCopy(G[j]); iid := 1; while iid <= Length(h[1]) do lth:=h[1][iid]; il:=GBNP.LookUpOccurTreeAllLstPTSLR(lth,GLOT,true); + +## Print( "il = ", il, "\n" ); + il:=Filtered(il,x->x[1]<>j); while il<>[] do i1:=il[1]; diff --git a/lib/occurtree.gi b/lib/occurtree.gi index 1859bc7..6c05128 100644 --- a/lib/occurtree.gi +++ b/lib/occurtree.gi @@ -121,7 +121,10 @@ end; ### GBNP.CreateOccurTreePTSLR:=function(L,pg,left) - if (pg <> GBNP.GetOptions().pg) then + if (pg <> GBNP.GetOptions().pg) then + +Error("here"); + Info(InfoGBNP,2,"Warning: CreateOccurTreePTSLR: pg argument (",pg,") is not the same as pg option (",GBNP.GetOptions().pg,")\n"); fi; From 301a5a7cd8bd2aebb73a9bb25006b6f6914ea1c5 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 8 Sep 2023 15:15:01 +0100 Subject: [PATCH 02/13] added issue15.g and issue15.tst --- tst/issue15.g | 10 ++++++++++ tst/issue15.tst | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tst/issue15.g create mode 100644 tst/issue15.tst diff --git a/tst/issue15.g b/tst/issue15.g new file mode 100644 index 0000000..a6acc52 --- /dev/null +++ b/tst/issue15.g @@ -0,0 +1,10 @@ +LoadPackage("gbnp"); +SetInfoLevel( InfoGBNP, 2 ); +A:=FreeAssociativeAlgebraWithOne(Rationals,"a","b"); +a:=A.1; +b:=A.2; +rels := [ a^3, a^2*b, a*b^2+a^2, b*a^2, a^3+b^2+b*a, a*b^2+a*b*a, + b*a*b+b*a^2, b^2*a+b*a^2, b^3+b*a^2, a^2*b*a, a*b*a^2, b*a^2*b ]; +relsnp := List( rels, x-> GP2NP(x) ); +grobnp := Grobner(relsnp); +grob := List( grobnp, p -> NP2GP(p,A) ); diff --git a/tst/issue15.tst b/tst/issue15.tst new file mode 100644 index 0000000..a5a98df --- /dev/null +++ b/tst/issue15.tst @@ -0,0 +1,23 @@ +gap> START_TEST("GBNP issue 15"); +gap> +gap> LoadPackage("gbnp");; +gap> +gap> A:=FreeAssociativeAlgebraWithOne(Rationals,"a","b");; +gap> a:=A.1;; +gap> b:=A.2;; +gap> rels := [ a^3, a^2*b, a*b^2+a^2, b*a^2, a^3+b^2+b*a, +> a*b^2+a*b*a, b*a*b+b*a^2, b^2*a+b*a^2, b^3+b*a^2, +> a^2*b*a, a*b*a^2, b*a^2*b ];; +gap> Display(rels); +[ (1)*a^3, (1)*a^2*b, (1)*a^2+(1)*a*b^2, (1)*b*a^2, (1)*b*a+(1)*b^2+(1)*a^3, + (1)*a*b*a+(1)*a*b^2, (1)*b*a^2+(1)*b*a*b, (1)*b*a^2+(1)*b^2*a, + (1)*b*a^2+(1)*b^3, (1)*a^2*b*a, (1)*a*b*a^2, (1)*b*a^2*b ] +gap> relsnp := List( rels, x-> GP2NP(x) );; +gap> grobnp := Grobner(relsnp);; +gap> grob := List( grobnp, p -> NP2GP(p,A) );; +gap> Display(grob); +[ (1)*b^2+(1)*b*a, (1)*a^3, (1)*a^2*b, (1)*a*b*a+(-1)*a^2, (1)*b*a^2, + (1)*b*a*b+(1)*b*a^2 ] +gap> +gap> STOP_TEST("GBNP issue 15",10000); + From f71f623c3111bff88f6f3f22de0d67f7d108611a Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 8 Sep 2023 16:16:51 +0100 Subject: [PATCH 03/13] adjustments grobner.gi and occurtree.gi --- lib/grobner.gi | 8 +++----- lib/occurtree.gi | 3 --- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/grobner.gi b/lib/grobner.gi index b168059..f4a4728 100644 --- a/lib/grobner.gi +++ b/lib/grobner.gi @@ -629,7 +629,6 @@ end);; GBNP.ReducePol2:=function(arg) local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT,done,one; G:=arg[1]; - one:=One(G[1][2][1]); if Length(arg)>=2 then GLOT:=arg[2]; lts:=LMonsNP(G); @@ -662,9 +661,10 @@ local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT,done,one; for i in Reversed( [1..Length(lts)-1] ) do if ( lts[i] = lts[i+1] ) then done := false; -## Print( "G[i],G[i+1] = ", G[i], G[i+1], "\n" ); +Print( "G[i],G[i+1] = ", G[i], G[i+1], "\n" ); + one:=One(G[i][2][1]); G[i+1] := CleanNP(AddNP(G[i+1],G[i],one,-one)); -## Print( "new G[i+1] = ", G[i+1], "\n" ); +Print( "new G[i+1] = ", G[i+1], "\n" ); fi; od; if not done then @@ -918,7 +918,6 @@ Grobner,function(arg) local tt,todo,G, funcs,KI,loop, withpair; # - Compute internal NormalForm Info(InfoGBNP,1,"number of entered polynomials is ",Length(KI)); - if (withpair) then # no cleaning should be needed when continuing G:= ShallowCopy(KI); @@ -1053,7 +1052,6 @@ SGrobner,function(arg) local tt,todo,G,GLOT,funcs,KI,loop,withpair; else KI:=arg[1]; fi; - tt:=Runtime(); if Length(arg)>=2 and IsInt(arg[Length(arg)]) then diff --git a/lib/occurtree.gi b/lib/occurtree.gi index 6c05128..89c88e7 100644 --- a/lib/occurtree.gi +++ b/lib/occurtree.gi @@ -122,9 +122,6 @@ end; GBNP.CreateOccurTreePTSLR:=function(L,pg,left) if (pg <> GBNP.GetOptions().pg) then - -Error("here"); - Info(InfoGBNP,2,"Warning: CreateOccurTreePTSLR: pg argument (",pg,") is not the same as pg option (",GBNP.GetOptions().pg,")\n"); fi; From 04a4279b87ebb2ad9eb37bb2ca99c14145aea485 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Sat, 9 Sep 2023 14:23:43 +0100 Subject: [PATCH 04/13] commented out two print statements --- lib/grobner.gi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/grobner.gi b/lib/grobner.gi index f4a4728..272fd84 100644 --- a/lib/grobner.gi +++ b/lib/grobner.gi @@ -661,10 +661,10 @@ local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT,done,one; for i in Reversed( [1..Length(lts)-1] ) do if ( lts[i] = lts[i+1] ) then done := false; -Print( "G[i],G[i+1] = ", G[i], G[i+1], "\n" ); +## Print( "G[i],G[i+1] = ", G[i], G[i+1], "\n" ); one:=One(G[i][2][1]); G[i+1] := CleanNP(AddNP(G[i+1],G[i],one,-one)); -Print( "new G[i+1] = ", G[i+1], "\n" ); +## Print( "new G[i+1] = ", G[i+1], "\n" ); fi; od; if not done then From b9ba11f9f646f3ccdd9b955143191285aa8e6d11 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 4 Oct 2023 12:22:47 +0100 Subject: [PATCH 05/13] make new polynomial monic --- lib/grobner.gi | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/lib/grobner.gi b/lib/grobner.gi index 272fd84..40841e4 100644 --- a/lib/grobner.gi +++ b/lib/grobner.gi @@ -509,8 +509,8 @@ GBNP.StrongNormalForm2:=function(f,G,G2) i1:=GBNP.OccurInLst(lth,ltsG); i2:=GBNP.OccurInLst(lth,ltsG2); while i1[1]+i2[1]>0 do -# Print("starting while loop with in StrongNormalForm2 with\n "); -# Print(" i1[1]+i2[1] = ", i1[1]+i2[1]," and h="); PrintNP(h); +Print("starting while loop with in StrongNormalForm2 with\n "); +Print(" i1[1]+i2[1] = ", i1[1]+i2[1]," and h="); PrintNP(h); if i1[1]>0 then g:=G[i1[1]]; ga:=lth{[1..i1[2]-1]}; @@ -541,7 +541,7 @@ GBNP.StrongNormalForm2:=function(f,G,G2) od; iid := iid+1; od; -# Info(InfoGBNP,3, "computation time of the StrongNormalFormNP = ",Runtime()-tt); +Info(InfoGBNP,3, "computation time of the StrongNormalFormNP = ",Runtime()-tt); return(h); end;; @@ -627,7 +627,7 @@ end);; ### GBNP.ReducePol2:=function(arg) -local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT,done,one; +local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT,done,one,count; G:=arg[1]; if Length(arg)>=2 then GLOT:=arg[2]; @@ -650,6 +650,8 @@ local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT,done,one; SortParallel(lts,G,LtNP); GBNP.SortParallelLOT(temp,GLOT,LtNP); else +count:=0; +Print( "starting at count = 0\n" ); done := false; while not done do for i in [1..Length(G)] do @@ -661,27 +663,31 @@ local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT,done,one; for i in Reversed( [1..Length(lts)-1] ) do if ( lts[i] = lts[i+1] ) then done := false; -## Print( "G[i],G[i+1] = ", G[i], G[i+1], "\n" ); +count := count+1; +Print( "\ncount = ", count, ", i = ", i, "\n" ); +Print( "G[i],G[i+1] = ", G[i], G[i+1], "\n" ); one:=One(G[i][2][1]); G[i+1] := CleanNP(AddNP(G[i+1],G[i],one,-one)); -## Print( "new G[i+1] = ", G[i+1], "\n" ); + G[i+1] := MkMonicNP( G[i+1] ); +Print( "new G[i+1] = ", G[i+1], "\n" ); fi; od; if not done then ## need to resort G lts:=LMonsNP(G); SortParallel(lts,G,LtNP); -## Print( "resorted lts and G:\n", lts, "\n", G, "\n" ); +Print( "resorted lts and G:\n", lts, "\n", G, "\n" ); fi; + +if (count=5) then return 0; fi; + od; -## Print( "after SortParallel G and lts =:\n", G, "\n", lts, "\n" ); +Print( "after SortParallel G and lts =:\n", G, "\n", lts, "\n" ); GLOT:=GBNP.CreateOccurTreePTSLR(lts,GBNP.CalculatePGlts(lts),true); fi; -## Print( "initial GLOT:\n", GLOT, "\n" ); - lans:=Length(lts); ind:=[1..lans]; @@ -691,7 +697,7 @@ local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT,done,one; j:=i+1; while j <= lans do -## Print( "[i,j] = ", [i,j], "\n" ); +Print( "[i,j] = ", [i,j], "\n" ); if #IsSubsetBlist(Gset[j],Gset[i]) and GBNP.Occur(G[i][1][1],G[j][1][1]) <> 0 @@ -747,6 +753,9 @@ GBNP.ReducePol:=function(B) local ans; ans:=List(B,x -> MkMonicNP(CleanNP(x))); ans:=Filtered(ans, x -> x <> [[],[]]); + +Print( "in GBNP.ReducePol, ans = ", ans, "\n" ); + GBNP.ReducePol2(ans); return(ans); end;; From c8eac1432d84170d57449df11ac4ed91b35924d0 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 4 Oct 2023 17:22:14 +0100 Subject: [PATCH 06/13] small change in final answer for NMO Example 3 --- doc/examples/nmo/example03.g | 22 +++++++++++----------- doc/examples/nmo/example03.xml | 24 ++++++++++++------------ doc/examples/nmo/example04.g | 28 ++++++++++++++-------------- doc/examples/nmo/example04.xml | 28 ++++++++++++++-------------- doc/nmo.xml | 2 +- tst/nmo.tst | 2 +- 6 files changed, 53 insertions(+), 53 deletions(-) diff --git a/doc/examples/nmo/example03.g b/doc/examples/nmo/example03.g index 20db273..bead1e0 100644 --- a/doc/examples/nmo/example03.g +++ b/doc/examples/nmo/example03.g @@ -5,16 +5,16 @@ # left-lexicographic ordering implicitly assumed in {\GBNP}: LoadPackage("gbnp", false); -A := FreeAssociativeAlgebraWithOne(Rationals,"x","y","z");; -x := A.x;; y := A.y;; z := A.z;; id := One(A);; -polys := [ x^2 + y^2 + z^2 - id, x^2 + z^2 - y, x-z, - x*y-y*x, x*z-z*x, y*z-z*y];; -reps := GP2NPList(polys);; -gb := Grobner(reps);; -NP2GPList(gb,A); +A3 := FreeAssociativeAlgebraWithOne(Rationals,"x","y","z");; +x := A3.x;; y := A3.y;; z := A3.z;; id := One(A3);; +polys3 := [ x^2 + y^2 + z^2 - id, x^2 + z^2 - y, x-z, + x*y-y*x, x*z-z*x, y*z-z*y];; +reps3 := GP2NPList(polys3);; +gb3 := Grobner(reps3);; +NP2GPList(gb3,A3); -ml := NCMonomialLeftLexicographicOrdering(A,[3,2,1]); -PatchGBNP(ml); -gb := Grobner(reps);; -NP2GPList(gb,A); +ml3 := NCMonomialLeftLexicographicOrdering(A3,[3,2,1]); +PatchGBNP(ml3); +gb3 := Grobner(reps3);; +NP2GPList(gb3,A3); diff --git a/doc/examples/nmo/example03.xml b/doc/examples/nmo/example03.xml index a1e9787..77002e8 100644 --- a/doc/examples/nmo/example03.xml +++ b/doc/examples/nmo/example03.xml @@ -6,22 +6,22 @@ left-lexicographic ordering implicitly assumed in {\GBNP}: gap> LoadPackage("gbnp", false); true -gap> A := FreeAssociativeAlgebraWithOne(Rationals,"x","y","z");; -gap> x := A.x;; y := A.y;; z := A.z;; id := One(A);; -gap> polys := [ x^2 + y^2 + z^2 - id, x^2 + z^2 - y, x-z, -> x*y-y*x, x*z-z*x, y*z-z*y];; -gap> reps := GP2NPList(polys);; -gap> gb := Grobner(reps);; -gap> NP2GPList(gb,A); +gap> A3 := FreeAssociativeAlgebraWithOne(Rationals,"x","y","z");; +gap> x := A3.x;; y := A3.y;; z := A3.z;; id := One(A3);; +gap> polys3 := [ x^2 + y^2 + z^2 - id, x^2 + z^2 - y, x-z, +> x*y-y*x, x*z-z*x, y*z-z*y];; +gap> reps3 := GP2NPList(polys3);; +gap> gb3 := Grobner(reps3);; +gap> NP2GPList(gb3,A3); [ (1)*z+(-1)*x, (1)*x^2+(-1/2)*y, (1)*y*x+(-1)*x*y, - (1)*y^2+(2)*x^2+(-1)* ] + (1)*y^2+(1)*y+(-1)* ] -gap> ml := NCMonomialLeftLexicographicOrdering(A,[3,2,1]); +gap> ml3 := NCMonomialLeftLexicographicOrdering(A3,[3,2,1]); NCMonomialLeftLexicographicOrdering([ (1)*z, (1)*y, (1)*x ]) -gap> PatchGBNP(ml); +gap> PatchGBNP(ml3); LtNP patched. GtNP patched. -gap> gb := Grobner(reps);; -gap> NP2GPList(gb,A); +gap> gb3 := Grobner(reps3);; +gap> NP2GPList(gb3,A3); [ (1)*z^4+(1/2)*z^2+(-1/4)*, (1)*y+(-2)*z^2, (1)*x+(-1)*z ] diff --git a/doc/examples/nmo/example04.g b/doc/examples/nmo/example04.g index b222883..985303d 100644 --- a/doc/examples/nmo/example04.g +++ b/doc/examples/nmo/example04.g @@ -8,20 +8,20 @@ LoadPackage("gbnp", false); -A := FreeAssociativeAlgebraWithOne(Rationals,"a","b","c","d","e","f");; -a := A.a;; b := A.b;; c := A.c;; d := A.d;; e := A.e;; f := A.f;; +A4 := FreeAssociativeAlgebraWithOne(Rationals,"a","b","c","d","e","f");; +a := A4.a;; b := A4.b;; c := A4.c;; d := A4.d;; e := A4.e;; f := A4.f;; -polys := [ e*a, a^3 + f*a, a^9 + c*a^3, a^81 + c*a^9 + d*a^3, - a^27 + d*a^81 + e*a^9 + f*a^3, b + c*a^27 + e*a^81 + f*a^9, - c*b + d*a^27 + f*a^81, a + d*b + e*a^27, c*a + e*b + f*a^27, - d*a + f*b, b^3 - b, a*b - b*a, a*c - c*a, a*d - d*a, - a*e - e*a, a*f - f*a, b*c - c*b, b*d - d*b, b*e - e*b, - b*f - f*b, c*d - d*c, c*e - e*c, c*f - f*c, d*e - e*d, - d*f - f*d, e*f - f*e +polys4 := [ e*a, a^3 + f*a, a^9 + c*a^3, a^81 + c*a^9 + d*a^3, + a^27 + d*a^81 + e*a^9 + f*a^3, b + c*a^27 + e*a^81 + f*a^9, + c*b + d*a^27 + f*a^81, a + d*b + e*a^27, c*a + e*b + f*a^27, + d*a + f*b, b^3 - b, a*b - b*a, a*c - c*a, a*d - d*a, + a*e - e*a, a*f - f*a, b*c - c*b, b*d - d*b, b*e - e*b, + b*f - f*b, c*d - d*c, c*e - e*c, c*f - f*c, d*e - e*d, + d*f - f*d, e*f - f*e ];; -reps := GP2NPList(polys);; +reps4 := GP2NPList(polys4);; -ml := NCMonomialLeftLengthLexOrdering(A); -PatchGBNP(ml); -gb := Grobner(reps);; -NP2GPList(gb,A); +ml4 := NCMonomialLeftLengthLexOrdering(A4); +PatchGBNP(ml4); +gb4 := Grobner(reps4);; +NP2GPList(gb4,A4); diff --git a/doc/examples/nmo/example04.xml b/doc/examples/nmo/example04.xml index de46895..8d67834 100644 --- a/doc/examples/nmo/example04.xml +++ b/doc/examples/nmo/example04.xml @@ -9,26 +9,26 @@ the following example shows. It was taken from the book page 339 of gap> LoadPackage("gbnp", false); true -gap> A := FreeAssociativeAlgebraWithOne(Rationals,"a","b","c","d","e","f");; -gap> a := A.a;; b := A.b;; c := A.c;; d := A.d;; e := A.e;; f := A.f;; +gap> A4 := FreeAssociativeAlgebraWithOne(Rationals,"a","b","c","d","e","f");; +gap> a := A4.a;; b := A4.b;; c := A4.c;; d := A4.d;; e := A4.e;; f := A4.f;; -gap> polys := [ e*a, a^3 + f*a, a^9 + c*a^3, a^81 + c*a^9 + d*a^3, -> a^27 + d*a^81 + e*a^9 + f*a^3, b + c*a^27 + e*a^81 + f*a^9, -> c*b + d*a^27 + f*a^81, a + d*b + e*a^27, c*a + e*b + f*a^27, -> d*a + f*b, b^3 - b, a*b - b*a, a*c - c*a, a*d - d*a, -> a*e - e*a, a*f - f*a, b*c - c*b, b*d - d*b, b*e - e*b, -> b*f - f*b, c*d - d*c, c*e - e*c, c*f - f*c, d*e - e*d, -> d*f - f*d, e*f - f*e +gap> polys4 := [ e*a, a^3 + f*a, a^9 + c*a^3, a^81 + c*a^9 + d*a^3, +> a^27 + d*a^81 + e*a^9 + f*a^3, b + c*a^27 + e*a^81 + f*a^9, +> c*b + d*a^27 + f*a^81, a + d*b + e*a^27, c*a + e*b + f*a^27, +> d*a + f*b, b^3 - b, a*b - b*a, a*c - c*a, a*d - d*a, +> a*e - e*a, a*f - f*a, b*c - c*b, b*d - d*b, b*e - e*b, +> b*f - f*b, c*d - d*c, c*e - e*c, c*f - f*c, d*e - e*d, +> d*f - f*d, e*f - f*e > ];; -gap> reps := GP2NPList(polys);; +gap> reps4 := GP2NPList(polys4);; -gap> ml := NCMonomialLeftLengthLexOrdering(A); +gap> ml4 := NCMonomialLeftLengthLexOrdering(A4); NCMonomialLeftLengthLexicographicOrdering([ (1)*a, (1)*b, (1)*c, (1)*d, (1)*e,\ (1)*f ]) -gap> PatchGBNP(ml); +gap> PatchGBNP(ml4); LtNP patched. GtNP patched. -gap> gb := Grobner(reps);; -gap> NP2GPList(gb,A); +gap> gb4 := Grobner(reps4);; +gap> NP2GPList(gb4,A4); [ (1)*a, (1)*b, (1)*d*c+(-1)*c*d, (1)*e*c+(-1)*c*e, (1)*e*d+(-1)*d*e, (1)*f*c+(-1)*c*f, (1)*f*d+(-1)*d*f, (1)*f*e+(-1)*e*f ] diff --git a/doc/nmo.xml b/doc/nmo.xml index 4001d8d..9799ec1 100644 --- a/doc/nmo.xml +++ b/doc/nmo.xml @@ -347,7 +347,7 @@ gap> reps3 := GP2NPList( polys3 );; gap> gb3 := Grobner( reps3 );; gap> NP2GPList( gb3, A3 ); [ (1)*z+(-1)*x, (1)*x^2+(-1/2)*y, (1)*y*x+(-1)*x*y, - (1)*y^2+(2)*x^2+(-1)*<identity ...> ] + (1)*y^2+(1)*y+(-1)*<identity ...> ] The example, as presented in the book, uses a left-lexicographic ordering diff --git a/tst/nmo.tst b/tst/nmo.tst index 1c1260e..a1d46d4 100644 --- a/tst/nmo.tst +++ b/tst/nmo.tst @@ -162,7 +162,7 @@ gap> reps3 := GP2NPList( polys3 );; gap> gb3 := Grobner( reps3 );; gap> NP2GPList( gb3, A3 ); [ (1)*z+(-1)*x, (1)*x^2+(-1/2)*y, (1)*y*x+(-1)*x*y, - (1)*y^2+(2)*x^2+(-1)* ] + (1)*y^2+(1)*y+(-1)* ] gap> gap> # The example, as presented in the book, uses a left-lexicographic gap> # ordering with z < y < x. We create the ordering in NMO, From 8084a34de08ccbaca3b2a876eab2cc42d9bdec76 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 4 Oct 2023 17:22:41 +0100 Subject: [PATCH 07/13] temporary print statements --- lib/grobner.gi | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/lib/grobner.gi b/lib/grobner.gi index 40841e4..894c8c0 100644 --- a/lib/grobner.gi +++ b/lib/grobner.gi @@ -509,8 +509,8 @@ GBNP.StrongNormalForm2:=function(f,G,G2) i1:=GBNP.OccurInLst(lth,ltsG); i2:=GBNP.OccurInLst(lth,ltsG2); while i1[1]+i2[1]>0 do -Print("starting while loop with in StrongNormalForm2 with\n "); -Print(" i1[1]+i2[1] = ", i1[1]+i2[1]," and h="); PrintNP(h); +# Print("starting while loop with in StrongNormalForm2 with\n "); +# Print(" i1[1]+i2[1] = ", i1[1]+i2[1]," and h="); PrintNP(h); if i1[1]>0 then g:=G[i1[1]]; ga:=lth{[1..i1[2]-1]}; @@ -651,24 +651,25 @@ local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT,done,one,count; GBNP.SortParallelLOT(temp,GLOT,LtNP); else count:=0; -Print( "starting at count = 0\n" ); done := false; while not done do +count:=count+1; +Print( "\ncount = ", count, "\n" ); for i in [1..Length(G)] do G[i]:=GBNP.ReduceCancellation(G[i]); od; lts:=LMonsNP(G); SortParallel(lts,G,LtNP); +if (count=1) then +Print("after initial sorting, G = \n", G ); +fi; done := true; for i in Reversed( [1..Length(lts)-1] ) do if ( lts[i] = lts[i+1] ) then - done := false; -count := count+1; -Print( "\ncount = ", count, ", i = ", i, "\n" ); + done := false; Print( "G[i],G[i+1] = ", G[i], G[i+1], "\n" ); one:=One(G[i][2][1]); - G[i+1] := CleanNP(AddNP(G[i+1],G[i],one,-one)); - G[i+1] := MkMonicNP( G[i+1] ); + G[i+1] := MkMonicNP(CleanNP(AddNP(G[i+1],G[i],one,-one))); Print( "new G[i+1] = ", G[i+1], "\n" ); fi; od; @@ -678,9 +679,6 @@ Print( "new G[i+1] = ", G[i+1], "\n" ); SortParallel(lts,G,LtNP); Print( "resorted lts and G:\n", lts, "\n", G, "\n" ); fi; - -if (count=5) then return 0; fi; - od; Print( "after SortParallel G and lts =:\n", G, "\n", lts, "\n" ); @@ -753,9 +751,6 @@ GBNP.ReducePol:=function(B) local ans; ans:=List(B,x -> MkMonicNP(CleanNP(x))); ans:=Filtered(ans, x -> x <> [[],[]]); - -Print( "in GBNP.ReducePol, ans = ", ans, "\n" ); - GBNP.ReducePol2(ans); return(ans); end;; From b5dda36e2e9dcbd795c906a676fc359d9c91a1a6 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 5 Oct 2023 11:54:23 +0100 Subject: [PATCH 08/13] temporary version of grobner.gi --- lib/grobner.gi | 79 +++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/lib/grobner.gi b/lib/grobner.gi index 894c8c0..e5ec0fe 100644 --- a/lib/grobner.gi +++ b/lib/grobner.gi @@ -588,8 +588,8 @@ end;; ### -InstallGlobalFunction( -StrongNormalFormNP,function(f,G) local ih, fm, Gl, lts, lcf, hlp; +InstallGlobalFunction( StrongNormalFormNP, function(f,G) + local ih, fm, Gl, lts, lcf, hlp; fm := CleanNP(f); if fm = [[],[]] then return fm; fi; lcf := fm[2][1]; @@ -661,22 +661,24 @@ Print( "\ncount = ", count, "\n" ); lts:=LMonsNP(G); SortParallel(lts,G,LtNP); if (count=1) then -Print("after initial sorting, G = \n", G ); +Print("after initial sorting, G has length ", Length(G), "\n", G, "\n" ); fi; done := true; for i in Reversed( [1..Length(lts)-1] ) do if ( lts[i] = lts[i+1] ) then done := false; -Print( "G[i],G[i+1] = ", G[i], G[i+1], "\n" ); +## Print( "G[i],G[i+1] = ", G[i], G[i+1], "\n" ); one:=One(G[i][2][1]); G[i+1] := MkMonicNP(CleanNP(AddNP(G[i+1],G[i],one,-one))); -Print( "new G[i+1] = ", G[i+1], "\n" ); +## Print( "new G[i+1] = ", G[i+1], "\n" ); fi; od; if not done then ## need to resort G + G := Filtered( G, L -> L <> [ [ ], [ ] ] ); lts:=LMonsNP(G); SortParallel(lts,G,LtNP); +Print( "G now has length ", Length(G), "\n" ); Print( "resorted lts and G:\n", lts, "\n", G, "\n" ); fi; od; @@ -685,23 +687,22 @@ Print( "after SortParallel G and lts =:\n", G, "\n", lts, "\n" ); GLOT:=GBNP.CreateOccurTreePTSLR(lts,GBNP.CalculatePGlts(lts),true); fi; - lans:=Length(lts); ind:=[1..lans]; - while ind <> [] do i:=ind[1]; RemoveSet(ind,i); j:=i+1; while j <= lans do -Print( "[i,j] = ", [i,j], "\n" ); +## Print( "[i,j], G[3] = ", [i,j], G[3], "\n" ); if #IsSubsetBlist(Gset[j],Gset[i]) and GBNP.Occur(G[i][1][1],G[j][1][1]) <> 0 # XXX can this occur be removed then new:=GBNP.StrongNormalForm2TS(G,j,GLOT); +Print("new = ", new, " at [i,j] = ", [i,j], "\n" ); if new = [[],[]] then GBNP.RemoveMonFromTreePTSLR(G[j][1][1],j,GLOT,true); RemoveElmList(G,j); @@ -729,7 +730,7 @@ Print( "[i,j] = ", [i,j], "\n" ); fi; od; od; - +Print( "in ReducePol2 at end of [i,j] loop, G[3] = ", G[3], "\n" ); return GLOT; end;; @@ -752,6 +753,9 @@ GBNP.ReducePol:=function(B) local ans; ans:=List(B,x -> MkMonicNP(CleanNP(x))); ans:=Filtered(ans, x -> x <> [[],[]]); GBNP.ReducePol2(ans); + +Print( "in ReducePol, ans[3] = ", ans[3], "\n" ); + return(ans); end;; @@ -889,8 +893,8 @@ end;; ### #Grobner is used in:# ### -InstallGlobalFunction( -Grobner,function(arg) local tt,todo,G, funcs,KI,loop, withpair; +InstallGlobalFunction( Grobner, function(arg) + local tt,todo,G, funcs,KI,loop, withpair; # set the default options funcs:=ShallowCopy(GBNP.GrobnerLoopRec); @@ -929,7 +933,7 @@ Grobner,function(arg) local tt,todo,G, funcs,KI,loop, withpair; G:= GBNP.ReducePol(KI); fi; -## Print( "here is the resulting G\n", G, "\n" ); +Print( "here is the resulting G\n", G, "\n" ); # only call GBNP.CalculatePG after reduction funcs.pg:=GBNP.CalculatePG(G); @@ -1045,8 +1049,8 @@ end); ### #SGrobner is used in: SGrobnerModule# ### -InstallGlobalFunction( -SGrobner,function(arg) local tt,todo,G,GLOT,funcs,KI,loop,withpair; +InstallGlobalFunction( SGrobner, function(arg) + local tt,todo,G,GLOT,funcs,KI,loop,withpair; # set the default options funcs:=ShallowCopy(GBNP.SGrobnerLoopRec); @@ -1081,9 +1085,14 @@ SGrobner,function(arg) local tt,todo,G,GLOT,funcs,KI,loop,withpair; # no cleaning should be needed when continuing G:= ShallowCopy(KI); else +Print( "in SGrobner KI[3] = ", KI[3], "\n" ); G:= GBNP.ReducePol(KI); +Print( "in SGrobner G[3] = ", G[3], "\n" ); fi; +Print( "after call of GBNP.ReducePol: \n" ); +Print( "G[3] = ", G[3], "\n" ); + # only call GBNP.CalculatePG after reduction funcs.pg:=GBNP.CalculatePG(G); @@ -1195,8 +1204,8 @@ end); ### #BaseQA is used in:# ### -InstallGlobalFunction( -BaseQA , function(G,t,maxno) local ans, hlst, i, h, GF,one; +InstallGlobalFunction( BaseQA, function(G,t,maxno) + local ans, hlst, i, h, GF,one; # estimate the number of generators if t = 0 then t := NumAlgGensNPList(G); @@ -1260,8 +1269,8 @@ end);; ### #DimQA is used in:# ### -InstallGlobalFunction( -DimQA , function(G,n) local s,t0; +InstallGlobalFunction( DimQA, function(G,n) + local s,t0; if n = 0 then n := NumAlgGensNPList(G); @@ -1307,8 +1316,7 @@ end);; ### #MulQA is used in: MatrixQA# ### -InstallGlobalFunction( -MulQA , function(p1,p2,G) +InstallGlobalFunction( MulQA, function(p1,p2,G) return StrongNormalFormNP(MulNP(p1,p2),G); end);; @@ -1674,8 +1682,7 @@ end;; ### #IsStrongGrobnerBasis uses: GBNP.IsGrobnerBasisTest# ### #IsStrongGrobnerBasis used in:# -InstallGlobalFunction( -IsStrongGrobnerBasis,function(G) +InstallGlobalFunction( IsStrongGrobnerBasis, function(G) return GBNP.IsGrobnerBasisTest(G,true); end); @@ -1710,8 +1717,7 @@ end); ### #IsGrobnerBasis uses: GBNP.IsGrobnerBasisTest# ### #IsGrobnerBasis used in:# -InstallGlobalFunction( -IsGrobnerBasis,function(G) +InstallGlobalFunction( IsGrobnerBasis, function(G) return GBNP.IsGrobnerBasisTest(G,false); end); @@ -1892,8 +1898,7 @@ end; ### - true if it can be proved that (G,D) is a Gröbner pair. ### -InstallGlobalFunction( -IsGrobnerPair,function(G,D) +InstallGlobalFunction( IsGrobnerPair, function(G,D) local pol, # NP polynomial, counter pol2, # NP polynomial GLOT, # Left Occur Tree of G @@ -2044,8 +2049,7 @@ end; ### - A record containing the new G, todo ### -InstallGlobalFunction( -MakeGrobnerPair,function(G,D) +InstallGlobalFunction( MakeGrobnerPair, function(G,D) local pol, # NP polynomial, counter pol2, # NP polynomial GLOT, # Left Occur Tree of G @@ -2188,8 +2192,7 @@ end); ### #StrongNormalFormNPM is used in: MulQM# ### -InstallGlobalFunction( -StrongNormalFormNPM,function(v,GR) +InstallGlobalFunction( StrongNormalFormNPM, function(v,GR) if v=[[],[]] then return v; else @@ -2268,8 +2271,8 @@ end); ### #SGrobnerModule is used in:# ### -InstallGlobalFunction( -SGrobnerModule,function(KI_p,KI_ts) local tt,todo,G,GB_ts,temp; +InstallGlobalFunction( SGrobnerModule, function(KI_p,KI_ts) + local tt,todo,G,GB_ts,temp; # XXX check for module generators G:=Filtered(KI_p,x->x<>[[],[]]); @@ -2349,8 +2352,7 @@ end);; ### #MulQM is used in: MatrixQA# ### -InstallGlobalFunction( -MulQM , function(p1,p2,GBR) +InstallGlobalFunction( MulQM, function(p1,p2,GBR) if (Length(p2[1])=0) then # the second argument is zero @@ -2432,9 +2434,8 @@ end);; ### #BaseQM is used in:# ### -InstallGlobalFunction( -BaseQM,function(GBR,t,mt,maxno) -local ans, hlst, i, h, one, mn; +InstallGlobalFunction( BaseQM, function(GBR,t,mt,maxno) + local ans, hlst, i, h, one, mn; if t = 0 then t := Maximum(NumAlgGensNPList(GBR.ts), NumAlgGensNPList(GBR.p)); fi; @@ -2522,8 +2523,8 @@ end);; ### #DimQM is used in:# ### -InstallGlobalFunction( -DimQM , function(GBR,n,mt) local s,t0, mn; +InstallGlobalFunction( DimQM, function(GBR,n,mt) + local s,t0, mn; t0 := Runtime(); if n = 0 then n := Maximum(NumAlgGensNPList(GBR.ts), NumAlgGensNPList(GBR.p)); From 097d7d57442d890281d01bb76020b73cbf6af90a Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 5 Oct 2023 17:56:50 +0100 Subject: [PATCH 09/13] temporary changes to grobner.gi --- lib/grobner.gi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/grobner.gi b/lib/grobner.gi index e5ec0fe..0dc83b0 100644 --- a/lib/grobner.gi +++ b/lib/grobner.gi @@ -689,6 +689,7 @@ Print( "after SortParallel G and lts =:\n", G, "\n", lts, "\n" ); fi; lans:=Length(lts); ind:=[1..lans]; +Print( "ind = ", ind, "\n" ); while ind <> [] do i:=ind[1]; RemoveSet(ind,i); @@ -753,8 +754,7 @@ GBNP.ReducePol:=function(B) local ans; ans:=List(B,x -> MkMonicNP(CleanNP(x))); ans:=Filtered(ans, x -> x <> [[],[]]); GBNP.ReducePol2(ans); - -Print( "in ReducePol, ans[3] = ", ans[3], "\n" ); +Print( "in ReducePol after ReducePol2, ans[3] = ", ans[3], "\n" ); return(ans); end;; From c7b24d6352907944bb0c560eb50054b2223f3943 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Mon, 9 Oct 2023 09:10:25 +0100 Subject: [PATCH 10/13] more temporary changes to grobner.gi --- lib/grobner.gi | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/grobner.gi b/lib/grobner.gi index 0dc83b0..d4a7684 100644 --- a/lib/grobner.gi +++ b/lib/grobner.gi @@ -686,25 +686,23 @@ Print( "resorted lts and G:\n", lts, "\n", G, "\n" ); Print( "after SortParallel G and lts =:\n", G, "\n", lts, "\n" ); GLOT:=GBNP.CreateOccurTreePTSLR(lts,GBNP.CalculatePGlts(lts),true); + fi; lans:=Length(lts); ind:=[1..lans]; -Print( "ind = ", ind, "\n" ); + while ind <> [] do i:=ind[1]; RemoveSet(ind,i); j:=i+1; while j <= lans do - -## Print( "[i,j], G[3] = ", [i,j], G[3], "\n" ); - if #IsSubsetBlist(Gset[j],Gset[i]) and GBNP.Occur(G[i][1][1],G[j][1][1]) <> 0 # XXX can this occur be removed then new:=GBNP.StrongNormalForm2TS(G,j,GLOT); -Print("new = ", new, " at [i,j] = ", [i,j], "\n" ); if new = [[],[]] then +Print( "new at [i,j] = ", [i,j], "\n" ); GBNP.RemoveMonFromTreePTSLR(G[j][1][1],j,GLOT,true); RemoveElmList(G,j); RemoveSet(ind,lans); @@ -731,7 +729,8 @@ Print("new = ", new, " at [i,j] = ", [i,j], "\n" ); fi; od; od; -Print( "in ReducePol2 at end of [i,j] loop, G[3] = ", G[3], "\n" ); +Print( "in ReducePol2 at end of [i,j] loop:\n" ); +Print( "G has length ", Length(G), ", G[3] = ", G[3], "\n" ); return GLOT; end;; @@ -743,7 +742,7 @@ end;; ### G - list of non-commutative polynomials ### ### Returns: -### G - Cleaned, reduced, ordered list of non trivial S-polynomials. +### G - Cleaned, reduced, ordered list of non-trivial S-polynomials. ### ### #GBNP.ReducePol uses: CleanNP GBNP.ReducePol2 MkMonicNP# ### #GBNP.ReducePol is used in: GBNP.SGrobnerTrunc GBNP.SGrobnerTruncLevel Grobner SGrobner# @@ -754,8 +753,8 @@ GBNP.ReducePol:=function(B) local ans; ans:=List(B,x -> MkMonicNP(CleanNP(x))); ans:=Filtered(ans, x -> x <> [[],[]]); GBNP.ReducePol2(ans); -Print( "in ReducePol after ReducePol2, ans[3] = ", ans[3], "\n" ); - +Print( "in ReducePol after ReducePol2:\n" ); +Print("ans has length ", Length(ans), ", ans[3] = ", ans[3], "\n" ); return(ans); end;; @@ -1085,13 +1084,12 @@ InstallGlobalFunction( SGrobner, function(arg) # no cleaning should be needed when continuing G:= ShallowCopy(KI); else -Print( "in SGrobner KI[3] = ", KI[3], "\n" ); G:= GBNP.ReducePol(KI); -Print( "in SGrobner G[3] = ", G[3], "\n" ); +Print( "in SGrobner G has length ", Length(G), ", G[3] = ", G[3], "\n" ); fi; Print( "after call of GBNP.ReducePol: \n" ); -Print( "G[3] = ", G[3], "\n" ); +Print( "G has length ", Length(G), ", G[3] = ", G[3], "\n" ); # only call GBNP.CalculatePG after reduction funcs.pg:=GBNP.CalculatePG(G); From b33316e64d7eea1d7ca8c09a585ecfb790301109 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Mon, 9 Oct 2023 21:30:22 +0100 Subject: [PATCH 11/13] test23 passes at last --- lib/grobner.gi | 1829 +++++++++++++++++++++++------------------------- 1 file changed, 890 insertions(+), 939 deletions(-) diff --git a/lib/grobner.gi b/lib/grobner.gi index d4a7684..825aebf 100644 --- a/lib/grobner.gi +++ b/lib/grobner.gi @@ -70,26 +70,28 @@ ### returns the start of u in v if there is such a t ### ### Arguments: -### u,v - two monomials +### u,v - two monomials ### ### Returns: -### i - position in v where the monomial u starts -### 0 - the monomial u is not contained in v +### i - position in v where the monomial u starts +### 0 - the monomial u is not contained in v ### ### #GBNP.RightOccur uses: LtNP# ### #GBNP.RightOccur is used in: GBNP.RightOccurInLst# ### GBNP.RightOccur:=function(u,v) local lu,lv; - if u = v then return(1); fi; - if LtNP(u,v) then + if u = v then + return(1); + fi; + if LtNP(u,v) then lu:=Length(u); - lv:=Length(v); - if v{[lv-lu+1..lv]}=u then - return(lv-lu+1); + lv:=Length(v); + if v{[lv-lu+1..lv]}=u then + return(lv-lu+1); fi; - fi; - return(0); + fi; + return(0); end;; ################## @@ -100,25 +102,28 @@ end;; ### returns 1 if there is such a t ### ### Arguments: -### u,v - two monomials +### u,v - two monomials ### ### Returns: -### 1 - if u occurs at the left of v -### 0 - the monomial u is not contained in v +### 1 - if u occurs at the left of v +### 0 - the monomial u is not contained in v ### ### #GBNP.LeftOccur uses: LtNP# ### #GBNP.LeftOccur is used in: GBNP.LeftObs GBNP.RightObs# ### -GBNP.LeftOccur:=function(u,v) local lu; - if u = v then return(1); fi; - if LtNP(u,v) then +GBNP.LeftOccur:=function(u,v) + local lu; + if u = v then + return(1); + fi; + if LtNP(u,v) then lu:=Length(u); - if v{[1..lu]}=u then - return(1); + if v{[1..lu]}=u then + return(1); fi; - fi; - return(0); + fi; + return(0); end;; ################## @@ -129,54 +134,56 @@ end;; ### returns 1 if u = [], the empty word ### ### Arguments: -### u,v - two monomials +### u,v - two monomials ### ### Returns: -### i - position in v where the monomial u starts -### 0 - the monomial u is not contained in v +### i - position in v where the monomial u starts +### 0 - the monomial u is not contained in v ### ### #GBNP.Occur uses: LtNP# ### #GBNP.Occur is used in: FinCheckQA GBNP.CentralT GBNP.CentralTrace GBNP.OccurInLst GBNP.ReducePol2 GBNP.ReducePolTrace2 GBNP.SGrobnerLoops# ### -GBNP.Occur:=function(u,v) local i,lu,p; - if u = v then return(1); fi; - if LtNP(u,v) then +GBNP.Occur:=function(u,v) + local i,lu,p; + if u = v then + return(1); + fi; + if LtNP(u,v) then lu:=Length(u); for i in [1..Length(v)-lu+1] do - if v{[i..lu+i-1]}=u then - return(i); - fi; + if v{[i..lu+i-1]}=u then + return(i); + fi; od; -# p:=PositionSublist(v,u); -# if p<>fail then -# return p; -# fi; - fi; - return(0); +# p:=PositionSublist(v,u); +# if p<>fail then +# return p; +# fi; + fi; + return(0); end; - - ################## ### GBNP.RightOccurInLst ### - Finding the first index i such that the monomial R[i] ### in the list R is a solution to t.R[i]=u. ### ### Arguments: -### u - monomial -### Rlst - list of monomials +### u - monomial +### Rlst - list of monomials ### ### Returns: -### [i,j] - the monomial R[i] is the first monomial in R dividing u and -### is thus contained in u, starting at position j -### [0,0] - no monomial of R divides the monomial u +### [i,j] - the monomial R[i] is the first monomial in R dividing u and +### is thus contained in u, starting at position j +### [0,0] - no monomial of R divides the monomial u ### ### #GBNP.RightOccurInLst uses: GBNP.RightOccur# ### #GBNP.RightOccurInLst is used in:# ### -GBNP.RightOccurInLst:=function(u,Rlst) local i,j,lr; +GBNP.RightOccurInLst:=function(u,Rlst) + local i,j,lr; i := 0; lr := Length(Rlst); while i < lr do @@ -193,13 +200,13 @@ end;; ### in the list R divides the given monomial u. ### ### Arguments: -### u - monomial -### Rlst - list of monomials +### u - monomial +### Rlst - list of monomials ### ### Returns: -### [i,j] - the monomial R[i] is the first monomial in R dividing u and -### is thus contained in u, starting at position j -### [0,0] - no monomial of R divides the monomial u +### [i,j] - the monomial R[i] is the first monomial in R dividing u and +### is thus contained in u, starting at position j +### [0,0] - no monomial of R divides the monomial u ### ### #GBNP.OccurInLst uses: GBNP.Occur# ### #GBNP.OccurInLst is used in: GBNP.MakeArgumentLevel GBNP.NondivMonsByLevel GBNP.NondivMonsPTS GBNP.NondivMonsPTSenum GBNP.NormalForm2 GBNP.StrongNormalForm2 GBNP.StrongNormalFormTrace2# @@ -212,13 +219,13 @@ GBNP.OccurInLst:=function(u,Rlst) local i,j,lr; i := i+1; j:= GBNP.Occur(Rlst[i],u); #j:= PositionSublist(u,Rlst[i]); - if j>0 then return([i,j]); fi; + if j>0 then + return([i,j]); + fi; #if j<>fail then return([i,j]); fi; od; return([0,0]); -end;; - - +end;; ################# ### GBNP.SelfObs @@ -228,25 +235,26 @@ end;; ### Only the one with the smallest a and b is needed, see ****. ### ### Arguments: -### j - index of the monomial for which we search a self-obs. -### R - list of monomials (in the application: leading terms) +### j - index of the monomial for which we search a self-obs. +### R - list of monomials (in the application: leading terms) ### ### Returns: -### [[[],j,b,a,j,[]]] - the self obstruction with smallest a and b -### [] - if R[j] has no self obstructions +### [[[],j,b,a,j,[]]] - the self obstruction with smallest a and b +### [] - if R[j] has no self obstructions ### ####Note: ***same form as left obs*** ### #GBNP.SelfObs uses:# ### #GBNP.SelfObs is used in: GBNP.ObsTrace GBNP.ObsTrunc# ### -GBNP.SelfObs:=function(j,R) local i,u,lu; - u:=R[j]; +GBNP.SelfObs:=function(j,R) + local i,u,lu; + u:=R[j]; lu:=Length(u); for i in [1..lu-1] do - if u{[1..lu-i]}=u{[i+1..lu]} then - return([[[],j,u{[lu-i+1..lu]},u{[1..i]},j,[]]]); - fi; + if u{[1..lu-i]}=u{[i+1..lu]} then + return([[[],j,u{[lu-i+1..lu]},u{[1..i]},j,[]]]); + fi; od; return([]); end;; @@ -260,43 +268,46 @@ end;; ### self obstruction of R[j] (if present) is taken into account. ### ### Arguments: -### j - index of the monomial for which we search left-obs. -### R - set of leading terms (monomials) -### sob - 'smallest' self-obstruction of R[j] +### j - index of the monomial for which we search left-obs. +### R - set of leading terms (monomials) +### sob - 'smallest' self-obstruction of R[j] ### ### Returns: -### ans - List of found left-obstructions +### ans - List of found left-obstructions ### ### #GBNP.LeftObs uses: GBNP.LeftOccur# ### #GBNP.LeftObs is used in: GBNP.ObsTrace GBNP.ObsTrunc# ### -GBNP.LeftObs:=function(j,R,sob) local i,h,k,u,v,dr,ga,lu,lv,mi,ans,eli,flag; +GBNP.LeftObs:=function(j,R,sob) + local i,h,k,u,v,dr,ga,lu,lv,mi,ans,eli,flag; ans:=sob; u:=R[j]; lu:=Length(u); for i in [1..j-1] do - v:=R[i]; - lv:=Length(v); - mi:=Minimum([lu,lv]); - for k in [1..mi-1] do - if u{[lu-k+1..lu]}=v{[1..k]} then - ga:=u{[1..lu-k]}; - dr:=v{[k+1..lv]}; - flag:=true; - eli:=[]; - for h in ans do - if GBNP.LeftOccur(h[3],dr)=1 then - flag:=false; - break; # saves time - jwk - elif GBNP.LeftOccur(dr,h[3])=1 then - Add(eli,h); - fi; - od; - ans:=Difference(ans,eli); - if flag then Add(ans,[[],j,dr,ga,i,[]]); fi; - fi; - od; + v:=R[i]; + lv:=Length(v); + mi:=Minimum([lu,lv]); + for k in [1..mi-1] do + if u{[lu-k+1..lu]}=v{[1..k]} then + ga:=u{[1..lu-k]}; + dr:=v{[k+1..lv]}; + flag:=true; + eli:=[]; + for h in ans do + if GBNP.LeftOccur(h[3],dr)=1 then + flag:=false; + break; # saves time - jwk + elif GBNP.LeftOccur(dr,h[3])=1 then + Add(eli,h); + fi; + od; + ans:=Difference(ans,eli); + if flag then + Add(ans,[[],j,dr,ga,i,[]]); + fi; + fi; + od; od; return(ans); end;; @@ -311,52 +322,54 @@ end;; ### into account (if it exists). ### ### Arguments: -### j - index of the monomial for which we search the right +### j - index of the monomial for which we search the right ### obstructions -### R - list of monomials (leading terms) -### sob - 'smallest' self-obstruction of R[j] +### R - list of monomials (leading terms) +### sob - 'smallest' self-obstruction of R[j] ### ### Returns: -### ans - List of found right-obstructions (not containing sob) +### ans - List of found right-obstructions (not containing sob) ### ### #GBNP.RightObs uses: GBNP.LeftOccur# ### #GBNP.RightObs is used in: GBNP.ObsTrace GBNP.ObsTrunc# ### -GBNP.RightObs:=function(j,R,sob) local i,h,k,u,v,dr,ga,lu,lv,mi,eli,flag, sobr, ans; +GBNP.RightObs:=function(j,R,sob) + local i,h,k,u,v,dr,ga,lu,lv,mi,eli,flag, sobr, ans; if sob<>[] then - sobr := [sob[1][4],sob[1][5],sob[1][6],sob[1][1],sob[1][2],sob[1][3]]; - ans:=[sobr]; + sobr := [sob[1][4],sob[1][5],sob[1][6], + sob[1][1],sob[1][2],sob[1][3]]; + ans:=[sobr]; else - ans:=[]; - sobr:=[]; + ans:=[]; + sobr:=[]; fi; u:=R[j]; lu:=Length(u); for i in [1..j-1] do - v:=R[i]; - lv:=Length(v); - mi:=Minimum([lu,lv]); - for k in [1..mi-1] do - if v{[lv-k+1..lv]}=u{[1..k]} then - ga:=v{[1..lv-k]}; - dr:=u{[k+1..lu]}; - flag:=true; - eli:=[]; - for h in ans do - if GBNP.LeftOccur(Reversed(h[1]),Reversed(ga))=1 - then - flag:=false; - break; # saves time - jwk - elif GBNP.LeftOccur(Reversed(ga),Reversed(h[1]))=1 - then - Append(eli,h); - fi; - od; - ans:=Difference(ans,eli); - if flag then Add(ans,[ga,j,[],[],i,dr]); fi; - fi; - od; + v:=R[i]; + lv:=Length(v); + mi:=Minimum([lu,lv]); + for k in [1..mi-1] do + if v{[lv-k+1..lv]}=u{[1..k]} then + ga:=v{[1..lv-k]}; + dr:=u{[k+1..lu]}; + flag:=true; + eli:=[]; + for h in ans do + if GBNP.LeftOccur(Reversed(h[1]),Reversed(ga))=1 then + flag:=false; + break; # saves time - jwk + elif GBNP.LeftOccur(Reversed(ga),Reversed(h[1]))=1 then + Append(eli,h); + fi; + od; + ans:=Difference(ans,eli); + if flag then + Add(ans,[ga,j,[],[],i,dr]); + fi; + fi; + od; od; return(Difference(ans,sobr)); end;; @@ -367,11 +380,11 @@ end;; ### Output is a cleaned polynomial ### ### Arguments: -### l - an obstruction -### G - list of non-commutative polynomials +### l - an obstruction +### G - list of non-commutative polynomials ### ### Returns: -### pol - cleaned S-polynomial in the basis G w.r.t. the obstruction l +### pol - cleaned S-polynomial in the basis G w.r.t. the obstruction l ### ### #GBNP.Spoly uses: AddNP BimulNP# ### #GBNP.Spoly is used in: GBNP.CentralT GBNP.ObsTall GBNP.ObsTrunc# @@ -379,7 +392,7 @@ end;; GBNP.Spoly:=function(l,G) return(AddNP(BimulNP(l[1],G[l[2]],l[3]),BimulNP(l[4],G[l[5]],l[6]), - One(G[l[2]][2][1]),-1*One(G[l[2]][2][1]))); + One(G[l[2]][2][1]),-1*One(G[l[2]][2][1]))); end;; ################### @@ -393,19 +406,19 @@ end;; ### - polynomial f is not empty. (= [[],[]]) ### ### Arguments: -### f - a non-commutative polynomial -### G - list of non-commutative polynomials -### G2 - list of non-commutative polynomials +### f - a non-commutative polynomial +### G - list of non-commutative polynomials +### G2 - list of non-commutative polynomials ### ### Returns: -### pol - normal form of f w.r.t. G union G2 +### pol - normal form of f w.r.t. G union G2 ### ### #GBNP.NormalForm2 uses: AddNP BimulNP GBNP.OccurInLst LMonsNP# ### #GBNP.NormalForm2 is used in: GBNP.NormalForm# ### -GBNP.NormalForm2:=function(f,G,G2) local g,h,i,j,l,dr,ga,tt,lth,ltsG,i2,l2,ltsG2; - +GBNP.NormalForm2:=function(f,G,G2) + local g,h,i,j,l,dr,ga,tt,lth,ltsG,i2,l2,ltsG2; tt:=Runtime(); h:=StructuralCopy(f); lth:=h[1][1]; @@ -415,38 +428,36 @@ GBNP.NormalForm2:=function(f,G,G2) local g,h,i,j,l,dr,ga,tt,lth,ltsG,i2,l2,ltsG2 l2:=Length(ltsG2); i:=GBNP.OccurInLst(lth,ltsG); i2:=GBNP.OccurInLst(lth,ltsG2); - while i[1]>0 or i2[1]>0 do - if i[1]>0 then - g:=G[i[1]]; - ga:=lth{[1..i[2]-1]}; - dr:=lth{[i[2]+Length(g[1][1])..Length(lth)]}; - h:=AddNP(h,BimulNP(ga,g,dr),One(h[2][1]),-h[2][1]/g[2][1]); - if h=[[],[]] then + while i[1]>0 or i2[1]>0 do + if i[1]>0 then + g:=G[i[1]]; + ga:=lth{[1..i[2]-1]}; + dr:=lth{[i[2]+Length(g[1][1])..Length(lth)]}; + h:=AddNP(h,BimulNP(ga,g,dr),One(h[2][1]),-h[2][1]/g[2][1]); + if h=[[],[]] then # Print("computation time of the NormalForm = ",Runtime()-tt,"\n"); - return(h); - fi; - lth:=h[1][1]; - i:=GBNP.OccurInLst(lth,ltsG); - i2:=GBNP.OccurInLst(lth,ltsG2); - else - g:=G2[i2[1]]; - ga:=lth{[1..i2[2]-1]}; - dr:=lth{[i2[2]+Length(g[1][1])..Length(lth)]}; - h:=AddNP(h,BimulNP(ga,g,dr),One(h[2][1]),-h[2][1]/g[2][1]); - if h=[[],[]] then + return(h); + fi; + lth:=h[1][1]; + i:=GBNP.OccurInLst(lth,ltsG); + i2:=GBNP.OccurInLst(lth,ltsG2); + else + g:=G2[i2[1]]; + ga:=lth{[1..i2[2]-1]}; + dr:=lth{[i2[2]+Length(g[1][1])..Length(lth)]}; + h:=AddNP(h,BimulNP(ga,g,dr),One(h[2][1]),-h[2][1]/g[2][1]); + if h=[[],[]] then # Print("computation time of the NormalForm = ",Runtime()-tt,"\n"); - return(h); - fi; - lth:=h[1][1]; - i:=GBNP.OccurInLst(lth,ltsG); - i2:=GBNP.OccurInLst(lth,ltsG2); - fi; + return(h); + fi; + lth:=h[1][1]; + i:=GBNP.OccurInLst(lth,ltsG); + i2:=GBNP.OccurInLst(lth,ltsG2); + fi; od; # Print("computation time of the NormalForm = ",Runtime()-tt,"\n"); return(h); end;; - - ################### ### GBNP.NormalForm @@ -457,19 +468,21 @@ end;; ### - polynomial f is clean. ### ### Arguments: -### f - a non-commutative polynomial -### G - list of non-commutative polynomials +### f - a non-commutative polynomial +### G - list of non-commutative polynomials ### ### Returns: -### pol - normal form of f w.r.t. G +### pol - normal form of f w.r.t. G ### ### #GBNP.NormalForm uses: GBNP.NormalForm2# ### #GBNP.NormalForm is used in:# ### GBNP.NormalForm:=function(f,G) - if f = [[],[]] then return f; - else return GBNP.NormalForm2(f,G,[]); + if f = [[],[]] then + return f; + else + return GBNP.NormalForm2(f,G,[]); fi; end;; @@ -484,12 +497,12 @@ end;; ### - polynomial f is not empty (that is, f <> [[],[]]). ### ### Arguments: -### f - a non-commutative polynomial -### G - list of non-commutative polynomials -### G2 - list of non-commutative polynomials +### f - a non-commutative polynomial +### G - list of non-commutative polynomials +### G2 - list of non-commutative polynomials ### ### Returns: -### pol - strong normalform of f w.r.t. G +### pol - strong normalform of f w.r.t. G ### ### #GBNP.StrongNormalForm2 uses: AddNP BimulNP GBNP.OccurInLst LMonsNP# ### #GBNP.StrongNormalForm2 is used in: GBNP.ObsTrunc StrongNormalFormNP StrongNormalFormNPM# @@ -503,39 +516,41 @@ GBNP.StrongNormalForm2:=function(f,G,G2) ltsG2:=LMonsNP(G2); iid := 1; while iid <= Length(h[1]) do - lth:=h[1][iid]; - l:=Length(ltsG); - l2:=Length(ltsG2); - i1:=GBNP.OccurInLst(lth,ltsG); - i2:=GBNP.OccurInLst(lth,ltsG2); - while i1[1]+i2[1]>0 do -# Print("starting while loop with in StrongNormalForm2 with\n "); -# Print(" i1[1]+i2[1] = ", i1[1]+i2[1]," and h="); PrintNP(h); + lth:=h[1][iid]; + l:=Length(ltsG); + l2:=Length(ltsG2); + i1:=GBNP.OccurInLst(lth,ltsG); + i2:=GBNP.OccurInLst(lth,ltsG2); + while i1[1]+i2[1]>0 do if i1[1]>0 then - g:=G[i1[1]]; - ga:=lth{[1..i1[2]-1]}; - dr:=lth{[i1[2]+Length(g[1][1])..Length(lth)]}; - h:=AddNP(h,BimulNP(ga,g,dr),One(g[2][1]),-h[2][iid]/g[2][1]); - if h=[[],[]] then return(h); fi; + g:=G[i1[1]]; + ga:=lth{[1..i1[2]-1]}; + dr:=lth{[i1[2]+Length(g[1][1])..Length(lth)]}; + h:=AddNP(h,BimulNP(ga,g,dr),One(g[2][1]),-h[2][iid]/g[2][1]); + if h=[[],[]] then + return(h); + fi; if iid <= Length(h[1]) then - lth := h[1][iid]; - i1:=GBNP.OccurInLst(lth,ltsG); - i2:=GBNP.OccurInLst(lth,ltsG2); - else - return(h); + lth := h[1][iid]; + i1:=GBNP.OccurInLst(lth,ltsG); + i2:=GBNP.OccurInLst(lth,ltsG2); + else + return(h); fi; else - g:=G2[i2[1]]; - ga:=lth{[1..i2[2]-1]}; - dr:=lth{[i2[2]+Length(g[1][1])..Length(lth)]}; - h:=AddNP(h,BimulNP(ga,g,dr),One(g[2][1]),-h[2][iid]/g[2][1]); - if h=[[],[]] then return(h); fi; + g:=G2[i2[1]]; + ga:=lth{[1..i2[2]-1]}; + dr:=lth{[i2[2]+Length(g[1][1])..Length(lth)]}; + h:=AddNP(h,BimulNP(ga,g,dr),One(g[2][1]),-h[2][iid]/g[2][1]); + if h=[[],[]] then + return(h); + fi; if iid <= Length(h[1]) then - lth := h[1][iid]; - i1:=GBNP.OccurInLst(lth,ltsG); - i2:=GBNP.OccurInLst(lth,ltsG2); + lth := h[1][iid]; + i1:=GBNP.OccurInLst(lth,ltsG); + i2:=GBNP.OccurInLst(lth,ltsG2); else - return(h); + return(h); fi; fi; od; @@ -544,7 +559,6 @@ GBNP.StrongNormalForm2:=function(f,G,G2) Info(InfoGBNP,3, "computation time of the StrongNormalFormNP = ",Runtime()-tt); return(h); end;; - ################### ### StrongNormalFormNP @@ -577,17 +591,16 @@ end;; ### ### ### Arguments: -### f - a non-commutative polynomial -### G - list of non-commutative polynomials +### f - a non-commutative polynomial +### G - list of non-commutative polynomials ### ### Returns: -### pol - a strong normalform of f with respect to G +### pol - a strong normalform of f with respect to G ### ### #StrongNormalFormNP uses: CleanNP GBNP.StrongNormalForm2 MkMonicNP# ### #StrongNormalFormNP is used in: MulQA# ### - InstallGlobalFunction( StrongNormalFormNP, function(f,G) local ih, fm, Gl, lts, lcf, hlp; fm := CleanNP(f); @@ -597,140 +610,103 @@ InstallGlobalFunction( StrongNormalFormNP, function(f,G) Gl := []; lts := []; for ih in G do hlp := MkMonicNP(CleanNP(ih)); - if hlp <> [[],[]] then - Add(Gl,hlp); - Add(lts,hlp[1][1]); - fi; + if hlp <> [[],[]] then + Add(Gl,hlp); + Add(lts,hlp[1][1]); + fi; od; SortParallel(lts,Gl,LtNP); fm := GBNP.StrongNormalForm2(fm,Gl,[]); return([fm[1], lcf * fm[2]]); end);; - ################## ### GBNP.ReducePol2 ### New function to clean the input ### - set variant ### ### Arguments: -### G - list of non-commutative polynomials +### G - list of non-commutative polynomials ### GLOT (opt) - optional occur tree ### ### Results in: -### G - Cleaned, reduced, ordered list of non trivial S-polynomials. +### G - Cleaned, reduced, ordered list of non trivial S-polynomials. ### Returns: -### GLOT - Updated occur tree +### GLOT - Updated occur tree ### ### #GBNP.ReducePol2 uses: GBNP.AddMonToTreePTSLR GBNP.CalculatePGlts GBNP.CreateOccurTreePTSLR GBNP.GetOptions GBNP.Occur GBNP.ReduceCancellation GBNP.RemoveMonFromTreePTSLR GBNP.StrongNormalForm2TS LMonsNP LtNP MkMonicNP# ### #GBNP.ReducePol2 is used in: GBNP.AllObsTrunc GBNP.ReducePol GBNP.SGrobnerTruncLevel SGrobner# ### GBNP.ReducePol2:=function(arg) -local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT,done,one,count; + local i,j,jl,h,ind,lts,new,lans,newind,temp,G,GLOT; G:=arg[1]; if Length(arg)>=2 then - GLOT:=arg[2]; + GLOT:=arg[2]; lts:=LMonsNP(G); - if IsBound(GBNP.GetOptions().CancellativeMonoid) then - lts:=StructuralCopy(lts); - # Structural copy is needed to be able to update the tree - # in case of a cancellative monoid - for i in [1..Length(G)] do - G[i]:=GBNP.ReduceCancellation(G[i]); - if (G[i][1]<>lts[i]) then - GBNP.RemoveMonFromTreePTSLR(lts[i],i,GLOT,true); - GBNP.AddMonToTreePTSLR(G[i][1],i,GLOT,true); - lts[i]:=G[i][1]; - fi; - od; - - fi; - temp:=ShallowCopy(lts); - SortParallel(lts,G,LtNP); - GBNP.SortParallelLOT(temp,GLOT,LtNP); + if IsBound(GBNP.GetOptions().CancellativeMonoid) then + lts:=StructuralCopy(lts); + # Structural copy is needed to be able to update the tree + # in case of a cancellative monoid + for i in [1..Length(G)] do + G[i]:=GBNP.ReduceCancellation(G[i]); + if (G[i][1]<>lts[i]) then + GBNP.RemoveMonFromTreePTSLR(lts[i],i,GLOT,true); + GBNP.AddMonToTreePTSLR(G[i][1],i,GLOT,true); + lts[i]:=G[i][1]; + fi; + od; + + fi; + temp:=ShallowCopy(lts); + SortParallel(lts,G,LtNP); + GBNP.SortParallelLOT(temp,GLOT,LtNP); else -count:=0; - done := false; - while not done do -count:=count+1; -Print( "\ncount = ", count, "\n" ); - for i in [1..Length(G)] do - G[i]:=GBNP.ReduceCancellation(G[i]); - od; - lts:=LMonsNP(G); - SortParallel(lts,G,LtNP); -if (count=1) then -Print("after initial sorting, G has length ", Length(G), "\n", G, "\n" ); -fi; - done := true; - for i in Reversed( [1..Length(lts)-1] ) do - if ( lts[i] = lts[i+1] ) then - done := false; -## Print( "G[i],G[i+1] = ", G[i], G[i+1], "\n" ); - one:=One(G[i][2][1]); - G[i+1] := MkMonicNP(CleanNP(AddNP(G[i+1],G[i],one,-one))); -## Print( "new G[i+1] = ", G[i+1], "\n" ); - fi; - od; - if not done then - ## need to resort G - G := Filtered( G, L -> L <> [ [ ], [ ] ] ); - lts:=LMonsNP(G); - SortParallel(lts,G,LtNP); -Print( "G now has length ", Length(G), "\n" ); -Print( "resorted lts and G:\n", lts, "\n", G, "\n" ); - fi; - od; - -Print( "after SortParallel G and lts =:\n", G, "\n", lts, "\n" ); - - GLOT:=GBNP.CreateOccurTreePTSLR(lts,GBNP.CalculatePGlts(lts),true); - + for i in [1..Length(G)] do + G[i]:=GBNP.ReduceCancellation(G[i]); + od; + lts:=LMonsNP(G); + SortParallel(lts,G,LtNP); + GLOT:=GBNP.CreateOccurTreePTSLR(lts,GBNP.CalculatePGlts(lts),true); fi; lans:=Length(lts); ind:=[1..lans]; while ind <> [] do - i:=ind[1]; + i:=ind[1]; RemoveSet(ind,i); j:=i+1; - while j <= lans do - if #IsSubsetBlist(Gset[j],Gset[i]) and - GBNP.Occur(G[i][1][1],G[j][1][1]) <> 0 - # XXX can this occur be removed - then - new:=GBNP.StrongNormalForm2TS(G,j,GLOT); - if new = [[],[]] then -Print( "new at [i,j] = ", [i,j], "\n" ); - GBNP.RemoveMonFromTreePTSLR(G[j][1][1],j,GLOT,true); - RemoveElmList(G,j); - RemoveSet(ind,lans); - lans:=lans-1; - else - newind:=PositionSorted(G,new, - function(x,y) return LtNP(x[1][1], y[1][1]); end - ); - GBNP.RemoveMonFromTreePTSLR(G[j][1][1],j,GLOT,true); - RemoveElmList(G,j); - GBNP.AddMonToTreePTSLR(new[1][1],newind,GLOT,true); - InsertElmList(G,newind,MkMonicNP(new)); - RemoveSet(ind,j); - + while j <= lans do + if #IsSubsetBlist(Gset[j],Gset[i]) and + ( GBNP.Occur(G[i][1][1],G[j][1][1]) <> 0 ) then + # XXX can this occur be removed + new:=GBNP.StrongNormalForm2TS(G,j,GLOT); + if new = [[],[]] then + GBNP.RemoveMonFromTreePTSLR(G[j][1][1],j,GLOT,true); + RemoveElmList(G,j); + RemoveSet(ind,lans); + lans:=lans-1; + else + newind:=PositionSorted(G,new, + function(x,y) return LtNP(x[1][1], y[1][1]); end); + GBNP.RemoveMonFromTreePTSLR(G[j][1][1],j,GLOT,true); + RemoveElmList(G,j); + GBNP.AddMonToTreePTSLR(new[1][1],newind,GLOT,true); + InsertElmList(G,newind,MkMonicNP(new)); + RemoveSet(ind,j); + for h in [1..Length(ind)] do - if ind[h] in [newind..j-1] then ind[h]:=ind[h]+1; fi; - od; - if i in [newind..j-1] then i:=i+1; fi; - AddSet(ind,newind); - j:=j+1; - fi; - else - j:=j+1; - fi; - od; + if ind[h] in [newind..j-1] then ind[h]:=ind[h]+1; fi; + od; + if i in [newind..j-1] then i:=i+1; fi; + AddSet(ind,newind); + j:=j+1; + fi; + else + j:=j+1; + fi; + od; od; -Print( "in ReducePol2 at end of [i,j] loop:\n" ); -Print( "G has length ", Length(G), ", G[3] = ", G[3], "\n" ); return GLOT; end;; @@ -739,23 +715,47 @@ end;; ### New function to clean the input ### ### Arguments: -### G - list of non-commutative polynomials +### G - list of non-commutative polynomials ### ### Returns: -### G - Cleaned, reduced, ordered list of non-trivial S-polynomials. +### G - Cleaned, reduced, ordered list of non-trivial S-polynomials. ### ### #GBNP.ReducePol uses: CleanNP GBNP.ReducePol2 MkMonicNP# ### #GBNP.ReducePol is used in: GBNP.SGrobnerTrunc GBNP.SGrobnerTruncLevel Grobner SGrobner# ### -GBNP.ReducePol:=function(B) local ans; - - ans:=List(B,x -> MkMonicNP(CleanNP(x))); - ans:=Filtered(ans, x -> x <> [[],[]]); - GBNP.ReducePol2(ans); -Print( "in ReducePol after ReducePol2:\n" ); -Print("ans has length ", Length(ans), ", ans[3] = ", ans[3], "\n" ); - return(ans); +GBNP.ReducePol:=function(B) + local G,i,done,one,count; + G:=List(B,x -> MkMonicNP(CleanNP(x))); + G:=Filtered(G, x -> x <> [[],[]]); + ## Extra loop added October 2023 to fix issue #15 + ## this tests to find two polynomials with the same leading monomial + ## and, when found, replaces the second with their difference. + ## Note that this includes the case when a polynomial is repeated. + count:=0; + done := false; + while not done do + count:=count+1; + for i in [1..Length(G)] do + G[i]:=GBNP.ReduceCancellation(G[i]); + od; + Sort(G,function(u,v) return LtNP(u[1][1],v[1][1]);end); + done := true; + for i in Reversed( [1..Length(G)-1] ) do + if ( G[i][1][1] = G[i+1][1][1] ) then + done := false; + one:=One(G[i][2][1]); + G[i+1] := MkMonicNP(CleanNP(AddNP(G[i+1],G[i],one,-one))); + fi; + od; + if not done then + ## need to resort G + G := Filtered( G, L -> L <> [ [ ], [ ] ] ); + Sort(G,function(u,v) return LtNP(u[1][1],v[1][1]);end); + fi; + od; + GBNP.ReducePol2(G); + return(G); end;; ################### @@ -784,20 +784,21 @@ end;; ### - (should this be added) reducing with G ### ### Arguments: -### G - list of non-commutative polynomials +### G - list of non-commutative polynomials ### ### Returns: -### todo - list of non trivial S-polynomials. +### todo - list of non trivial S-polynomials. ### ## #GBNP.AllObs uses: GBNP.AddMonToTreePTSLR GBNP.CreateOccurTreePTSLR GBNP.GetOptions GBNP.ObsTall GBNP.StrongNormalFormTall LMonsNP# ### #GBNP.AllObs is used in: GBNP.IsGrobnerBasisTest Grobner IsGrobnerPair MakeGrobnerPair SGrobner# ### -GBNP.AllObs:=function(G, funcs) local k,ans,temp,GLOT,ansLOT,pGLOT,pGROT,from; - +GBNP.AllObs:=function(G, funcs) + local k,ans,temp,GLOT,ansLOT,pGLOT,pGROT,from; # a trivial Gröbner basis has no obstructions. - if (G=[]) or (G=[ [ [ [ ] ], [ 1 ] ] ]) then return []; fi; - + if (G=[]) or (G=[ [ [ [ ] ], [ 1 ] ] ]) then + return []; + fi; ans := []; ansLOT := GBNP.CreateOccurTreePTSLR( [], funcs.pg, true );; GLOT := GBNP.CreateOccurTreePTSLR( LMonsNP(G), funcs.pg, true ); @@ -805,30 +806,27 @@ GBNP.AllObs:=function(G, funcs) local k,ans,temp,GLOT,ansLOT,pGLOT,pGROT,from; pGROT := GBNP.CreateOccurTreePTSLR( [], funcs.pg, false ); if IsBound( GBNP.GetOptions().lenGB ) then - from := GBNP.GetOptions().lenGB; + from := GBNP.GetOptions().lenGB; else - from := 1; + from := 1; fi; for k in [ from .. Length(G) ] do GBNP.AddMonToTreePTSLR( G[k][1][1], k, pGLOT, true); GBNP.AddMonToTreePTSLR( G[k][1][1], k, pGROT, false); - GBNP.ObsTall( k, G, ans, rec( GL:=GLOT, pGL:=pGLOT, pGR:=pGROT, - todoL:=ansLOT ), funcs); # change this in a new AllObsall + GBNP.ObsTall( k, G, ans, rec( GL:=GLOT, pGL:=pGLOT, pGR:=pGROT, + todoL:=ansLOT ), funcs); # change this in a new AllObsall od; # only reduce with G, do not reduce with itself yet # GBNP.ReducePol2( ans ); for k in [1 .. Length(ans)] do - ans[k]:=GBNP.StrongNormalFormTall(ans[k],G,GLOT,funcs); + ans[k]:=GBNP.StrongNormalFormTall(ans[k],G,GLOT,funcs); od; - temp := LMonsNP( ans ); SortParallel( temp, ans, LtNP ); - return( ans ); end;; - ################## ### Grobner ### <#GAPDoc Label="Grobner"> @@ -900,17 +898,17 @@ InstallGlobalFunction( Grobner, function(arg) # the number of arguments should be 1 or 2 (KI [, max]) if Length(arg)<1 then - return fail; + return fail; else - KI:=arg[1]; + KI:=arg[1]; fi; tt:=Runtime(); - + if Length(arg)>=2 and IsInt(arg[Length(arg)]) then funcs.maxiterations := arg[Length(arg)]; fi; - + if Length(arg)>=2 and IsList(arg[2]) then withpair:=true; else @@ -932,13 +930,10 @@ InstallGlobalFunction( Grobner, function(arg) G:= GBNP.ReducePol(KI); fi; -Print( "here is the resulting G\n", G, "\n" ); - # only call GBNP.CalculatePG after reduction funcs.pg:=GBNP.CalculatePG(G); Info(InfoGBNP,1,"number of polynomials after reduction is ",Length(G)); -# Print("The list of starting polynomials is:\n ",G,"\n"); Info(InfoGBNP,1,"End of phase I"); @@ -952,22 +947,17 @@ Print( "here is the resulting G\n", G, "\n" ); else todo:=GBNP.AllObs(G, funcs); fi; + Info(InfoGBNP,1,"End of phase II"); -# Print("Current list of spolynomials is ",todo,"\n"); -# Print("Current number of spolynomials is ",Length(todo),"\n"); - Info(InfoGBNP,1,"End of phase II"); - - -# phase III, The loop + # phase III, The loop loop := GBNP.SGrobnerLoops(G,todo,funcs); if loop.completed <> true then - Info(InfoGBNP,1,"Calculation interrupted after ",funcs.maxiterations, - " iterations" - ); + Info(InfoGBNP,1,"Calculation interrupted after ", + funcs.maxiterations," iterations"); else - Info(InfoGBNP,1,"End of phase III"); + Info(InfoGBNP,1,"End of phase III"); fi; # End of the algorithm @@ -975,9 +965,9 @@ Print( "here is the resulting G\n", G, "\n" ); Info(InfoGBNPTime,1,"The computation took ",Runtime()-tt," msecs."); if IsBound(funcs.maxiterations) then - return loop; + return loop; else - return loop.G; + return loop.G; fi; end); @@ -1055,22 +1045,22 @@ InstallGlobalFunction( SGrobner, function(arg) funcs:=ShallowCopy(GBNP.SGrobnerLoopRec); if Length(arg)<1 then - return fail; + return fail; else - KI:=arg[1]; + KI:=arg[1]; fi; tt:=Runtime(); if Length(arg)>=2 and IsInt(arg[Length(arg)]) then funcs.maxiterations := arg[Length(arg)]; fi; - + if Length(arg)>=2 and IsList(arg[2]) then withpair:=true; else withpair:=false; fi; - + # phase I, start-up, building G # - Clean the list and make all polynomials monic # - Sort each polynomial so that its leading term is in front @@ -1085,19 +1075,13 @@ InstallGlobalFunction( SGrobner, function(arg) G:= ShallowCopy(KI); else G:= GBNP.ReducePol(KI); -Print( "in SGrobner G has length ", Length(G), ", G[3] = ", G[3], "\n" ); fi; -Print( "after call of GBNP.ReducePol: \n" ); -Print( "G has length ", Length(G), ", G[3] = ", G[3], "\n" ); - # only call GBNP.CalculatePG after reduction funcs.pg:=GBNP.CalculatePG(G); Info(InfoGBNP,1,"number of polynomials after reduction is ",Length(G)); -# Print("The list of starting polynomials is:\n ",G,"\n"); Info(InfoGBNP,1,"End of phase I"); - # phase II, initialization, making todo # - Compute all possible obstructions @@ -1109,60 +1093,52 @@ Print( "G has length ", Length(G), ", G[3] = ", G[3], "\n" ); else todo:=GBNP.AllObs(G, funcs); fi; - -# Print("Current list of spolynomials is ",todo,"\n"); -# Print("Current number of spolynomials is ",Length(todo),"\n"); Info(InfoGBNP,1,"End of phase II"); - -# phase III, The loop + # phase III, The loop loop := GBNP.SGrobnerLoops(G,todo,funcs); - if loop.completed <> true then - Info(InfoGBNP,1,"Calculation interrupted after ",funcs.maxiterations, - " iterations" - ); + Info(InfoGBNP,1,"Calculation interrupted after ", + funcs.maxiterations," iterations"); else - Info(InfoGBNP,1,"End of phase III"); + Info(InfoGBNP,1,"End of phase III"); fi; # phase IV, Make the result reduced GLOT:=GBNP.ReducePol2(G); GBNP.ReducePolTails(G,[],GLOT); # reduce the tails of the polynomials - Info(InfoGBNP,1,"End of phase IV"); # End of the algorithm - Info(InfoGBNPTime,1,"The computation took ",Runtime()-tt," msecs."); - - if IsBound(funcs.maxiterations) then - return loop; - else - return loop.G; - fi; + Info(InfoGBNPTime,1,"The computation took ",Runtime()-tt," msecs."); + if IsBound(funcs.maxiterations) then + return loop; + else + return loop.G; + fi; end); ###################################################### ### GBNP.NondivMons ### ### Arguments: -### lts - list of leading terms -### t - number of elements in the alphabet -### maxno - maximum number of monomials to be found +### lts - list of leading terms +### t - number of elements in the alphabet +### maxno - maximum number of monomials to be found ### ### Returns: -### ans - List of nondiv. monomials +### ans - List of nondiv. monomials ### -### uses: - GBNP.RightOccurInLst -### used in: - DimQA, BaseQA +### uses: - GBNP.RightOccurInLst +### used in: - DimQA, BaseQA # new version in occurtree3.gi ###################################################### -###BaseQA +### BaseQA ### ### <#GAPDoc Label="BaseQA"> ### @@ -1190,14 +1166,14 @@ end); ### ### returns a basis of terms ### Arguments: -### G - a Grobner basis -### t - number of elements in the alphabet -### maxno - maximum number of terms to be found +### G - a Grobner basis +### t - number of elements in the alphabet +### maxno - maximum number of terms to be found ### ### Returns: -### ans - List of terms forming a basis of QA = NP algebra mod G +### ans - List of terms forming a basis of QA = NP algebra mod G ### -### uses: - GBNP.NondivMons, LMonsNP +### uses: - GBNP.NondivMons, LMonsNP ### #BaseQA uses: GBNP.NondivMons LMonsNP# ### #BaseQA is used in:# ### @@ -1211,9 +1187,9 @@ InstallGlobalFunction( BaseQA, function(G,t,maxno) GF:=Filtered(G,x->x<>[[],[]]); if Length(GF)>0 then - one:=One(GF[1][2][1]); + one:=One(GF[1][2][1]); else - one:=1; + one:=1; fi; hlst := GBNP.NondivMons(LMonsNP(G),t,maxno); ans := []; @@ -1222,11 +1198,11 @@ InstallGlobalFunction( BaseQA, function(G,t,maxno) Add(ans,[[h],[one]]); od; od; - return ans; + return ans; end);; ###################################################### -###DimQA +### DimQA ### <#GAPDoc Label="DimQA"> ### ### ### <#/GAPDoc> ### Arguments: -### G - a Grobner basis +### G - a Grobner basis ### n - the number of variables ### ### Returns: -### s - the dimension of the quotient algebra +### s - the dimension of the quotient algebra ### ### #DimQA uses: GBNP.NondivMonsPTSenum LMonsNP# ### #DimQA is used in:# ### InstallGlobalFunction( DimQA, function(G,n) - local s,t0; - - if n = 0 then - n := NumAlgGensNPList(G); - fi; - t0 := Runtime(); - if Length(G) = 0 then - Error("dim is infinite as ideal is trivial.\n"); - fi; - s := GBNP.NondivMonsPTSenum([],LMonsNP(G),n,0,0); - Info(InfoGBNPTime,2,"The computation took ",Runtime()-t0," msecs."); - return s; -end);; + local s,t0; + if n = 0 then + n := NumAlgGensNPList(G); + fi; + t0 := Runtime(); + if Length(G) = 0 then + Error("dim is infinite as ideal is trivial.\n"); + fi; + s := GBNP.NondivMonsPTSenum([],LMonsNP(G),n,0,0); + Info(InfoGBNPTime,2,"The computation took ",Runtime()-t0," msecs."); + return s; +end);; #################################################### -###MulQA multiplication in the quotient algebra +### MulQA multiplication in the quotient algebra ### <#GAPDoc Label="MulQA"> ### ### ### ### Arguments: -### G - a Grobner basis +### G - a Grobner basis ### p1, p2 - two polynomials ### ### Returns: -### ans - the strong normal form of the product p1*p2 with +### ans - the strong normal form of the product p1*p2 with ### respect to G ### ### #MulQA uses: MulNP StrongNormalFormNP# @@ -1315,7 +1290,7 @@ end);; ### InstallGlobalFunction( MulQA, function(p1,p2,G) - return StrongNormalFormNP(MulNP(p1,p2),G); + return StrongNormalFormNP(MulNP(p1,p2),G); end);; ################### @@ -1331,14 +1306,14 @@ end);; ### - polynomial f is not empty (that is, f <> [[],[]]). ### ### Arguments: -### f - a non-commutative polynomial -### G - list of non-commutative polynomials -### G2 - list of non-commutative polynomials -### Gset - list of the leading term-sets -### G2set - list of the leading term-sets +### f - a non-commutative polynomial +### G - list of non-commutative polynomials +### G2 - list of non-commutative polynomials +### Gset - list of the leading term-sets +### G2set - list of the leading term-sets ### ### Returns: -### pol - strong normalform of f w.r.t. G +### pol - strong normalform of f w.r.t. G ### ### #GBNP.StrongNormalForm2TS uses: AddNP BimulNP GBNP.LookUpOccurTreeAllLstPTSLR# ### #GBNP.StrongNormalForm2TS is used in: GBNP.ReducePol2 GBNP.ReducePolTails# @@ -1346,34 +1321,30 @@ end);; GBNP.StrongNormalForm2TS:=function(G,j,GLOT) local g,h,il,i1,l,dr,ga,tt,lth,iid; - -## Print( "in StrongNormalForm2TS G[j] = ", G[j], "\n" ); - h:=StructuralCopy(G[j]); iid := 1; while iid <= Length(h[1]) do - lth:=h[1][iid]; - il:=GBNP.LookUpOccurTreeAllLstPTSLR(lth,GLOT,true); - -## Print( "il = ", il, "\n" ); - - il:=Filtered(il,x->x[1]<>j); - while il<>[] do - i1:=il[1]; - g:=G[i1[1]]; - ga:=lth{[1..i1[2]-1]}; - dr:=lth{[i1[2]+Length(g[1][1])..Length(lth)]}; - h:=AddNP(h,BimulNP(ga,g,dr),One(g[2][1]),-h[2][iid]/g[2][1]); - if h=[[],[]] then return(h); fi; - if iid <= Length(h[1]) then + lth:=h[1][iid]; + il:=GBNP.LookUpOccurTreeAllLstPTSLR(lth,GLOT,true); + il:=Filtered(il,x->x[1]<>j); + while il<>[] do + i1:=il[1]; + g:=G[i1[1]]; + ga:=lth{[1..i1[2]-1]}; + dr:=lth{[i1[2]+Length(g[1][1])..Length(lth)]}; + h:=AddNP(h,BimulNP(ga,g,dr),One(g[2][1]),-h[2][iid]/g[2][1]); + if h=[[],[]] then + return(h); + fi; + if iid <= Length(h[1]) then lth := h[1][iid]; - il:=GBNP.LookUpOccurTreeAllLstPTSLR(lth,GLOT,true); - il:=Filtered(il,x->x[1]<>j); - else - return(h); - fi; - od; - iid := iid+1; + il:=GBNP.LookUpOccurTreeAllLstPTSLR(lth,GLOT,true); + il:=Filtered(il,x->x[1]<>j); + else + return(h); + fi; + od; + iid := iid+1; od; return(h); end;; @@ -1390,50 +1361,50 @@ end;; ### - polynomial f is not empty. (= [[],[]]) ### ### Arguments: -### f - a non-commutative polynomial -### G - list of non-commutative polynomials -### G2 - list of non-commutative polynomials +### f - a non-commutative polynomial +### G - list of non-commutative polynomials +### G2 - list of non-commutative polynomials ### ### Returns: -### pol - normal form of f w.r.t. G union G2 +### pol - normal form of f w.r.t. G union G2 ### ### #GBNP.NormalForm2T uses: AddNP BimulNP GBNP.OccurInLstT# ### #GBNP.NormalForm2T is used in:# ### GBNP.NormalForm2T:=function(f,G,G2,GLOT,G2LOT) -local g,h,i,i2,j,l,dr,ga,tt,lth; + local g,h,i,i2,j,l,dr,ga,tt,lth; tt:=Runtime(); h:=StructuralCopy(f); lth:=h[1][1]; i:=GBNP.OccurInLstT(lth,GLOT); i2:=GBNP.OccurInLstT(lth,G2LOT); while i[1]>0 or i2[1]>0 do - if i[1]>0 then - g:=G[i[1]]; - ga:=lth{[1..i[2]-1]}; - dr:=lth{[i[2]+Length(g[1][1])..Length(lth)]}; - h:=AddNP(h,BimulNP(ga,g,dr),One(h[2][1]),-h[2][1]/g[2][1]); - if h=[[],[]] then - Info(InfoGBNPTime,3,"computation time of the NormalForm = ",Runtime()-tt); - return(h); - fi; - lth:=h[1][1]; - i:=GBNP.OccurInLstT(lth,GLOT); - i2:=GBNP.OccurInLstT(lth,G2LOT); - else - g:=G2[i2[1]]; - ga:=lth{[1..i2[2]-1]}; - dr:=lth{[i2[2]+Length(g[1][1])..Length(lth)]}; - h:=AddNP(h,BimulNP(ga,g,dr),One(h[2][1]),-h[2][1]/g[2][1]); - if h=[[],[]] then - Info(InfoGBNPTime,3,"computation time of the NormalForm = ",Runtime()-tt); - return(h); - fi; - lth:=h[1][1]; - i:=GBNP.OccurInLstT(lth,GLOT); - i2:=GBNP.OccurInLstT(lth,G2LOT); - fi; + if i[1]>0 then + g:=G[i[1]]; + ga:=lth{[1..i[2]-1]}; + dr:=lth{[i[2]+Length(g[1][1])..Length(lth)]}; + h:=AddNP(h,BimulNP(ga,g,dr),One(h[2][1]),-h[2][1]/g[2][1]); + if h=[[],[]] then + Info(InfoGBNPTime,3,"computation time of the NormalForm = ",Runtime()-tt); + return(h); + fi; + lth:=h[1][1]; + i:=GBNP.OccurInLstT(lth,GLOT); + i2:=GBNP.OccurInLstT(lth,G2LOT); + else + g:=G2[i2[1]]; + ga:=lth{[1..i2[2]-1]}; + dr:=lth{[i2[2]+Length(g[1][1])..Length(lth)]}; + h:=AddNP(h,BimulNP(ga,g,dr),One(h[2][1]),-h[2][1]/g[2][1]); + if h=[[],[]] then + Info(InfoGBNPTime,3,"computation time of the NormalForm = ",Runtime()-tt); + return(h); + fi; + lth:=h[1][1]; + i:=GBNP.OccurInLstT(lth,GLOT); + i2:=GBNP.OccurInLstT(lth,G2LOT); + fi; od; Info(InfoGBNPTime,3,"computation time of the NormalForm = ",Runtime()-tt); return(h); @@ -1446,44 +1417,45 @@ end;; ### - uses lterm-sets ### ### Arguments: -### j - index of a non-commutative polynomial in G -### G - list of non-commutative polynomials -### lst - list of S-polynomials (todo) +### j - index of a non-commutative polynomial in G +### G - list of non-commutative polynomials +### lst - list of S-polynomials (todo) ### Gset ### lstset ### ### Returns: -### todo - new list of S-polynomials. S-polynomials with G[j] added +### todo - new list of S-polynomials. S-polynomials with G[j] added ### ### #GBNP.CentralT uses: GBNP.AddMonToTreePTSLR GBNP.Occur GBNP.Spoly GBNP.StrongNormalForm2Tall LMonsNP MkMonicNP# ### #GBNP.CentralT is used in:# ### -GBNP.CentralT:=function(j,G,todo,OT,funcs) local R,ob,temp,a,i,o,u,v,lu,lv,all; - R := LMonsNP(G); - - u:=R[j]; - lu:=Length(u); - #all:=GBNP.LookUpOccurTreeAllLstPTSLR(u,OT.GL,true); - #all:=Filtered(all,x->x[1] 1 and o+lu<=lv then - temp:=GBNP.Spoly([v{[1..o-1]},j,v{[o+lu..lv]},[],i,[]],G); - if temp <> [[],[]] then - temp:=GBNP.StrongNormalForm2Tall(temp,G,todo,OT,funcs); - if temp <> [[],[]] then - Add(todo,MkMonicNP(temp)); - if not IsTHeapOT(todo) then # heap -> added to tree already - GBNP.AddMonToTreePTSLR(temp[1][1],-1, - OT.todoL,true); # jwk - add to the tree too - fi; - fi; - fi; - fi; - od; +GBNP.CentralT:=function(j,G,todo,OT,funcs) + local R,ob,temp,a,i,o,u,v,lu,lv,all; + R := LMonsNP(G); + u:=R[j]; + lu:=Length(u); + #all:=GBNP.LookUpOccurTreeAllLstPTSLR(u,OT.GL,true); + #all:=Filtered(all,x->x[1] 1 and o+lu<=lv then + temp:=GBNP.Spoly([v{[1..o-1]},j,v{[o+lu..lv]},[],i,[]],G); + if temp <> [[],[]] then + temp:=GBNP.StrongNormalForm2Tall(temp,G,todo,OT,funcs); + if temp <> [[],[]] then + Add(todo,MkMonicNP(temp)); + if not IsTHeapOT(todo) then + # heap -> added to tree already + GBNP.AddMonToTreePTSLR(temp[1][1],-1,OT.todoL,true); + # jwk - add to the tree too + fi; + fi; + fi; + fi; + od; end;; ################# @@ -1495,12 +1467,12 @@ end;; ### self obstruction of R[j] (if present) is taken into account. ### ### Arguments: -### j - index of the monomial for which we search left-obs. -### R - set of leading terms (monomials) -### sob - 'smallest' self-obstruction of R[j] +### j - index of the monomial for which we search left-obs. +### R - set of leading terms (monomials) +### sob - 'smallest' self-obstruction of R[j] ### ### Returns: -### ans - List of found left-obstructions +### ans - List of found left-obstructions ### ### #GBNP.LeftObsT uses: GBNP.AddMonToTreePTSLR GBNP.CreateOccurTreePTSLR GBNP.LookUpOccurTreeForObsPTSLR GBNP.LookUpOccurTreePTSLRPos LtNP# ### #GBNP.LeftObsT is used in: GBNP.ObsTall# @@ -1515,51 +1487,41 @@ end;; # + deelobstructies prefix reductie (sort,tree) GBNP.LeftObsT:=function(j,R,GLOT) -local i,k, - u,v, - l, - dr,ga,lo, - lu,lv, - mi,ans, - len, - ansLOT, - sob; - + local i,k,u,v,l,dr,ga,lo,lu,lv,mi,ans,len,ansLOT,sob; ans:=[]; u:=R[j]; lu:=Length(u); lo:=GBNP.LookUpOccurTreeForObsPTSLR(u,j,GLOT,true); for l in lo do - i:=l[1]; - v:=R[i]; - - lv:=Length(v); - mi:=Minimum([lu,lv]); - k:=lu+1-l[2]; - # if u{[lu-k+1..lu]}=v{[1..k]} # holds by lookup - ga:=u{[1..lu-k]}; - dr:=v{[k+1..lv]}; - - Add(ans,[[],j,dr,ga,i,[]]); + i:=l[1]; + v:=R[i]; + lv:=Length(v); + mi:=Minimum([lu,lv]); + k:=lu+1-l[2]; + # if u{[lu-k+1..lu]}=v{[1..k]} # holds by lookup + ga:=u{[1..lu-k]}; + dr:=v{[k+1..lv]}; + Add(ans,[[],j,dr,ga,i,[]]); od; Sort(ans,function(u,v) return LtNP(u[3],v[3]);end); ansLOT:=GBNP.CreateOccurTreePTSLR([],GLOT.pg,true); - - - i:=1;len:=Length(ans);sob:=0; + + i:=1; + len:=Length(ans); + sob:=0; while i<=len do - if GBNP.LookUpOccurTreePTSLRPos(ans[i][3],ansLOT,true,1) = 0 then - if ans[i][5]=j then #selfobs - sob:=i; - fi; - GBNP.AddMonToTreePTSLR(ans[i][3],i,ansLOT,true); - i:=i+1; - else - RemoveElmList(ans,i); - len:=len-1; - fi; + if GBNP.LookUpOccurTreePTSLRPos(ans[i][3],ansLOT,true,1) = 0 then + if ans[i][5]=j then #selfobs + sob:=i; + fi; + GBNP.AddMonToTreePTSLR(ans[i][3],i,ansLOT,true); + i:=i+1; + else + RemoveElmList(ans,i); + len:=len-1; + fi; od; return(rec(obs:=ans,sobnr:=sob)); @@ -1575,12 +1537,12 @@ end;; ### into account (if it exists). ### ### Arguments: -### j - index of the monomial for which we search left-obs. -### R - set of leading terms (monomials) -### GROT - set of leading terms (monomials) +### j - index of the monomial for which we search left-obs. +### R - set of leading terms (monomials) +### GROT - set of leading terms (monomials) ### ### Returns: -### ans - List of found left-obstructions +### ans - List of found left-obstructions ### ### #GBNP.RightObsT uses: GBNP.AddMonToTreePTSLR GBNP.CreateOccurTreePTSLR GBNP.LookUpOccurTreeForObsPTSLR GBNP.LookUpOccurTreePTSLRPos LtNP# ### #GBNP.RightObsT is used in: GBNP.ObsTall# @@ -1594,31 +1556,21 @@ end;; # + deelobstructies prefix reductie (sort,tree) GBNP.RightObsT:=function(j,R,GROT) -local i,k, - u,v, - l, - dr,ga,lo, - lu,lv, - mi,ans, - len, - ansROT, - sob; - + local i,k,u,v,l,dr,ga,lo,lu,lv,mi,ans,len,ansROT,sob; ans:=[]; u:=R[j]; lu:=Length(u); lo:=GBNP.LookUpOccurTreeForObsPTSLR(u,j,GROT,false); for l in lo do - i:=l[1]; - v:=R[i]; - lv:=Length(v); - mi:=Minimum([lu,lv]); - k:=lu+1-l[2]; - # if u{[lu-k+1..lu]}=v{[1..k]} # holds by lookup - ga:=v{[1..lv-k]}; - dr:=u{[k+1..lu]}; - - Add(ans,[ga,j,[],[],i,dr]); + i:=l[1]; + v:=R[i]; + lv:=Length(v); + mi:=Minimum([lu,lv]); + k:=lu+1-l[2]; + # if u{[lu-k+1..lu]}=v{[1..k]} # holds by lookup + ga:=v{[1..lv-k]}; + dr:=u{[k+1..lu]}; + Add(ans,[ga,j,[],[],i,dr]); od; Sort(ans,function(u,v) return LtNP(u[1],v[1]);end); @@ -1626,21 +1578,23 @@ local i,k, ansROT:=GBNP.CreateOccurTreePTSLR([],GROT.pg,false); if (ansROT.pg<> GROT.pg) then - Print(R,"\n"); + Print(R,"\n"); fi; - i:=1;len:=Length(ans);sob:=0; + i:=1; + len:=Length(ans); + sob:=0; while i<=len do - if GBNP.LookUpOccurTreePTSLRPos(ans[i][1],ansROT,false,1) = 0 then - if ans[i][5]=j then #selfobs - sob:=i; - fi; - GBNP.AddMonToTreePTSLR(ans[i][1],i,ansROT,false); - i:=i+1; - else - RemoveElmList(ans,i); - len:=len-1; - fi; + if GBNP.LookUpOccurTreePTSLRPos(ans[i][1],ansROT,false,1) = 0 then + if ans[i][5]=j then #selfobs + sob:=i; + fi; + GBNP.AddMonToTreePTSLR(ans[i][1],i,ansROT,false); + i:=i+1; + else + RemoveElmList(ans,i); + len:=len-1; + fi; od; return(rec(obs:=ans,sobnr:=sob)); @@ -1675,13 +1629,13 @@ end;; ### Zero polynomials are allowed. ### ### Arguments: -### - G the list of polynomials in NP form to check +### - G the list of polynomials in NP form to check ### ### #IsStrongGrobnerBasis uses: GBNP.IsGrobnerBasisTest# ### #IsStrongGrobnerBasis used in:# InstallGlobalFunction( IsStrongGrobnerBasis, function(G) - return GBNP.IsGrobnerBasisTest(G,true); + return GBNP.IsGrobnerBasisTest(G,true); end); ###################### @@ -1710,13 +1664,13 @@ end); ### Check whether a set of polynomials in NP form is a Gröbner basis. ### ### Arguments: -### - G the list of polynomials in NP form to check +### - G the list of polynomials in NP form to check ### ### #IsGrobnerBasis uses: GBNP.IsGrobnerBasisTest# ### #IsGrobnerBasis used in:# InstallGlobalFunction( IsGrobnerBasis, function(G) - return GBNP.IsGrobnerBasisTest(G,false); + return GBNP.IsGrobnerBasisTest(G,false); end); ############################### @@ -1749,9 +1703,9 @@ end); ### reduced by other polynomials in G. ### ### Arguments: -### - G the list of polynomials in NP form to check -### - strong boolean that indicates whether the test is for a "normal", -### ("reduced") or "reduced strong" Gröbner basis +### - G the list of polynomials in NP form to check +### - strong boolean that indicates whether the test is for a "normal", +### ("reduced") or "reduced strong" Gröbner basis ### ### Returns: ### @@ -1763,99 +1717,96 @@ end); # [[[]],[1]] (should be only one if strong=true, if strong=false the result is # true if 1 occurs) GBNP.IsGrobnerBasisTest:=function(G,strong) - local i, # counter - Gclean, # G cleaned - Gdouble,# polynomials of G with leading term the same as a - # leading term in Gdouble - Gsingle,# polynomials of G with all different leading terms - GsLOT, # occur tree for Gsingle - doubleObs,# obstructions from double terms - lt, # leading terms of Gclean - np, # polynomial of G in np form - one, # one of the field - pg, # number of prefix generators - pol, - f, - singleObs;# obstructions from double terms - - # make sure all polynomials in G are cleaned and non-zero - Gclean:=[]; - for i in [1..Length(G)] do - np:=CleanNP(G[i]); - if np<>[[],[]] then - Add(Gclean, MkMonicNP(np)); - fi; - od; - - if Length(Gclean)=0 then - # an empty set is a (trivial) Gröbner basis - return true; - fi; - - # set the one of the field - one:=One(Gclean[1][2][1]); - - # sort the cleaned G - Sort(Gclean, function(x,y) LtNP(x[1][1],y[1][1]); end); - # set the number of prefix generators - pg:=GBNP.CalculatePG(Gclean); - if pg > 0 then - pg:=0; # no prefix generators - else # pg < 0 : prefix generators (correct for negative index) - pg:=-pg; - fi; - - # store the list of leading terms in lt - lt:=LMonsNP(Gclean); - - # check if G can reduce itself - if strong then - GsLOT:=GBNP.CreateOccurTreePTSLR([],pg,true); - for i in [1..Length(Gclean)] do - pol:=Gclean[i]; - if AddNP(pol, - GBNP.StrongNormalFormTall(pol,Gclean,GsLOT, - rec(pg:=pg, strong:=true) - ), 1, -1 - )<>[[],[]] then - return false; - fi; - GBNP.AddMonToTreePTSLR(pol[1][1],i,GsLOT,true); - od; - - # TODO - else - # create a tree structure for fast strong normal form - # calculation - GsLOT:=GBNP.CreateOccurTreePTSLR([],pg,true); - - fi; - - doubleObs:=[]; - Gsingle:=[Gclean[1]]; - Gdouble:=[]; - for i in [2..Length(Gclean)] do - if lt[i]<>lt[i-1] then - # different leading term -> add to Gsingle - Add(Gsingle, Gclean[i]); - else # same leading term -> add to Gdouble - Add(Gdouble, Gclean[i]); - Add(doubleObs, AddNP(Gclean[i-1],Gclean[i],one,-one)); - fi; - od; - - # calculate all obstructions from Gsingle - singleObs:=GBNP.AllObs(Gsingle, rec(pg:=pg)); - - for pol in Concatenation(singleObs,doubleObs) do - # check if the obstruction reduces to zero - if GBNP.StrongNormalFormTall(pol,G,GsLOT,rec(pg:=pg)) <> [[],[]] then - # does not reduce to zero -> not a Gröbner basis - return false; - fi; - od; - - return true; + local i, # counter + Gclean, # G cleaned + Gdouble, # polynomials of G with leading term the same as a + # leading term in Gdouble + Gsingle, # polynomials of G with all different leading terms + GsLOT, # occur tree for Gsingle + doubleObs, # obstructions from double terms + lt, # leading terms of Gclean + np, # polynomial of G in np form + one, # one of the field + pg, # number of prefix generators + pol, + f, + singleObs; # obstructions from double terms + + # make sure all polynomials in G are cleaned and non-zero + Gclean:=[]; + for i in [1..Length(G)] do + np:=CleanNP(G[i]); + if np<>[[],[]] then + Add(Gclean, MkMonicNP(np)); + fi; + od; + + if Length(Gclean)=0 then + # an empty set is a (trivial) Gröbner basis + return true; + fi; + + # set the one of the field + one:=One(Gclean[1][2][1]); + + # sort the cleaned G + Sort(Gclean, function(x,y) LtNP(x[1][1],y[1][1]); end); + # set the number of prefix generators + pg:=GBNP.CalculatePG(Gclean); + if pg > 0 then + pg:=0; # no prefix generators + else # pg < 0 : prefix generators (correct for negative index) + pg:=-pg; + fi; + + # store the list of leading terms in lt + lt:=LMonsNP(Gclean); + + # check if G can reduce itself + if strong then + GsLOT:=GBNP.CreateOccurTreePTSLR([],pg,true); + for i in [1..Length(Gclean)] do + pol:=Gclean[i]; + if AddNP(pol,GBNP.StrongNormalFormTall(pol,Gclean,GsLOT, + rec(pg:=pg, strong:=true) ), 1, -1 ) <> [[],[]] then + return false; + fi; + GBNP.AddMonToTreePTSLR(pol[1][1],i,GsLOT,true); + od; + + # TODO + else + # create a tree structure for fast strong normal form + # calculation + GsLOT:=GBNP.CreateOccurTreePTSLR([],pg,true); + + fi; + + doubleObs:=[]; + Gsingle:=[Gclean[1]]; + Gdouble:=[]; + for i in [2..Length(Gclean)] do + if lt[i]<>lt[i-1] then + # different leading term -> add to Gsingle + Add(Gsingle, Gclean[i]); + else # same leading term -> add to Gdouble + Add(Gdouble, Gclean[i]); + Add(doubleObs, AddNP(Gclean[i-1],Gclean[i],one,-one)); + fi; + od; + + # calculate all obstructions from Gsingle + singleObs:=GBNP.AllObs(Gsingle, rec(pg:=pg)); + + for pol in Concatenation(singleObs,doubleObs) do + # check if the obstruction reduces to zero + if GBNP.StrongNormalFormTall(pol,G,GsLOT,rec(pg:=pg)) <> [[],[]] then + # does not reduce to zero -> not a Gröbner basis + return false; + fi; + od; + + return true; end; # special cases to check : @@ -1889,7 +1840,7 @@ end; ### ### Arguments: ### - G -### - D +### - D ### (G,D) is the Gröbner pair to be tested. ### ### Returns: @@ -1897,122 +1848,119 @@ end; ### InstallGlobalFunction( IsGrobnerPair, function(G,D) - local pol, # NP polynomial, counter - pol2, # NP polynomial - GLOT, # Left Occur Tree of G - DLOT, # Left Occur Tree of D - pg, # number of prefix generators - obs, # the set of obstructions - i, # counter - nonred; # number of polynomials which can not be proven to be reducible; - - # definition 10 from CohenGijsbersEtAl2007 - # 1) all polynomials are monic - # NOTE: what happens with zero polynomials ? - - for pol in Concatenation(G,D) do - if not (pol=MkMonicNP(CleanNP(pol))) then - # pol is not monic -> return false - Info(InfoGBNP, 1, "Condition 1 is not satisfied."); - Info(InfoGBNP, 2, "Not all polynomials are monic."); - return false; - elif (pol=[[],[]]) then - # zero polynomial is not monic either - Info(InfoGBNP, 1, "Condition 1 is not satisfied."); - Info(InfoGBNP, 2, "Not all polynomials are monic: zero polynomial found."); - return false; - fi; - od; - # NOTE: fixable by replacing a non monic polynomial by a monic one - - # 2) assume G \cup D is a basis for I (instead of just G) - - # 3) i every element of D belongs to I (because of modified 2) - # hard to do otherwise (without calculating a GB from G) - # ii check if every element of D is in reduced form wrt G (note: not - # strong reduced) - - pg:=GBNP.CalculatePG(G); - GLOT:=GBNP.CreateOccurTreePTSLR( LMonsNP(G), pg, true); - - for i in [1.. Length(D)] do - pol:=D[i]; - - # zero polynomials are in already normal form - if (pol <> [[],[]]) then - # just check leading terms: - if GBNP.OccurInLstPTSLR(pol[1][1], GLOT, true)[1]<>0 - then - Info(InfoGBNP, 1, "Condition 3 is not satisfied."); - Info(InfoGBNP, 2, "Not all polynomials in D are in normal form with respect to G (index: ",i,")"); - # pol is not in normal form -> return false - Info(InfoGBNP, 3, 1/0); - return false; - fi; - fi; - od; - # NOTE: fixable by replacing each element by its normal form - - # 4) the set of D is basic for G - # for each non-weak obstruction of G, check that it is reducible by - # G \cup D - obs := GBNP.AllObs(G,rec(pg:=pg, strong:=true)); - for i in [1..Length(obs)] do - obs[i] := GBNP.StrongNormalFormTall(obs[i], G, GLOT, - rec(pg:=pg, strong:=true) - ); - - od; - DLOT:=GBNP.CreateOccurTreePTSLR( LMonsNP(D), pg, true); - - nonred:=0; - for pol in obs do - if GBNP.StrongNormalForm2Tall(pol,G,D, rec(GL:=GLOT, - todoL:=DLOT), rec(pg:=pg, strong:=true) - )<>[[],[]] then - # pol is not in normal form -> return false - nonred:=nonred+1; - fi; - od; - if (nonred>0) then - Info(InfoGBNP, 1, "Condition 4 is not satisfied."); - Info(InfoGBNP, 2, "D is not basic for G for ",nonred,"/", - Length(D), " polynomials"); - return false; - fi; - - # NOTE: fixable by adding the new normal form to D - - return true; + local pol, # NP polynomial, counter + pol2, # NP polynomial + GLOT, # Left Occur Tree of G + DLOT, # Left Occur Tree of D + pg, # number of prefix generators + obs, # the set of obstructions + i, # counter + nonred; # number of polynomials which can not be proven to be reducible; + + # definition 10 from CohenGijsbersEtAl2007 + # 1) all polynomials are monic + # NOTE: what happens with zero polynomials ? + + for pol in Concatenation(G,D) do + if not (pol=MkMonicNP(CleanNP(pol))) then + # pol is not monic -> return false + Info(InfoGBNP, 1, "Condition 1 is not satisfied."); + Info(InfoGBNP, 2, "Not all polynomials are monic."); + return false; + elif (pol=[[],[]]) then + # zero polynomial is not monic either + Info(InfoGBNP, 1, "Condition 1 is not satisfied."); + Info(InfoGBNP, 2, "Not all polynomials are monic: zero polynomial found."); + return false; + fi; + od; + # NOTE: fixable by replacing a non monic polynomial by a monic one + + # 2) assume G \cup D is a basis for I (instead of just G) + + # 3) i every element of D belongs to I (because of modified 2) + # hard to do otherwise (without calculating a GB from G) + # ii check if every element of D is in reduced form wrt G (note: not + # strong reduced) + + pg:=GBNP.CalculatePG(G); + GLOT:=GBNP.CreateOccurTreePTSLR( LMonsNP(G), pg, true); + + for i in [1.. Length(D)] do + pol:=D[i]; + + # zero polynomials are in already normal form + if (pol <> [[],[]]) then + # just check leading terms: + if GBNP.OccurInLstPTSLR(pol[1][1], GLOT, true)[1]<>0 + then + Info(InfoGBNP, 1, "Condition 3 is not satisfied."); + Info(InfoGBNP, 2, "Not all polynomials in D are in normal form with respect to G (index: ",i,")"); + # pol is not in normal form -> return false + Info(InfoGBNP, 3, 1/0); + return false; + fi; + fi; + od; + # NOTE: fixable by replacing each element by its normal form + + # 4) the set of D is basic for G + # for each non-weak obstruction of G, check that it is reducible by + # G \cup D + obs := GBNP.AllObs(G,rec(pg:=pg, strong:=true)); + for i in [1..Length(obs)] do + obs[i] := GBNP.StrongNormalFormTall(obs[i], G, GLOT, + rec(pg:=pg, strong:=true) ); + od; + DLOT:=GBNP.CreateOccurTreePTSLR( LMonsNP(D), pg, true); + + nonred:=0; + for pol in obs do + if GBNP.StrongNormalForm2Tall(pol,G,D, rec(GL:=GLOT, + todoL:=DLOT), rec(pg:=pg, strong:=true) ) <> [[],[]] then + # pol is not in normal form -> return false + nonred:=nonred+1; + fi; + od; + if (nonred>0) then + Info(InfoGBNP, 1, "Condition 4 is not satisfied."); + Info(InfoGBNP, 2, "D is not basic for G for ",nonred,"/", + Length(D), " polynomials"); + return false; + fi; + + # NOTE: fixable by adding the new normal form to D + + return true; end); # function to check if monimials are monic and clean and/or make them so GBNP.MakeGrobnerPairMakeMonic:=function(G) - local i, # counter - pol, # polynomial being checked - pol2, # monic version of pol - monic, # true if all polynomials (so far) were already monic - newG; # G made monic - - monic:=true; - newG := ShallowCopy(G); - for i in [1..Length(newG)] do - pol := newG[i]; - pol2 := MkMonicNP(CleanNP(pol)); - if not (pol = pol2) then - # update newG[i] - monic:=false; - newG[i]:=pol2; - elif pol = [[],[]] then - # zero NP polynomial - monic:=false; - fi; - od; - if (not monic) then - Info(InfoGBNP, 2, "Condition 1 was not satisfied (fixed)."); - Info(InfoGBNP, 3, "Not all polynomials were monic."); - fi; - return Filtered(newG,x -> x <> [[],[]]); + local i, # counter + pol, # polynomial being checked + pol2, # monic version of pol + monic, # true if all polynomials (so far) were already monic + newG; # G made monic + + monic:=true; + newG := ShallowCopy(G); + for i in [1..Length(newG)] do + pol := newG[i]; + pol2 := MkMonicNP(CleanNP(pol)); + if not (pol = pol2) then + # update newG[i] + monic:=false; + newG[i]:=pol2; + elif pol = [[],[]] then + # zero NP polynomial + monic:=false; + fi; + od; + if (not monic) then + Info(InfoGBNP, 2, "Condition 1 was not satisfied (fixed)."); + Info(InfoGBNP, 3, "Not all polynomials were monic."); + fi; + return Filtered(newG,x -> x <> [[],[]]); end; ####################### @@ -2048,97 +1996,96 @@ end; ### InstallGlobalFunction( MakeGrobnerPair, function(G,D) - local pol, # NP polynomial, counter - pol2, # NP polynomial - GLOT, # Left Occur Tree of G - DLOT, # Left Occur Tree of D - newG, - newD, - pg, # number of prefix generators - obs, # the set of obstructions - i, # counter - fixed ; # number of polynomials which has been fixed - - # definition 10 from CohenGijsbersEtAl2007 - # 1) all polynomials are monic - # NOTE: what happens with zero polynomials ? - # NOTE: it is ok to consider them monic (but MkMonic might need - # adjustment) - - newG:=GBNP.MakeGrobnerPairMakeMonic(G); - newD:=GBNP.MakeGrobnerPairMakeMonic(D); - - # NOTE: fixable by replacing a non monic polynomial by a monic one - - # 2) assume G \cup D is a basis for I (instead of just G) - - # 3) i every element of D belongs to I (because of modified 2) - # hard to do otherwise (without calculating a GB from G) - # ii check if every element of D is in reduced form wrt G (note: not - # strong reduced) - - pg:=GBNP.CalculatePG(newG); - GLOT:=GBNP.CreateOccurTreePTSLR( LMonsNP(newG), pg, true); - fixed:=0; - - for i in [1.. Length(newD)] do - pol:=newD[i]; - - # zero polynomials are in already normal form - if (pol <> [[],[]]) then - # just check leading terms: - if GBNP.OccurInLstPTSLR(pol[1][1], GLOT, true)[1]<>0 - then - fixed:=fixed+1; - newD[i]:=GBNP.StrongNormalFormTall( - newD[i], newG, GLOT, - rec(pg:=pg, strong:=true) - ); - fi; - fi; - od; - - if (fixed >0) then - Info(InfoGBNP, 2, "Condition 3 was not satisfied (fixed)."); - Info(InfoGBNP, 3, "Not all polynomials in D were in normal form with respect to G."); - fi; - # NOTE: fixable by replacing each element by its normal form - - # 4) the set of D is basic for G - # for each non-weak obstruction of G, check that it is reducible by - # G \cup D - obs := GBNP.AllObs(newG,rec(pg:=pg, strong:=true)); - for i in [1..Length(obs)] do - obs[i] := GBNP.StrongNormalFormTall(obs[i], newG, GLOT, - rec(pg:=pg, strong:=true) - ); - - od; - DLOT:=GBNP.CreateOccurTreePTSLR( LMonsNP(newD), pg, true); - - fixed:=0; - for i in [1..Length(obs)] do - pol:=obs[i]; - pol2:=GBNP.StrongNormalForm2Tall(pol,newG,newD, rec(GL:=GLOT, - todoL:=DLOT), rec(pg:=pg, strong:=true)); - - if pol2<>[[],[]] then - # pol is not in normal form -> add false - fixed:=fixed+1; - Add(newD,pol2); - GBNP.AddMonToTreePTSLR(pol2[1][1],-1,DLOT,true); - fi; - od; - if (fixed>0) then - Info(InfoGBNP, 1, "Condition 4 was not satisfied. ", - "(fixed)"); - Info(InfoGBNP, 2, "D was not basic for G for ",fixed, - "/", Length(newD), " polynomials"); - fi; - - # NOTE: fixable by adding the new normal form to D - - return rec(G:=newG,todo:=newD); + local pol, # NP polynomial, counter + pol2, # NP polynomial + GLOT, # Left Occur Tree of G + DLOT, # Left Occur Tree of D + newG, + newD, + pg, # number of prefix generators + obs, # the set of obstructions + i, # counter + fixed; # number of polynomials which has been fixed + + # definition 10 from CohenGijsbersEtAl2007 + # 1) all polynomials are monic + # NOTE: what happens with zero polynomials ? + # NOTE: it is ok to consider them monic (but MkMonic might need + # adjustment) + + newG:=GBNP.MakeGrobnerPairMakeMonic(G); + newD:=GBNP.MakeGrobnerPairMakeMonic(D); + + # NOTE: fixable by replacing a non monic polynomial by a monic one + + # 2) assume G \cup D is a basis for I (instead of just G) + + # 3) i every element of D belongs to I (because of modified 2) + # hard to do otherwise (without calculating a GB from G) + # ii check if every element of D is in reduced form wrt G (note: not + # strong reduced) + + pg:=GBNP.CalculatePG(newG); + GLOT:=GBNP.CreateOccurTreePTSLR( LMonsNP(newG), pg, true); + fixed:=0; + + for i in [1.. Length(newD)] do + pol:=newD[i]; + + # zero polynomials are in already normal form + if (pol <> [[],[]]) then + # just check leading terms: + if GBNP.OccurInLstPTSLR(pol[1][1], GLOT, true)[1]<>0 + then + fixed:=fixed+1; + newD[i]:=GBNP.StrongNormalFormTall( + newD[i], newG, GLOT, + rec(pg:=pg, strong:=true) + ); + fi; + fi; + od; + + if (fixed >0) then + Info(InfoGBNP, 2, "Condition 3 was not satisfied (fixed)."); + Info(InfoGBNP, 3, "Not all polynomials in D were in normal form with respect to G."); + fi; + # NOTE: fixable by replacing each element by its normal form + + # 4) the set of D is basic for G + # for each non-weak obstruction of G, check that it is reducible by + # G \cup D + obs := GBNP.AllObs(newG,rec(pg:=pg, strong:=true)); + for i in [1..Length(obs)] do + obs[i] := GBNP.StrongNormalFormTall(obs[i], newG, GLOT, + rec(pg:=pg, strong:=true) + ); + + od; + DLOT:=GBNP.CreateOccurTreePTSLR( LMonsNP(newD), pg, true); + + fixed:=0; + for i in [1..Length(obs)] do + pol:=obs[i]; + pol2:=GBNP.StrongNormalForm2Tall(pol,newG,newD, rec(GL:=GLOT, + todoL:=DLOT), rec(pg:=pg, strong:=true)); + + if pol2<>[[],[]] then + # pol is not in normal form -> add false + fixed:=fixed+1; + Add(newD,pol2); + GBNP.AddMonToTreePTSLR(pol2[1][1],-1,DLOT,true); + fi; + od; + if (fixed>0) then + Info(InfoGBNP, 1, "Condition 4 was not satisfied. ","(fixed)"); + Info(InfoGBNP, 2, "D was not basic for G for ",fixed, + "/", Length(newD), " polynomials"); + fi; + + # NOTE: fixable by adding the new normal form to D + + return rec(G:=newG,todo:=newD); end); ########################### @@ -2180,23 +2127,23 @@ end); ### - polynomial f is clean. ### ### Arguments: -### f - a non-commutative polynomial -### G - list of non-commutative polynomials +### f - a non-commutative polynomial +### G - list of non-commutative polynomials ### ### Returns: -### pol - strong normalform of f w.r.t. G +### pol - strong normalform of f w.r.t. G ### ### #StrongNormalFormNPM uses: GBNP.StrongNormalForm2# ### #StrongNormalFormNPM is used in: MulQM# ### InstallGlobalFunction( StrongNormalFormNPM, function(v,GR) - if v=[[],[]] then - return v; - else - # GBNP.StrongNormalForm2 can be used for this - return GBNP.StrongNormalForm2(v,GR.p,GR.ts); - fi; + if v=[[],[]] then + return v; + else + # GBNP.StrongNormalForm2 can be used for this + return GBNP.StrongNormalForm2(v,GR.p,GR.ts); + fi; end); ###################### @@ -2274,18 +2221,18 @@ InstallGlobalFunction( SGrobnerModule, function(KI_p,KI_ts) # XXX check for module generators G:=Filtered(KI_p,x->x<>[[],[]]); - + if Length(G)>0 and ((not IsBound(G[1][1][1][1])) or G[1][1][1][1]>0) then - G:=List(G,x->MulNP([[[-1]],[One(G[1][2][1])]], x)); + G:=List(G,x->MulNP([[[-1]],[One(G[1][2][1])]], x)); fi; # XXX should be calculated with pg=0 - # setting pg after SGrobner is a workaround when calling this function the - # first time, real solution should be verifying if the calculated pg of - # KI_ts is zero and storing the old pg value temporarily + # setting pg after SGrobner is a workaround when calling this function + # the first time, real solution should be verifying if the calculated pg + # of KI_ts is zero and storing the old pg value temporarily if GBNP.GetOptions().pg=0 then - GBNP.SetOption("pg",GBNP.CalculatePG(G)); + GBNP.SetOption("pg",GBNP.CalculatePG(G)); fi; # store pg value temporarily in the temp variable @@ -2338,30 +2285,30 @@ end);; ### <#/GAPDoc> ### ### Arguments: -### GBR - a Grobner basis +### GBR - a Grobner basis ### p1, p2 - two polynomials ### ### Returns: -### ans - the strong normal form of the product p1*p2 with +### ans - the strong normal form of the product p1*p2 with ### respect to GBR ### -### uses: - MulNP, StrongNormalFormNPM +### uses: - MulNP, StrongNormalFormNPM ### #MulQM uses: MulNP StrongNormalFormNPM# ### #MulQM is used in: MatrixQA# ### InstallGlobalFunction( MulQM, function(p1,p2,GBR) - if (Length(p2[1])=0) then - # the second argument is zero - return [[],[]]; - elif ((Length(p2[1][1])>0) and (p2[1][1][1]<0)) then - # the second argument is a module element (which is invalid) - Print("ERROR: Right multiplication should be with an element from the algebra.\n"); - return fail; - else - return StrongNormalFormNPM(MulNP(p1,p2),GBR); - fi; + if (Length(p2[1])=0) then + # the second argument is zero + return [[],[]]; + elif ((Length(p2[1][1])>0) and (p2[1][1][1]<0)) then + # the second argument is a module element (which is invalid) + Print("ERROR: Right multiplication should be with an element from the algebra.\n"); + return fail; + else + return StrongNormalFormNPM(MulNP(p1,p2),GBR); + fi; end);; ################# @@ -2420,13 +2367,13 @@ end);; ### ### returns a basis of terms ### Arguments: -### GBR - a Grobner basis -### t - number of elements in the alphabet -### mt - number of generators of the module -### maxno - maximum number of terms to be found +### GBR - a Grobner basis +### t - number of elements in the alphabet +### mt - number of generators of the module +### maxno - maximum number of terms to be found ### ### Returns: -### ans - List of terms forming a basis of QA = NP algebra mod G +### ans - List of terms forming a basis of QA = NP algebra mod G ### ### #BaseQM uses: GBNP.NondivMonsPTS LMonsNP# ### #BaseQM is used in:# @@ -2438,37 +2385,39 @@ InstallGlobalFunction( BaseQM, function(GBR,t,mt,maxno) t := Maximum(NumAlgGensNPList(GBR.ts), NumAlgGensNPList(GBR.p)); fi; - if mt = 0 then mn := GBR.pg; - else mn := mt; + if mt = 0 then + mn := GBR.pg; + else + mn := mt; fi; if Length(GBR.p)>0 then - if Length(GBR.p[1][2])=0 then - return []; - fi; - one:=One(GBR.p[1][2][1]); + if Length(GBR.p[1][2])=0 then + return []; + fi; + one:=One(GBR.p[1][2][1]); elif Length(GBR.ts)>0 then - if Length(GBR.ts[1][2])=0 then - return []; - fi; - one:=One(GBR.ts[1][2][1]); + if Length(GBR.ts[1][2])=0 then + return []; + fi; + one:=One(GBR.ts[1][2][1]); elif t>0 then - # trivial infinite basis - return "infinite"; + # trivial infinite basis + return "infinite"; fi; - + # amc probeert met 4 args te werken: # oude versie: # hlst := GBNP.NondivMonsPTS(LMonsNP(GBR.p),LMonsNP(GBR.ts),t,GBR.pg,maxno); # nieuwe versie: - hlst := GBNP.NondivMonsPTS(LMonsNP(GBR.p),LMonsNP(GBR.ts),t,mn,maxno); - ans := []; - for i in [1..Length(hlst)] do - for h in hlst[i] do - Add(ans,[[h],[one]]); - od; - od; - return ans; + hlst := GBNP.NondivMonsPTS(LMonsNP(GBR.p),LMonsNP(GBR.ts),t,mn,maxno); + ans := []; + for i in [1..Length(hlst)] do + for h in hlst[i] do + Add(ans,[[h],[one]]); + od; + od; + return ans; end);; ################ @@ -2510,31 +2459,33 @@ end);; ### ### <#/GAPDoc> ### Arguments: -### GBR - a Grobner basis record +### GBR - a Grobner basis record ### n - the number of variables ### mn - the number of elements in the module alphabet ### ### Returns: -### s - the dimension of the quotient algebra +### s - the dimension of the quotient algebra ### ### #DimQM uses: GBNP.NondivMonsPTSenum LMonsNP# ### #DimQM is used in:# ### InstallGlobalFunction( DimQM, function(GBR,n,mt) - local s,t0, mn; - t0 := Runtime(); - if n = 0 then - n := Maximum(NumAlgGensNPList(GBR.ts), NumAlgGensNPList(GBR.p)); - fi; - if mt = 0 then mn := GBR.pg; - Info(InfoGBNP,2,"number of prefix generators set to ",mn); - else mn := mt; - fi; - if Length(GBR.ts) = 0 and Length(GBR.p)=0 then - Error("dim is infinite as ideal is trivial.\n"); - fi; - s := GBNP.NondivMonsPTSenum(LMonsNP(GBR.p),LMonsNP(GBR.ts),n,mn,0); - Info(InfoGBNPTime,2,"The computation took ",Runtime()-t0," msecs."); - return s; + local s,t0, mn; + t0 := Runtime(); + if n = 0 then + n := Maximum(NumAlgGensNPList(GBR.ts), NumAlgGensNPList(GBR.p)); + fi; + if mt = 0 then + mn := GBR.pg; + Info(InfoGBNP,2,"number of prefix generators set to ",mn); + else + mn := mt; + fi; + if Length(GBR.ts) = 0 and Length(GBR.p)=0 then + Error("dim is infinite as ideal is trivial.\n"); + fi; + s := GBNP.NondivMonsPTSenum(LMonsNP(GBR.p),LMonsNP(GBR.ts),n,mn,0); + Info(InfoGBNPTime,2,"The computation took ",Runtime()-t0," msecs."); + return s; end);; From f465afeb9c1be45994542bb304575b629bcf9ef9 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jul 2024 15:26:45 +0200 Subject: [PATCH 12/13] Apply suggestions from code review --- lib/grobner.gi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/grobner.gi b/lib/grobner.gi index 825aebf..54ce7c6 100644 --- a/lib/grobner.gi +++ b/lib/grobner.gi @@ -82,7 +82,7 @@ GBNP.RightOccur:=function(u,v) local lu,lv; if u = v then - return(1); + return 1; fi; if LtNP(u,v) then lu:=Length(u); @@ -115,7 +115,7 @@ end;; GBNP.LeftOccur:=function(u,v) local lu; if u = v then - return(1); + return 1; fi; if LtNP(u,v) then lu:=Length(u); @@ -147,7 +147,7 @@ end;; GBNP.Occur:=function(u,v) local i,lu,p; if u = v then - return(1); + return 1; fi; if LtNP(u,v) then lu:=Length(u); @@ -220,7 +220,7 @@ GBNP.OccurInLst:=function(u,Rlst) local i,j,lr; j:= GBNP.Occur(Rlst[i],u); #j:= PositionSublist(u,Rlst[i]); if j>0 then - return([i,j]); + return [i,j]; fi; #if j<>fail then return([i,j]); fi; od; @@ -528,7 +528,7 @@ GBNP.StrongNormalForm2:=function(f,G,G2) dr:=lth{[i1[2]+Length(g[1][1])..Length(lth)]}; h:=AddNP(h,BimulNP(ga,g,dr),One(g[2][1]),-h[2][iid]/g[2][1]); if h=[[],[]] then - return(h); + return h; fi; if iid <= Length(h[1]) then lth := h[1][iid]; From a26373f83044563858133cbdd6e4c6fd202d0381 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jul 2024 15:28:23 +0200 Subject: [PATCH 13/13] Apply suggestions from code review --- lib/grobner.gi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/grobner.gi b/lib/grobner.gi index 54ce7c6..2ae5cca 100644 --- a/lib/grobner.gi +++ b/lib/grobner.gi @@ -543,7 +543,7 @@ GBNP.StrongNormalForm2:=function(f,G,G2) dr:=lth{[i2[2]+Length(g[1][1])..Length(lth)]}; h:=AddNP(h,BimulNP(ga,g,dr),One(g[2][1]),-h[2][iid]/g[2][1]); if h=[[],[]] then - return(h); + return h; fi; if iid <= Length(h[1]) then lth := h[1][iid]; @@ -755,7 +755,7 @@ GBNP.ReducePol:=function(B) fi; od; GBNP.ReducePol2(G); - return(G); + return G; end;; ################### @@ -1334,7 +1334,7 @@ GBNP.StrongNormalForm2TS:=function(G,j,GLOT) dr:=lth{[i1[2]+Length(g[1][1])..Length(lth)]}; h:=AddNP(h,BimulNP(ga,g,dr),One(g[2][1]),-h[2][iid]/g[2][1]); if h=[[],[]] then - return(h); + return h; fi; if iid <= Length(h[1]) then lth := h[1][iid];