Quelle involutive-cp.gi
Sprache: unbekannt
|
|
#############################################################################
##
#W involutive-cp.gi GAP4 package IBNP Gareth Evans & Chris Wensley
##
#############################################################################
##
#M PommaretDivision( <alg> <polys> <ord> )
##
InstallMethod( PommaretDivision, "generic method for list of monomials",
true, [ IsAlgebra, IsList, IsMonomialOrdering ], 0,
function( A, mons, ord )
local nmons, mvars, vars, i, posi, emoni;
nmons := Length( mons );
mvars := ListWithIdenticalEntries( nmons, 0 );
vars := OccuringVariableIndices( ord );
if ( vars = true ) then
Error( "specify the variable list in the ordering" );
fi;
for i in [1..nmons] do ## for each monnomial
emoni := ExtRepPolynomialRatFun( mons[i] )[1];
posi := Position( vars, emoni[1] );
mvars[i] := [1..posi]; ## [1 .. first letter]
od;
return mvars;
end );
#############################################################################
##
#M ThomasDivision( <alg> <polys> <ord> )
##
InstallMethod( ThomasDivision, "generic method for list of monomials",
true, [ IsAlgebra, IsList, IsMonomialOrdering ], 0,
function( A, mons, ord )
local genA, ngens, nmons, vars, e, max, j, k, p, i, m, mvars;
genA := GeneratorsOfLeftOperatorRingWithOne( A );
ngens := Length( genA );
nmons := Length( mons );
vars := OccuringVariableIndices( ord );
if ( vars = true ) then
Error( "specify the variable list in the ordering" );
fi;
## find the maximal exponents
max := ListWithIdenticalEntries( ngens, 0 );
for j in [1..nmons] do
e := ExtRepPolynomialRatFun( mons[j] )[1];
for k in [1..Length(e)/2] do
p := k+k-1;
i := Position( vars, e[p] );
m := e[p+1];
if ( m > max[i] ) then
max[i] := m;
fi;
od;
od;
Info( InfoIBNP, 2, "maximal exponents = ", max );
## find the multiplicative variables
mvars := ListWithIdenticalEntries( nmons, 0 );
for j in [1..nmons] do
mvars[j] := [ ];
e := ExtRepPolynomialRatFun( mons[j] )[1];
for k in [1..Length(e)/2] do
p := k+k-1;
i := Position( vars, e[p] );
m := e[p+1];
if ( m = max[i] ) then
Add( mvars[j], i );
fi;
od;
od;
Info( InfoIBNP, 2, "multiplicative variables = ", mvars );
return mvars;
end );
#############################################################################
##
#M JanetDivision( <alg> <polys> <ord> )
##
InstallMethod( JanetDivision, "generic method for list of monomials",
true, [ IsAlgebra, IsList, IsMonomialOrdering ], 0,
function( A, mons, ord )
local genA, ngens, nmons, vpos, vars, ordfn, expos, j, e, k, i,
mvars, done, ej, L, subj, ei, ok;
genA := ShallowCopy( GeneratorsOfLeftOperatorRingWithOne( A ) );
ngens := Length( genA );
Info( InfoIBNP, 2, "in JanetDivision, mons = ", mons );
nmons := Length( mons );
vpos := List( genA, g -> ExtRepPolynomialRatFun(g)[1][1] );
vars := OccuringVariableIndices( ord );
if ( vars = true ) then
Error( "specify the variable list in the ordering" );
fi;
ordfn := MonomialComparisonFunction( ord );
## create list of exponents, including zeroes
expos := ListWithIdenticalEntries( nmons, 0 );
for j in [1..nmons] do
expos[j] := ListWithIdenticalEntries( ngens, 0 );
e := ExtRepPolynomialRatFun( mons[j] )[1];
Info( InfoIBNP, 2, "e(mons[j]) = ", e );
for k in [1..Length(e)/2] do
i := Position( vpos, e[k+k-1] );
expos[j][i] := e[k+k];
od;
od;
Info( InfoIBNP, 2, "expos = ", expos );
## now set up the lists of multiplicative variables
mvars := ListWithIdenticalEntries( nmons, 0 );
for j in [1..nmons] do
mvars[j] := [ ];
od;
## test for x_1 .. x_{n-1}
for j in [1..ngens-1] do
done := ListWithIdenticalEntries( nmons, false );
for k in [1..nmons] do
if not done[k] then
done[k] := true;
ej := expos[k][j];
L := [k];
subj := expos[k]{[j+1..ngens]};
for i in [k+1..nmons] do
if ( subj = expos[i]{[j+1..ngens]} ) then
done[i] := true;
Add( L, i );
if ( expos[i][j] > ej ) then
ej := expos[i][j];
fi;
fi;
od;
for i in L do
if ( subj = expos[i]{[j+1..ngens]} )
and ( expos[i][j] = ej ) then
Add( mvars[i], j );
fi;
od;
fi;
od;
od;
## now test for x_n
ei := expos[1][ngens];
for k in [2..nmons] do
if ( expos[k][ngens] > ei ) then
ei := expos[k][ngens];
fi;
od;
## Error("here");
for k in [1..nmons] do
if ( expos[k][ngens] = ei ) then
Add( mvars[k], ngens );
fi;
od;
return mvars;
end );
#############################################################################
##
#M DivisionRecord( <args> )
##
BindGlobal( "DivisionRecord",
function( arg )
local nargs, A, polys, ord;
nargs := Length( arg );
if not ( nargs = 3 ) then
Error( "expecting arguments [ A, polys, ord ]" );
fi;
A := arg[1];
polys := arg[2];
ord := arg[3];
if not IsNearAdditiveMagma( A ) then
Error( "expecting an algebra as first parameter" );
fi;
if IsCommutative( A ) then
return DivisionRecordCP( A, polys, ord );
else
return DivisionRecordNP( A, polys, ord );
fi;
end );
############################################################################
##
#M IsDivisionRecord
##
InstallMethod( IsDivisionRecord, "generic method for records", true,
[ IsRecord ], 0,
function( r )
return ( IsBound\.( r, RNamObj( "div" ) ) )
and ( IsBound\.( r, RNamObj( "mvars" ) ) )
and ( IsBound\.( r, RNamObj( "polys" ) ) );
end );
#############################################################################
##
#M DivisionRecordCP( <alg> <polys> <ord> )
##
InstallMethod( DivisionRecordCP, "generic method for list of monomials",
true, [ IsAlgebra, IsList, IsMonomialOrdering ], 0,
function( A, polys, ord )
## Overview: returns local overlap-based multiplicative variables
## Detail: this function implements various algorithms
## described in the thesis "Noncommutative Involutive Bases"
## for finding multiplicative variable for a set of polynomials
local pl, genA, ordfn, ngens, npolys, mons, mvars;
pl := InfoLevel( InfoIBNP );
if( polys = [ ] ) then
return [ ];
fi;
genA := ShallowCopy( GeneratorsOfLeftOperatorRingWithOne( A ) );
ordfn := MonomialComparisonFunction( ord );
Sort( genA, ordfn );
ngens := Length( genA );
## set up arrays
npolys := Length( polys );
mons := List( polys, p -> LeadingMonomialOfPolynomial( p, ord ) );
Info( InfoIBNP, 2, "mons = ", mons );
if ( CommutativeDivision = "Pommaret" ) then
mvars := PommaretDivision( A, mons, ord );
elif ( CommutativeDivision = "Thomas" ) then
mvars := ThomasDivision( A, mons, ord );
elif ( CommutativeDivision = "Janet" ) then
mvars := JanetDivision( A, mons, ord );
else
Error( "invalid CommutativeDivision" );
fi;
return rec( div := CommutativeDivision, mvars := mvars, polys := polys );
end );
#############################################################################
##
#M IPolyReduce( <alg> <poly> <drec> <ord> )
##
BindGlobal( "IPolyReduce",
function( arg )
local nargs, A, p, drec, ord, polys, mvars;
nargs := Length( arg );
if not ( nargs = 4 ) then
Error( "expecting arguments [ A, pol, overlaprec, ordering ]" );
fi;
A := arg[1];
p := arg[2];
drec := arg[3];
polys := drec.polys;
mvars := drec.mvars;
ord := arg[4];
if not IsNearAdditiveMagma( A ) then
Error( "expecting an algebra as first parameter" );
fi;
if IsCommutative( A ) then
## add some tests
return IPolyReduceCP( A, p, drec, ord );
else
## add more tests
return IPolyReduceNP( A, p, drec, ord );
fi;
end );
#############################################################################
##
#M IPolyReduceCP( <alg> <poly> <drec> <ord> )
##
InstallMethod( IPolyReduceCP,
"generic method for a poly, record with fields [polys, mult vars]",
true, [ IsPolynomialRing, IsPolynomial, IsRecord, IsMonomialOrdering ], 0,
function( A, pol, drec, ord )
##
## Overview: Reduces 2nd arg w.r.t. 3rd arg (polys and vars)
##
## Detail: drec is a record containing a list 'polys' of polynomials
## and their multiplicative variables 'vars'.
## Given a polynomial _pol_, this function involutively
## reduces the polynomial with respect to the given polys
## with associated left and right multiplicative variables vars.
return CombinedIPolyReduceCP( A, pol, drec, ord, false );
end );
#############################################################################
##
#M LoggedIPolyReduce( <alg> <poly> <drec> <ord> )
##
BindGlobal( "LoggedIPolyReduce",
function( arg )
local nargs, A, p, drec, ord, polys, mvars;
nargs := Length( arg );
if not ( nargs = 4 ) then
Error( "expecting arguments [ A, pol, overlaprec, ordering ]" );
fi;
A := arg[1];
p := arg[2];
drec := arg[3];
polys := drec.polys;
mvars := drec.mvars;
ord := arg[4];
if not IsNearAdditiveMagma( A ) then
Error( "expecting an algebra as first parameter" );
fi;
if IsCommutative( A ) then
## add some tests
return CombinedIPolyReduceCP( A, p, drec, ord, true );
else
## add more tests
return CombinedIPolyReduceNP( A, p, drec, ord, true );
fi;
end );
#############################################################################
##
#M LoggedIPolyReduceCP( <alg> <poly> <drec> <ord> )
##
InstallMethod( LoggedIPolyReduceCP,
"generic method for a poly, record with fields [polys, mult vars]",
true, [ IsPolynomialRing, IsPolynomial,
IsRecord, IsMonomialOrdering ], 0,
function( A, pol, drec, ord )
##
## Overview: Reduces 2nd arg w.r.t. 3rd arg (polys and vars)
## just as in IPolyReduceCP, but returns a record contsaining the reduced
## polynomial and also logged information showing how the result is
## obtained from the original polynomial.
##
return CombinedIPolyReduceCP( A, pol, drec, ord, true );
end );
#############################################################################
##
#M CombinedIPolyReduceCP( <alg> <poly> <drec> <ord> <logging> )
##
InstallMethod( CombinedIPolyReduceCP,
"generic method for a poly, record with fields [polys, mult vars]",
true, [ IsPolynomialRing, IsPolynomial,
IsRecord, IsMonomialOrdering, IsBool ], 0,
function( A, pol, drec, ord, logging )
local polys, mvars, genA, vpos, a, z, front, back, eback,
numpolys, mons, coeffs, reduced, mon, coeff, term,
i, poli, moni, fac, coeffi, efac, lenf, ok, logs;
if not IsDivisionRecord( drec ) then
Error( "third argument should be an overlap record" );
fi;
Info( InfoIBNP, 3, "in IPolyReduceCP: pol = ", pol,
", logging = ", logging );
polys := drec.polys;
numpolys := Length( polys );
logs := List( [1..numpolys], i -> Zero( A ) );
mvars := drec.mvars;
genA := GeneratorsOfLeftOperatorRingWithOne( A );
vpos := List( genA, g -> ExtRepPolynomialRatFun(g)[1][1] );
a := genA[1];
z := a-a; ## zero polynomial;
front := z;
back := pol;
eback := ExtRepPolynomialRatFun( back );
mons := List( polys, p -> LeadingMonomialOfPolynomial( p, ord ) );
coeffs := List( polys, p -> LeadingCoefficientOfPolynomial( p, ord ) );
## we now recursively reduce every term in the polynomial
## until no more reductions are possible
while ( eback <> [ ] ) do
reduced := true;
while reduced and ( eback <> [ ] ) do
reduced := false;
mon := LeadingMonomialOfPolynomial( back, ord );
coeff := LeadingCoefficientOfPolynomial( back, ord );
i := 0;
while ( i < numpolys ) and ( not reduced ) do
## for each polynomial in the list
i := i+1;
poli := polys[i];
moni := mons[i]; ## pick a test monomial
fac := mon/moni;
if IsPolynomial( fac ) then ## moni divides mon
Info( InfoIBNP, 3, "divisor found: fac = ", fac );
coeffi := coeffs[i];
efac := ExtRepPolynomialRatFun( fac )[1];
Info( InfoIBNP, 3, "fac = ", fac, ", efac = ", efac );
lenf := Length( efac );
ok := ( lenf = 0 ) or ForAll( [1,3..lenf-1],
j -> Position( vpos, efac[j] ) in mvars[i] );
## if an involutive division was found
if ok then
## indicate a reduction has been carried out
## to exit the loop
## pick the divisor's leading coefficient
## pick 'nice' cancelling coefficients
term := (coeff/coeffi)*fac;
back := back - term*poli;
if logging then
logs[i] := logs[i] + term;
fi;
Info( InfoIBNP, 2, "reduced to: ", front+back );
eback := ExtRepPolynomialRatFun( back );
reduced := true;
fi;
fi;
od;
od;
if ( eback <> [ ] ) then
## no reduction of the lead term, so add it to front
front := front + coeff*mon;
back := back - coeff*mon;
eback := ExtRepPolynomialRatFun( back );
fi;
od;
if ( front <> z ) then
if ( LeadingCoefficientOfPolynomial( front, ord ) < 0 ) then
front := (-1)*front;
if logging then
logs := List( logs, t -> (-1)*t );
fi;
fi;
fi;
if not logging then
return front; ## return the reduced and simplified polynomial
else
return rec( result := front, logs := logs, polys := polys );
fi;
end );
#############################################################################
##
#M IAutoreduce( <args> )
##
BindGlobal( "IAutoreduce",
function( arg )
local nargs, A, polys, ord;
nargs := Length( arg );
if not ( nargs = 3 ) then
Error( "expecting arguments [ A, polys, ord ]" );
fi;
A := arg[1];
polys := arg[2];
ord := arg[3];
if not IsNearAdditiveMagma( A ) then
## add some tgests
Error( "expecting an algebra as first parameter" );
fi;
if IsCommutative( A ) then
## add more tests
return IAutoreduceCP( A, polys, ord );
else
return IAutoreduceNP( A, polys, ord );
fi;
end );
#############################################################################
##
#M IAutoreduceCP( <alg> <polys> <ord> )
##
InstallMethod( IAutoreduceCP, "generic method for list of polys",
true, [ IsAlgebra, IsList, IsMonomialOrdering ], 0,
function( A, polys, ord )
## Overview: Autoreduces a list of polynomials recursively
## until no more reductions are possible
## Detail: This function involutively reduces each member of a
## list of polynomials w.r.t. all the other members of the list,
## removing the polynomial from the list if it is involutively
## reduced to 0. Iterate until no more such reductions are possible.
local pl, div, npolys, genA, a, z, pos, old, reduced, ordfn,
oldPoly, nrec, newvars, vars, drec, oldvars, new, newPoly;
pl := InfoLevel( InfoIBNP );
div := CommutativeDivision;
npolys := Length( polys );
if( npolys < 2 ) then
## the input basis is empty or consists of a single polynomial
return polys;
fi;
genA := GeneratorsOfLeftOperatorRingWithOne( A );
a := genA[1];
z := a-a; ## zero polynomial;
## start by reducing the final element (working backwards means
## that less work has to be done calculating multiplicative variables)
## if we are using a local division and the basis is sorted by DegRevLex,
## the last polynomial is irreducible so we do not have to consider it.
## make a copy of the input basis for traversal
old := StructuralCopy( polys );
ordfn := MonomialComparisonFunction( ord );
reduced := true;
while reduced do
reduced := false;
Sort( old, ordfn );
npolys := Length( old );
pos := npolys;
drec := DivisionRecordCP( A, old, ord );
oldvars := drec.mvars;
if ( pl > 2 ) then
Print( "old = ", old, "\n" );
Print( "oldvars = ", oldvars, "\n" );
fi;
while ( pos > 0 ) and ( not reduced ) do ## for each poly in old
## extract pos-th element of the basis and reduce using the rest
oldPoly := old[pos];
if ( pl > 2 ) then
Print( "oldPoly = ", oldPoly, "\n" );
fi;
## construct basis without oldPoly
## calculate multiplicative Variables if using a local division
newvars := Concatenation( oldvars{[1..pos-1]},
oldvars{[pos+1..npolys]} );
new := Concatenation( old{[1..pos-1]}, old{[pos+1..npolys]} );
nrec := rec( div := div, mvars := newvars, polys := new );
## involutively reduce old polynomial w.r.t. the truncated list
newPoly := IPolyReduceCP( A, oldPoly, nrec, ord );
Info( InfoIBNP, 2, "newPoly = ", newPoly );
## if the polynomial did not reduce to 0
if ( newPoly = z ) then
## the polynomial reduced to zero
## remove the polynomial from the list
new := Concatenation( new{[1..pos-1]},
new{[pos+1..npolys]} );
pos := pos - 1;
npolys := npolys - 1;
elif ( oldPoly = newPoly ) then
## we may proceed to look at the next polynomial
pos := pos - 1;
else
## otherwise some reduction took place so start again
## add the new polynomial onto the list
reduced := true;
old := Concatenation( new, [ newPoly ] );
Info( InfoIBNP, 2, "reduction! now old = ", old );
fi;
od;
od;
Sort( old, ordfn );
## return the fully autoreduced basis
if ( old = polys ) then ## no change
return true;
else
return old;
fi;
end );
#############################################################################
##
#M InvolutiveBasis( <args> )
##
BindGlobal( "InvolutiveBasis",
function( arg )
local nargs, A, polys, ord;
nargs := Length( arg );
if not ( nargs = 3 ) then
Error( "expecting arguments [ A, polys, ord ]" );
fi;
A := arg[1];
polys := arg[2];
ord := arg[3];
if not IsNearAdditiveMagma( A ) then
## add some tests
Error( "expecting an algebra as first parameter" );
fi;
if IsCommutative( A ) then
## add more tests
return InvolutiveBasisCP( A, polys, ord );
else
return InvolutiveBasisNP( A, polys, ord );
fi;
end );
#############################################################################
##
#M InvolutiveBasisCP( <alg> <polys> <ord> )
##
InstallMethod( InvolutiveBasisCP,
"generic method for commutative algebra + list of polys + ordering",
true, [ IsAlgebra, IsList, IsMonomialOrdering ], 0,
function( A, polys, ord )
## Implements Algorithm 9 for computing commutative involutive bases.
local pl, npolys, genA, a, z, ngens, all, basis, vars, done,
ordfn, basis0, nbasis, drec, mvars, nvars, prolong,
i, j, npro, found, u, v;
pl := InfoLevel( InfoIBNP );
Info( InfoIBNP, 2, "Computing an Involutive Basis...");
npolys := Length( polys );
if( npolys < 2 ) then
## the input basis is empty or consists of a single polynomial
return polys;
fi;
genA := GeneratorsOfLeftOperatorRingWithOne( A );
a := genA[1];
z := a-a; ## zero polynomial;
ngens := Length( genA );
all := [ 1..ngens ];
basis := IAutoreduceCP( A, polys, ord );
if ( basis = true ) then ## no reduction
basis := polys;
fi;
Info( InfoIBNP, 2, "initial basis = ", basis );
done := false;
ordfn := MonomialComparisonFunction( ord );
while ( not done ) do
Sort( basis, ordfn );
Info( InfoIBNP, 1, "restarting with basis:\n", basis );
basis0 := ShallowCopy( basis );
basis := IAutoreduceCP( A, basis0, ord );
if ( basis = true ) then
basis := basis0;
else
Info( InfoIBNP, 1, "after autoreduction basis = \n", basis );
fi;
nbasis := Length( basis );
drec := DivisionRecordCP( A, basis, ord );
Info( InfoIBNP, 1, "division record for basis: ", drec );
mvars := drec.mvars;
nvars := List( mvars, v -> Difference( all, v ) );
Info( InfoIBNP, 2, "mvars = ", mvars );
Info( InfoIBNP, 2, "nvars = ", nvars );
## construct the prolongations
prolong := [ ];
for i in [ 1..nbasis ] do
for j in nvars[i] do
Add( prolong, genA[j]*basis[i] );
od;
od;
Sort( prolong, ordfn );
Info( InfoIBNP, 1, "prolongations = ", prolong );
npro := Length( prolong );
found := false;
for i in [1..npro] do
u := prolong[i];
v := IPolyReduceCP( A, u, drec, ord );
Info( InfoIBNP, 2, "u = ", u, ", v = ", v );
if ( v <> z ) then
found := true;
Add( basis, v );
Info( InfoIBNP, 2, "adding ", v );
if ( pl > 0 ) and
( Length(basis) > InvolutiveAbortLimit ) then
return fail;
fi;
drec := DivisionRecordCP( A, basis, ord );
fi;
od;
if not found then
done := true;
fi;
od;
return DivisionRecordCP( A, basis, ord);
end );
#############################################################################
##
#E involutive-cp.gi . . . . . . . . . . . . . . . . . . . . . . . ends here
##
[ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
]
|
2026-04-04
|