Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/ibnp/lib/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 11.8.2025 mit Größe 22 kB image not shown  

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.4 Sekunden  (vorverarbeitet)  ]