From 1938ac9f6442b10460d2560f9e9323200f509f06 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Thu, 4 Jul 2024 16:48:25 +0100 Subject: [PATCH] added LMonNP, LTermNP, LTermsNP; FactorOutGcdNP (#32) --- doc/examples/functions.g | 43 ++++++++- doc/examples/functions.xml | 52 ++++++++++- doc/gbnp_doc.xml | 2 + lib/nparith.gd | 4 + lib/nparith.gi | 186 ++++++++++++++++++++++++++++++------- tst/functions.tst | 48 +++++++++- tst/test-bound-03.tst | 4 +- 7 files changed, 297 insertions(+), 42 deletions(-) diff --git a/doc/examples/functions.g b/doc/examples/functions.g index 1d19a73..1880c87 100644 --- a/doc/examples/functions.g +++ b/doc/examples/functions.g @@ -471,6 +471,26 @@ PrintNPList(List(LMonsNP(Lnp), q -> [[q],[1]])); # <#/GAPDoc> +# <#GAPDoc Label="example-LTermNP"> +# Example: +# We put two polynomials in NP format into the list Lnp. +# +p1 := [[[1,1,2],[1]],[6,-7]];; +p2 := [[[1,2,2],[2]],[8,-9]];; +Lnp := [p1,p2];; +# + +# The leading term of a polynomial is returned by LTermNP, +# and the list of leading terms is computed by LTermsNP: + +# +LTermNP(p1); +LTnp := LTermsNP( Lnp ); +PrintNPList( LTnp ); +# + +# <#/GAPDoc> + # <#GAPDoc Label="example-MkMonicNP"> # Example: # Consider the following polynomial in NP format. @@ -479,13 +499,30 @@ p := [[[1,1,2],[]],[2,-1]];; PrintNP(p); # -# The coefficient of the leading term is 2. The function MkMonicNP finds -# this coefficient and divides all terms by it: - +# The coefficient of the leading term is 2. +# The function MkMonicNP finds this coefficient +# and divides every term by it: # PrintNP(MkMonicNP(p)); # +# <#/GAPDoc> +# <#GAPDoc Label="example-FactorOutGcdNP"> +# Example: +# Consider the following polynomial in NP format. +# +p := [[[1,1,2],[1,2],[1]],[30,70,105]];; +PrintNP(p); +# + +# The Gcd of the coefficients [30,70,105] is 5. +# The function FactorOutGcdNP divides the polynomial by 5: + +# +PrintNP(FactorOutGcdNP(p)); +m := MkMonicNP(p); +# +fm := FactorOutGcdNP(m); # <#/GAPDoc> diff --git a/doc/examples/functions.xml b/doc/examples/functions.xml index 41159f8..229b927 100644 --- a/doc/examples/functions.xml +++ b/doc/examples/functions.xml @@ -520,6 +520,30 @@ gap> PrintNPList(List(LMonsNP(Lnp), q -> [[q],[1]])); <#/GAPDoc> +<#GAPDoc Label="example-LTermNP"> +Example: +We put two polynomials in NP format into the list Lnp. + p1 := [[[1,1,2],[1]],[6,-7]];; +gap> p2 := [[[1,2,2],[2]],[8,-9]];; +gap> Lnp := [p1,p2];; +]]> + +The leading term of a polynomial is returned by LTermNP, +and the list of leading terms is computed by LTermsNP: + + LTermNP(p1); +[ [ 1, 1, 2 ], [ 6 ] ] +gap> LTnp := LTermsNP( Lnp ); +[ [ [ [ 1, 1, 2 ] ], [ 6 ] ], [ [ [ 1, 2, 2 ] ], [ 8 ] ] ] +gap> PrintNPList( LTnp ); +6a^2b +8ab^2 +]]> + +<#/GAPDoc> + <#GAPDoc Label="example-MkMonicNP"> Example: Consider the following polynomial in NP format. @@ -529,8 +553,9 @@ gap> PrintNP(p); 2a^2b - 1 ]]> -The coefficient of the leading term is 2. The function MkMonicNP finds -this coefficient and divides all terms by it: +The coefficient of the leading term is 2. +The function MkMonicNP finds this coefficient +and divides every term by it: PrintNP(MkMonicNP(p)); @@ -539,6 +564,29 @@ gap> PrintNP(MkMonicNP(p)); <#/GAPDoc> +<#GAPDoc Label="example-FactorOutGcdNP"> +Example: +Consider the following polynomial in NP format. + p := [[[1,1,2],[1,2],[1]],[30,70,105]];; +gap> PrintNP(p); + 30a^2b + 70ab + 105a +]]> + +The Gcd of the coefficients [30,70,105] is 5. +The function FactorOutGcdNP divides the polynomial by 5: + + PrintNP(FactorOutGcdNP(p)); + 6a^2b + 14ab + 21a +gap> m := MkMonicNP(p); +[ [ [ 1, 1, 2 ], [ 1, 2 ], [ 1 ] ], [ 1, 7/3, 7/2 ] ] +gap> fm := FactorOutGcdNP(m); +fail +]]> + +<#/GAPDoc> + <#GAPDoc Label="example-MulNP"> Example: diff --git a/doc/gbnp_doc.xml b/doc/gbnp_doc.xml index c5ade93..605db73 100644 --- a/doc/gbnp_doc.xml +++ b/doc/gbnp_doc.xml @@ -536,7 +536,9 @@ algebra with the same growth). <#Include Label="GtNP"> <#Include Label="LtNP"> <#Include Label="LMonsNP"> + <#Include Label="LTermsNP"> <#Include Label="MkMonicNP"> + <#Include Label="FactorOutGcdNP"> <#Include Label="MulNP">
Gröbner functions, standard variant diff --git a/lib/nparith.gd b/lib/nparith.gd index a4512f1..e8be017 100644 --- a/lib/nparith.gd +++ b/lib/nparith.gd @@ -25,9 +25,13 @@ DeclareGlobalFunction("LtNP"); DeclareGlobalFunction("GtNP"); +DeclareGlobalFunction("LMonNP"); DeclareGlobalFunction("LMonsNP"); +DeclareGlobalFunction("LTermNP"); +DeclareGlobalFunction("LTermsNP"); DeclareGlobalFunction("CleanNP"); DeclareGlobalFunction("MkMonicNP"); +DeclareGlobalFunction("FactorOutGcdNP"); DeclareGlobalFunction("AddNP"); DeclareGlobalFunction("MulNP"); DeclareGlobalFunction("BimulNP"); diff --git a/lib/nparith.gi b/lib/nparith.gi index cc61027..d497efc 100644 --- a/lib/nparith.gi +++ b/lib/nparith.gi @@ -19,15 +19,21 @@ ### filename = "nparith.gi" ### vs 0.9 +### (04/09/23) added LMonNP, LTermNP and LTermsNP +### (21/09/23) added FactorOutGcdNP ### THIS IS PART OF A GAP PACKAGE FOR COMPUTING WITH NON-COMMUTATIVE POLYNOMIALS #AddNP:=function(u,v,c,d) local ans,hlp; -> now in nparith3.gi #LtNP:=function(u,v) #GtNP:=function(u,v) -#LMonsNP:=function(pol) local i; +#LMonNP:=function(pol) +#LMonsNP:=function(lst) +#LTermNP:=function(pol) +#LTermsNP:=function(lst) #CleanNP:=function(pol) local i,h,l,v,mons,polh,coeffs,ansmons,anscoeffs; #MkMonicNP:=function(pol) +#FactorOutGcdNP:=function(pol) #BimulNP:=function(ga,u,dr) local i,ans; #MulNP:=function(u,v) local ans,i,j; #GBNP.LTermsTrace:=function(pol) local i; @@ -72,14 +78,9 @@ ### #AddNP is used in: EvalTrace GBNP.GP2NPM GBNP.IsGrobnerBasisTest GBNP.NormalForm2 GBNP.NormalForm2T GBNP.Spoly GBNP.SpolyTrace GBNP.StrongNormalForm2 GBNP.StrongNormalForm2TS GBNP.StrongNormalForm2TSPTS GBNP.StrongNormalForm2Tall GBNP.StrongNormalForm3Dall GBNP.StrongNormalFormTrace2 GBNP.TraceNP StrongNormalFormTraceDiff# ### -InstallGlobalFunction( -AddNP,function(u,v,c,d) -local lans,ans, - posu,posv,posans, - ulen,vlen,co; - +InstallGlobalFunction( AddNP, function(u,v,c,d) + local lans,ans,posu,posv,posans,ulen,vlen,co; ans:=[[],[]]; - # don't add the polynomial if the coefficient is zero if IsZero(c) then u:=[[],[]]; @@ -204,40 +205,43 @@ end);; ### #GtNP is used in:# ### -InstallGlobalFunction( -GtNP,function(u,v) +InstallGlobalFunction( GtNP, function(u,v) if Length(u)>Length(v) then return(true); elif Length(u)=Length(v) then return(u>v); - else return(false); + else + return(false); fi; end);; ################## -### LMonsNP +### LMonNP and LMonsNP ### ### <#GAPDoc Label="LMonsNP"> ### +### ### ### ### -### A list of leading monomials +### The leading monomial or a list of leading monomials. ### ### ### -### This function returns the leading monomials of a list Lnp -### of polynomials in NP format. The polynomials of Lnp are required to -### be clean; see Section . +### These functions return the leading monomial of a polynomial +### (resp. the leading monomials of a list of polynomials) in NP format. +### The polynomials of Lnp are required to be clean; +### see Section . ###

### <#Include Label="example-LMonsNP"> ### ### ### <#/GAPDoc> ### -### - Returns the leading monomials of a list of Noncommutative Polynomials. -### The polynomials are not zero and ordered such that -### the leading monomial comes first. +### - Returns the leading monomial(s) of a (list of) +### Noncommutative Polynomials. +### The polynomials are ordered such that the leading monomial comes first. +### If the zero polynomial is given as argument then 'fail' is returned. ### ### Arguments: ### pol - list of Noncommutative Polynomials @@ -249,11 +253,75 @@ end);; ### #LMonsNP is used in: BaseQA BaseQM DimQA DimQM GBNP.AllObs GBNP.AllObsTrunc GBNP.CentralT GBNP.CheckHom GBNP.IsGrobnerBasisTest GBNP.NormalForm2 GBNP.ObsTall GBNP.ObsTrunc GBNP.ReducePol2 GBNP.SGrobnerLoops GBNP.SGrobnerTrunc GBNP.StrongNormalForm2 IsGrobnerPair MakeGrobnerPair THeapOT# ### -InstallGlobalFunction( -LMonsNP,function(pol) local i; - return(List(pol,i->i[1][1])); +InstallGlobalFunction( LMonNP, function(pol) + if IsZero(pol) then + return fail; + else + return pol[1][1]; + fi; +end); + +InstallGlobalFunction(LMonsNP, lst -> List(lst,LMonNP)); + +################## +### LTermNP and LTermsNP +### +### <#GAPDoc Label="LTermsNP"> +### +### +### +### +### +### The leading term or a list of leading terms. +### +### +### +### These functions return the leading term of a polynomial +### (resp. the leading terms of a list of polynomials) in NP format. +### The polynomials of Lnp are required to be clean; +### see Section . +###

+### +### +### +### gap> p1 := [[[1,1,2],[1]],[6,-7]];; +### gap> p2 := [[[1,2,2],[2]],[8,-9]];; +### gap> Lnp := [p1,p2];; +### gap> LTermNP( p1 ); +### [ [ [ 1, 1, 2 ] ], [ 6 ] ] +### gap> LTnp := LTermsNP( Lnp ); +### [ [ [ [ 1, 1, 2 ] ], [ 6 ] ], [ [ [ 1, 2, 2 ] ], [ 8 ] ] ] +### gap> PrintNPList( LTnp ); +### 6a^2b +### 8ab^2 +### +### <#/GAPDoc> +### +### - Returns the leading term(s) of a (list of) +### Noncommutative Polynomials. +### The polynomials are ordered such that the leading monomial comes first. +### If the zero polynomial is given as argument then 'fail' is returned. +### +### Arguments: +### pol - list of Noncommutative Polynomials +### +### Returns: +### - a list of leading monomials +### +### #LTermNP uses:# +### #LTermNP is used in:# +### + +InstallGlobalFunction( LTermNP, function(pol) + if IsZero(pol) then + return fail; + else + return [ [ pol[1][1] ], [ pol[2][1] ] ]; + fi; end); +InstallGlobalFunction(LTermsNP, lst -> List(lst,LTermNP)); + ################## ### CleanNP ### <#GAPDoc Label="CleanNP"> @@ -284,8 +352,8 @@ end); ### #CleanNP is used in: CheckHomogeneousNPs EvalTrace GBNP.GP2NPM GBNP.IsGrobnerBasisTest GBNP.MakeGrobnerPairMakeMonic GBNP.NPArray2NPM GBNP.ReducePol GBNP.ReducePolTrace GP2NP IsGrobnerPair MulNP StrongNormalFormNP# ### -InstallGlobalFunction( -CleanNP,function(pol) local i,h,l,v,mons,polh,coeffs,ansmons,anscoeffs; +InstallGlobalFunction( CleanNP, function(pol) + local i,h,l,v,mons,polh,coeffs,ansmons,anscoeffs; polh:=StructuralCopy(pol); SortParallel(polh[1],polh[2],GtNP); mons:=polh[1]; @@ -344,13 +412,65 @@ end);; ### #MkMonicNP is used in: GBNP.CentralT GBNP.IsGrobnerBasisTest GBNP.MakeGrobnerPairMakeMonic GBNP.ObsTall GBNP.ObsTrunc GBNP.ReducePol GBNP.ReducePol2 GBNP.SGrobnerLoops IsGrobnerPair StrongNormalFormNP# ### -InstallGlobalFunction( -MkMonicNP,function(pol) - if pol=[[],[]] then return(pol); fi; - if IsOne(pol[2][1]) then return(pol); fi; +InstallGlobalFunction( MkMonicNP, function(pol) + if pol=[[],[]] then + return(pol); + fi; + if IsOne(pol[2][1]) then + return(pol); + fi; return([pol[1],pol[2]/pol[2][1]]); end);; +################## +### FactorOutGcdNP +### <#GAPDoc Label="FactorOutGcdNP"> +### +### +### +### np with Gcd(coefficients) factored out +### +### +### This function returns the scalar multiple of a polynomial +### np in NP format with integer coefficients +### such that its coefficients have Gcd equal to 1. +### If the coefficients are not all integers then fail is returned. +###

+### <#Include Label="example-FactorOutGcdNP"> +### +### +### <#/GAPDoc> +### - Makes a non-commutative polynomial with integer coeffiecients +### into one whose coefficients have Gcd equal to 1. +### +### Assumptions: +### - The polynomial is cleaned. +### - The leading term comes first. +### +### Arguments: +### pol - non-commutative polynomial +### +### Returns: +### pol - the non-commutative polynomial divided by Gcd(coefficients) +### +### #FactorOutGcdNP uses:# +### #FactorOutGcdNP is used in: # +### + +InstallGlobalFunction( FactorOutGcdNP, function(pol) + local g; + if pol=[[],[]] then + return(pol); + fi; + if not ForAll( pol[2], c -> IsInt(c) ) then + return fail; + fi; + g := Gcd( pol[2] ); + return([pol[1],pol[2]/g]); +end);; + ################# ### BimulNP ### <#GAPDoc Label="BimulNP"> @@ -384,8 +504,8 @@ end);; ### #BimulNP is used in: EvalTrace GBNP.NormalForm2 GBNP.NormalForm2T GBNP.Spoly GBNP.SpolyTrace GBNP.StrongNormalForm2 GBNP.StrongNormalForm2TS GBNP.StrongNormalForm2TSPTS GBNP.StrongNormalForm2Tall GBNP.StrongNormalForm3Dall GBNP.StrongNormalFormTrace2 GBNP.TraceNP# ### -InstallGlobalFunction( -BimulNP,function(ga,u,dr) local i,ans; +InstallGlobalFunction( BimulNP, function(ga,u,dr) + local i,ans; ans:=[]; for i in u[1] do Add(ans,Concatenation(ga,i,dr)); @@ -422,8 +542,8 @@ end);; ### #MulNP is used in: MulQA MulQM SGrobnerModule# ### -InstallGlobalFunction( -MulNP,function(u,v) local ans,i,j; +InstallGlobalFunction( MulNP, function(u,v) + local ans,i,j; ans:=[[],[]]; for i in [1..Length(u[1])] do for j in [1..Length(v[2])] do @@ -450,7 +570,7 @@ end);; ### #GBNP.LTermsTrace is used in: GBNP.AllObsTrace GBNP.CentralTrace GBNP.ObsTrace GBNP.ReducePolTrace2 GBNP.StrongNormalFormTrace2# ### -GBNP.LTermsTrace:=function(G) local i; +GBNP.LTermsTrace:=function(G) return(List(G,i->i.pol[1][1])); end; diff --git a/tst/functions.tst b/tst/functions.tst index a71e06f..ab7e039 100644 --- a/tst/functions.tst +++ b/tst/functions.tst @@ -509,15 +509,37 @@ gap> LMonsNP(Lnp); [ [ 1, 1, 2 ], [ 1, 2, 2 ] ] gap> # gap> -gap> -gap> # For a nicer printing, the monomials can be converted into polynomials in NP format, -gap> # and then submitted to PrintNPList: +gap> # For a nicer printing, the monomials can be converted into polynomials +gap> # in NP format, and then submitted to PrintNPList: gap> gap> # gap> PrintNPList(List(LMonsNP(Lnp), q -> [[q],[1]])); a^2b ab^2 gap> # +gap> # <#/GAPDoc> +gap> +gap> +gap> # <#GAPDoc Label="example-LTermNP"> +gap> # Example: +gap> # We put two polynomials in NP format into the list Lnp. +gap> # +gap> p1 := [[[1,1,2],[1]],[6,-7]];; +gap> p2 := [[[1,2,2],[2]],[8,-9]];; +gap> Lnp := [p1,p2];; +gap> # +gap> +gap> # The leading term of a polynomial is returned by LTermNP, +gap> # and the list of leading terms is computed by LTermsNP: +gap> +gap> # +gap> LTermNP( p1 ); +[ [ [ 1, 1, 2 ] ], [ 6 ] ] +gap> LTnp := LTermsNP( Lnp ); +[ [ [ [ 1, 1, 2 ] ], [ 6 ] ], [ [ [ 1, 2, 2 ] ], [ 8 ] ] ] +gap> List( LTnp, p -> NP2GP(p,A)); +[ (6)*a^2*b, (8)*a*b^2 ] +gap> # gap> gap> # <#/GAPDoc> gap> @@ -541,6 +563,26 @@ gap> gap> # <#/GAPDoc> gap> gap> +gap> # <#GAPDoc Label="example-FactorOutGcdNP"> +gap> # Example: +gap> # Consider the following polynomial in NP format. +gap> # +gap> p := [[[1,1,2],[1,2],[1]],[30,70,105]];; +gap> PrintNP(p); + 30a^2b + 70ab + 105a +gap> # +gap> +gap> # The Gcd of the coefficients [30,70,105] is 5. +gap> # The function FactorOutGcdNP divides the polynomial by 5: +gap> +gap> # +gap> PrintNP(FactorOutGcdNP(p)); + 6a^2b + 14ab + 21a +gap> # +gap> +gap> # <#/GAPDoc> +gap> +gap> gap> # <#GAPDoc Label="example-MulNP"> gap> # Example: gap> diff --git a/tst/test-bound-03.tst b/tst/test-bound-03.tst index 2a3e7f8..54cfbfd 100644 --- a/tst/test-bound-03.tst +++ b/tst/test-bound-03.tst @@ -147,12 +147,14 @@ gap> gap> # fails if zero occurs in the list -> what is the leading monomial of zero ?? gap> # not sure what the desired action should be (fail perhaps ?) gap> # might be better to document this +gap> # (04/09/23) the function now returns 'fail' gap> LMonsNP([])=[]; true gap> #LMonsNP([NPzero])=[]; gap> LMonsNP([NPone])=[M0]; true -gap> #LMonsNP([NPone,NPzero])=[M0]; +gap> LMonsNP([NPone,NPzero]); +[ [ ], fail ] gap> LMonsNP([NPone,NPone])=[M0,M0]; true gap>