Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


SSL groebner.gi   Interaktion und
Portierbarkeitunbekannt

 
#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Alexander Hulpke, David Joyner.
##
##  Copyright of GAP belongs to its developers, whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##
##  This file contains the implementations for monomial orderings and Groebner
##  bases.

# convenience function to catch cases
BindGlobal("GBasisFixOrderingArgument",function(a)
  if IsFunction(a) then
    a:=a();
  fi;
  return a;
end);

BindGlobal("MakeMonomialOrdering",function(name,ercomp)
local obj;
  obj:=Objectify(NewType(MonomialOrderingsFamily,IsMonomialOrderingDefaultRep),
                 rec());
  SetName(obj,name);
  SetMonomialExtrepComparisonFun(obj,ercomp);
  return obj;
end);

BindGlobal("InstallMonomialOrdering",function(ord,ordfun,idxord,
  # for external interfaces. We use the names as in Singular
  # this might change in future versions
  type
  )
  InstallGlobalFunction(ord,function(arg)
  local idx,nam,ordname,neword,ov;
    if Length(arg)=1 and IsList(arg[1]) then
      idx:=arg[1];
    else
      idx:=arg;
    fi;
    nam:=String(idx);
    if Length(idx)>0 and not IsInt(idx[1]) then
      idx:=List(idx,IndeterminateNumberOfUnivariateRationalFunction);
    fi;
    if Length(idx)>0 then
      ov:=Set(idx);
    else
      ov:=true;
    fi;
    if IsSSortedList(idx) then
      idx:=[];
    fi;
    if IsString(ord) then
      ordname:=ord;
    else
      ordname:=NameFunction(ord);
    fi;
    if Length(idx)>0 then
      # get an indexed ordering

      nam:=Concatenation(ordname,"(",nam,")");
      neword:=MakeMonomialOrdering(nam,
        function(a,b)
          # for each variable give its index position.
          return idxord(a,b,List([1..Maximum(idx)],i->Position(idx,i)));
        end);
      neword!.idxarrangement:=Immutable(idx);
      neword!.type:=Immutable(type);
      SetOccuringVariableIndices(neword,ov);
      return neword;
    else
      nam:=Concatenation(ordname,"()");
      neword:=MakeMonomialOrdering(nam,ordfun);
      neword!.idxarrangement:=Immutable(idx);
      neword!.type:=Immutable(type);
      SetOccuringVariableIndices(neword,ov);
      return neword;
    fi;
  end);
end);

InstallMethod(MonomialComparisonFunction,"default: use extrep",true,
  [IsMonomialOrderingDefaultRep],0,
function(ord)
local fun;
  fun:=MonomialExtrepComparisonFun(ord);
  return function(a,b)
  local e, f, le, lf,fam;
    fam:=FamilyObj(a);
    e:=ExtRepPolynomialRatFun(a);
    f:=ExtRepPolynomialRatFun(b);
    repeat
      if Length(e)=0 and Length(f)>0 then return true;
      elif Length(f)=0 then return false;
      fi;
      if Length(e)=2 then
        le:=1;
      else
        le:=LeadingMonomialPosExtRep(fam,e,fun);
      fi;
      if Length(f)=2 then
        lf:=1;
      else
        lf:=LeadingMonomialPosExtRep(fam,f,fun);
      fi;
      if fun(e[le],f[lf]) then
        return true;
      elif e[le]<>f[lf] then
        return false;
      fi;
      e:=e{Concatenation([1..le-1],[le+2..Length(e)])};
      f:=f{Concatenation([1..lf-1],[lf+2..Length(f)])};
    until false;
  end;
end);

#############################################################################
##
#F  MonomialLexOrdering()
#F  MonomialLexOrdering(<vari>)
##
##  This function creates a lexicographic ordering for monomials. If <vari>
##  is given and is a list of variables or variable indices, this is used as
##  the underlying order of variables.
InstallMonomialOrdering(MonomialLexOrdering,
  #ordinary case
  function(a,b)
  local l,m,i;
    l:=Length(a);
    m:=Length(b);
    i:=1;
    while i<l and i<m do
    # in this ordering x_1>x_2
      if a[i]>b[i] then
        return true;
      elif a[i]<b[i] then
        return false;
      elif a[i+1]<b[i+1] then
        return true;
      elif a[i+1]>b[i+1] then
        return false;
      fi;
      i:=i+2;
    od;
    if i<m then
      return true;
    fi;
    # bigger or equal
    return false;
  end,
  # indexed case
  function(a,b,idx)
  local l, m, min, i, am, ap, ai, has, bi,ret;
    l:=Length(a);
    m:=Length(b);

    # as variables are not necessarily stored in the right order, we'll have
    # to run through by variables one by one, The biggest index variables
    # first
    min:=0;

    repeat
      # get the smallest position (i.e. largest) remaining variable in a
      i:=1;
      am:=infinity;
      ap:=0;
      while i<l do
        ai:=idx[a[i]];
        if ai>min and ai<am then
          # smaller pos (i.e. larger) variable found
          am:=ai;
          ap:=i;
        fi;
        i:=i+2;
      od;
      if am=infinity then
        # no variable left in a. Test what is left in b
        i:=1;
        has:=false;
        while i<m do
          bi:=idx[b[i]];
          if bi>min then
            # b has variables left. So a is smaller
            return true;
          fi;
          i:=i+2;
        od;
        # b also not. thus a must be equal to b
        return false;
      fi;

      # now search for am in b
      i:=1;
      has:=false;
      while i<m do
        bi:=idx[b[i]];
        if bi>min then
          if bi<am then
            # b has a larger (smaller pos) variable left. Thus b is bigger.
            return true;
          elif bi=am then
            # the same variable occurs.
            has:=true;
            if a[ap+1]>b[i+1] then

              # a exponent is bigger
              ret:=false; # unless a smaller (larger pos) variable found
            elif a[ap+1]<b[i+1] then
              # b exponent is bigger
              ret:=true; # unless a smaller (larger pos) variable found
            else
              # same exponents -- cannot decide on this variable
              ret:=fail;
            fi;
          fi;
        fi;
        i:=i+2;
      od;
      if not has then
        # b has no variable as large as am. thus a is bigger
        return false;
      elif ret<>fail then
        # b has no larger variable than am  buty has am. Use the comparison
        return ret;
      fi;
      min:=am; # will increase until no variable in a left
    until false;
  end,
  MakeImmutable("lp"));

#############################################################################
##
#F  MonomialGrlexOrdering()
#F  MonomialGrlexOrdering(<vari>)
##
##  This function creates a degree/lexicographic ordering for monomials. If
##  <vari> is given and is a list of variables or variable indices, this is
##  used as the underlying order of variables.
InstallMonomialOrdering(MonomialGrlexOrdering,
  function(a,b)
  local s,t,i,l,m;
    s:=0;
    l:=Length(a);
    m:=Length(b);
    for i in [2,4..l] do
      s:=s+a[i];
    od;
    t:=0;
    for i in [2,4..m] do
      t:=t+b[i];
    od;
    if s<t then
      return true;
    elif s>t then
      return false;
    fi;

    # Lex
    i:=1;
    while i<l and i<m do
    # in this ordering x_1>x_2
      if a[i]>b[i] then
        return true;
      elif a[i]<b[i] then
        return false;
      elif a[i+1]<b[i+1] then
        return true;
      elif a[i+1]>b[i+1] then
        return false;
      fi;
      i:=i+2;
    od;
    if i<m then
      return true;
    fi;
    # bigger or equal
    return false;
  end,

  # indexed case
  function(a,b,idx)
  local s, l, m, t, min, i, am, ap, ai, has, bi, ret;
    s:=0;
    l:=Length(a);
    m:=Length(b);
    for i in [2,4..l] do
      s:=s+a[i];
    od;
    t:=0;
    for i in [2,4..m] do
      t:=t+b[i];
    od;
    if s<t then
      return true;
    elif s>t then
      return false;
    fi;

    # Lex


    # as variables are not necessarily stored in the right order, we'll have
    # to run through by variables one by one, The biggest index variables
    # first
    min:=0;

    repeat
      # get the smallest position (i.e. largest) remaining variable in a
      i:=1;
      am:=infinity;
      ap:=0;
      while i<l do
        ai:=idx[a[i]];
        if ai>min and ai<am then
          # smaller pos (i.e. larger) variable found
          am:=ai;
          ap:=i;
        fi;
        i:=i+2;
      od;
      if am=infinity then
        # no variable left in a. Test what is left in b
        i:=1;
        has:=false;
        while i<m do
          bi:=idx[b[i]];
          if bi>min then
            # b has variables left. So a is smaller
            return true;
          fi;
          i:=i+2;
        od;
        # b also not. thus a must be equal to b
        return false;
      fi;

      # now search for am in b
      i:=1;
      has:=false;
      while i<m do
        bi:=idx[b[i]];
        if bi>min then
          if bi<am then
            # b has a larger (smaller pos) variable left. Thus b is bigger.
            return true;
          elif bi=am then
            # the same variable occurs.
            has:=true;
            if a[ap+1]>b[i+1] then

              # a exponent is bigger
              ret:=false; # unless a smaller (larger pos) variable found
            elif a[ap+1]<b[i+1] then
              # b exponent is bigger
              ret:=true; # unless a smaller (larger pos) variable found
            else
              # same exponents -- cannot decide on this variable
              ret:=fail;
            fi;
          fi;
        fi;
        i:=i+2;
      od;
      if not has then
        # b has no variable as large as am. thus a is bigger
        return false;
      elif ret<>fail then
        # b has no larger variable than am  buty has am. Use the comparison
        return ret;
      fi;
      min:=am; # will increase until no variable in a left
    until false;
  end,
  MakeImmutable("Dp"));

#############################################################################
##
#F  MonomialGrevlexOrdering()
#F  MonomialGrevlexOrdering(<vari>)
##
##  This function creates a degree/reverse lexicographic ordering for
##  monomials. If <vari> is given and is a list of variables or variable
##  indices, this is used as the underlying order of variables.
InstallMonomialOrdering(MonomialGrevlexOrdering,
  #ordinary
  function(a,b)
  local s,t,i,j,l,m;
    s:=0;
    l:=Length(a);
    m:=Length(b);
    for i in [2,4..l] do
      s:=s+a[i];
    od;
    t:=0;
    for i in [2,4..m] do
      t:=t+b[i];
    od;
    if s<t then
      return true;
    elif s>t then
      return false;
    fi;
    # Revlex
    i:=l-1;
    j:=m-1;
    while i>0 and j>0 do
    # in this ordering x_1>x_2
      if a[i]>b[j] then
        # case x/0 -- a not bigger
        return true;
      elif a[i]<b[j] then
        # case 0/x  a bigger
        return false;
      elif a[i+1]<b[j+1] then
        # a-b is negative
        return false;
      elif a[i+1]>b[j+1] then
        # a-b is positive
        return true;
      fi;
      i:=i-2;
      j:=j-2;
    od;
    if i>0 then
      #a-part left
      return true;
    fi;
    # bigger or equal
    return false;
  end,
  # indexed case
  function(a,b,idx)
    Error("indexed grevlex not yet implemented");
  end,
  MakeImmutable("dp"));

#############################################################################
##
#F  EliminationOrdering(<elim>)
#F  EliminationOrdering(<elim>,<rest>)
##
##  This function creates an elimination ordering for eliminating the
##  variables in <elim>. Two monomials are compared first by the exponent
##  vectors for the variables listed in <elim> (a lexicographic comparison
##  with respect to the ordering indicated in <elim>).
##  If these submonomial are equal, the submonomials given by the other
##  variables are compared by a graded lexicographic ordering (with respect
##  to the variable order given in <rest>, if called with two parameters).
##
##  Both <elim> and <rest> may be a list of variables of a list of variable
##  indices.
InstallGlobalFunction(EliminationOrdering,function(arg)
local elimvar, nam, ord1, othvar, ord2,ov,neword;
  elimvar:=arg[1];
  nam:=ShallowCopy(String(elimvar));
  if not IsInt(elimvar[1]) then
    elimvar:=List(elimvar,IndeterminateNumberOfUnivariateRationalFunction);
  fi;
  ov:=Set(elimvar);
  ord1:=MonomialExtrepComparisonFun(MonomialLexOrdering(elimvar));
  if Length(arg)>1 then
    othvar:=arg[2];
    Add(nam,',');
    nam:=Concatenation(nam,String(othvar));
    if not IsInt(othvar[1]) then
      othvar:=List(othvar,IndeterminateNumberOfUnivariateRationalFunction);
    fi;
    ov:=Union(ov,othvar);
    ord2:=MonomialExtrepComparisonFun(MonomialGrlexOrdering(othvar));
  else
    ov:=true;
    ord2:=MonomialExtrepComparisonFun(MonomialGrlexOrdering());
  fi;

  neword:=MakeMonomialOrdering(
    Concatenation("EliminationOrdering(",nam,")"),
    function(a,b)
    local la, lb, asel, bsel, ah, bh, i;
      la:=Length(a);
      lb:=Length(b);
      asel:=[];
      for i in [1,3..la-1] do
        if a[i] in elimvar then
          Add(asel,i);
          Add(asel,i+1);
        fi;
      od;
      bsel:=[];
      for i in [1,3..lb-1] do
        if b[i] in elimvar then
          Add(bsel,i);
          Add(bsel,i+1);
        fi;
      od;
      ah:=a{asel};
      bh:=b{bsel};
      if ah=bh then
        ah:=a{Difference([1..la],asel)};
        bh:=b{Difference([1..lb],bsel)};
        return ord2(ah,bh);
      else
        return ord1(ah,bh);
      fi;
    end);
  SetOccuringVariableIndices(neword,ov);
  return neword;
end);

InstallMethod(MonomialExtrepComparisonFun,
  "functions are themselves -- for compatibility",true,[IsFunction],0,f->f);

InstallOtherMethod(OccuringVariableIndices,"polynomial",true,
  [IsPolynomial],0,
function(p)
local ov, l, i, j;
  p:=ExtRepPolynomialRatFun(p);
  ov:=[];
  for i in [1,3..Length(p)-1] do
    l:=p[i];
    for j in [1,3..Length(l)-1] do
      AddSet(ov,l[j]);
    od;
  od;
  return ov;
end);

InstallMethod(LeadingTermOfPolynomial,"with ordering",true,
  [IsPolynomialFunction,IsMonomialOrdering],0,
function(p,order)
local e,fam,a;
  order:=MonomialExtrepComparisonFun(order);
  e:=ExtRepPolynomialRatFun(p);
  fam:=FamilyObj(p);
  a:=LeadingMonomialPosExtRep(fam,e,order);
  return PolynomialByExtRepNC(fam,e{[a,a+1]});
end);

InstallOtherMethod(LeadingMonomialOfPolynomial,"with ordering",true,
  [IsPolynomialFunction,IsMonomialOrdering],0,
function(p,order)
local e,fam,a;
  if not IsPolynomial(p) then
    TryNextMethod();
  fi;
  order:=MonomialExtrepComparisonFun(order);
  e:=ExtRepPolynomialRatFun(p);
  fam:=FamilyObj(p);
  a:=LeadingMonomialPosExtRep(fam,e,order);
  return PolynomialByExtRepNC(fam,[e[a],One(CoefficientsFamily(fam))]);
end);

InstallOtherMethod(LeadingCoefficientOfPolynomial,"with ordering",true,
  [IsPolynomialFunction,IsMonomialOrdering],0,
function(p,order)
local e,fam,a;
  if not IsPolynomial(p) then
    TryNextMethod();
  fi;
  order:=MonomialExtrepComparisonFun(order);
  e:=ExtRepPolynomialRatFun(p);
  fam:=FamilyObj(p);
  a:=LeadingMonomialPosExtRep(fam,e,order);
  return e[a+1];
end);

# compute S-polynomial and return `0' if the leading monomials are coprime
BindGlobal("SPolynomial",function(p,q,order)
local a,b,c,d,e,f,i,j,ae,be,di,fam;
  order:=MonomialExtrepComparisonFun(order);
  e:=ExtRepPolynomialRatFun(p);
  f:=ExtRepPolynomialRatFun(q);
  fam:=FamilyObj(p);
  a:=LeadingMonomialPosExtRep(fam,e,order);
  b:=LeadingMonomialPosExtRep(fam,f,order);
  ae:=e[a];
  be:=f[b];

  # compute the cofactors
  i:=1;
  j:=1;
  c:=[];
  d:=[];
  while i<Length(ae) and j<Length(be) do
    if ae[i]<be[j] then
      # a has variable not in b
      Append(d,ae{[i,i+1]});
      i:=i+2;
    elif ae[i]>be[j] then
      # b has variable not in a
      Append(c,be{[j,j+1]});
      j:=j+2;
    else
      # variable in both: One larger?
      di:=be[j+1]-ae[i+1];
      if di>0 then
        Append(c,[ae[i],di]);
      elif di<0 then
        Append(d,[be[j],-di]);
      fi;
      i:=i+2;
      j:=j+2;
    fi;
  od;

  # trailing entries
  if i<Length(ae) then
    Append(d,ae{[i..Length(ae)]});
  elif j<Length(be) then
    Append(c,be{[j..Length(be)]});
  fi;
  return PolynomialByExtRepNC(fam,[c,f[b+1]])*p
         -PolynomialByExtRepNC(fam,[d,e[a+1]])*q;
end);

#############################################################################
##
#F  PolynomialReduction(poly,plist,order)     reduces poly with the ideal
##                                 generated by plist, according to order
##  The routine returns a list [remainder,[quotients]]
##
InstallGlobalFunction( PolynomialReduction, function(poly,plist,order)
local fam,quot,elist,lmp,lmo,lmc,x,y,z,mon,mon2,qmon,noreduce,
      ep,pos,di,rem,qmex;
  if IsMonomialOrdering(order) then
    order:=MonomialExtrepComparisonFun(order);
  fi;
  fam:=FamilyObj(poly);
  quot:=List(plist,i->Zero(poly));
  elist:=List(plist,ExtRepPolynomialRatFun);
  lmp:=List(elist,i->LeadingMonomialPosExtRep(fam,i,order));
  lmo:=List([1..Length(lmp)],i->elist[i][lmp[i]]);
  lmc:=List([1..Length(lmp)],i->elist[i][lmp[i]+1]);

  ep:=ExtRepPolynomialRatFun(poly);
  rem:=Zero(poly);
  while Length(ep)>0 do
    # now try whether we can reduce at x

    noreduce:=true;
    x:=LeadingMonomialPosExtRep(fam,ep,order);
    mon:=ep[x];
    y:=1;
    while y<=Length(plist) and noreduce do
      mon2:=lmo[y];
      #check whether the monomial at position x is a multiple of the
      #y-th leading monomial
      z:=1;
      pos:=1;
      qmon:=[]; # potential quotient
      noreduce:=false;
      while noreduce=false and z<=Length(mon2) and pos<=Length(mon) do
        if mon[pos]>mon2[z] then
          noreduce:=true; # indet in mon2 does not occur in mon -> does not
                          # divide
        elif mon[pos]<mon2[z] then
          Append(qmon,mon{[pos,pos+1]}); # indet only in mon
          pos:=pos+2;
        else
          # the indets are the same
          di:=mon[pos+1]-mon2[z+1];
          if di>0 then
            #divides and there is remainder
            Append(qmon,[mon[pos],di]);
          elif di<0 then
            noreduce:=true; # exponent to small
          fi;
          pos:=pos+2;
          z:=z+2;
        fi;
      od;

      # if there is a tail in mon2 left, cannot divide
      if z<=Length(mon2) then
        noreduce:=true;
      fi;
      y:=y+1;
    od;
    if noreduce then
      mon:=PolynomialByExtRepNC(fam,[ep[x],ep[x+1]]);
      rem:=rem+mon;
  #Print("noreduce:",PolynomialByExtRepNC(fam,ep)," ",mon," ",rem,"\n");
      ep:=ep{Difference([1..Length(ep)],[x,x+1])};
  #Print(ep,"\n");
    else
      y:=y-1; # re-correct incremented numbers

      # is there a tail in mon? if yes we need to append it
      if pos<Length(mon) then
        Append(qmon,mon{[pos..Length(mon)]});
      fi;

      # reduce!
      qmex:=[qmon,-ep[x+1]/lmc[y]];

      qmon:=PolynomialByExtRepNC(fam,[qmon,ep[x+1]/lmc[y]]); #quotient monomial
      quot[y]:=quot[y]+qmon;

      qmex:=ZippedProduct(qmex,elist[y],
             fam!.zeroCoefficient,fam!.zippedProduct);
      qmex:=ZippedSum(ep,qmex,fam!.zeroCoefficient,fam!.zippedSum);

      #poly:=PolynomialByExtRep(fam,ep);
      #poly:=poly-qmon*plist[y]; # reduce
      #ep:=ExtRepPolynomialRatFun(poly);
      #if ep<>qmex then Error("RED!"); fi;
      ep:=qmex;

    fi;
  od;
  return [rem,quot];
end);




#############################################################################
##
#F  PolynomialReducedRemainder(poly,plist,order)
##
InstallGlobalFunction(PolynomialReducedRemainder,function(poly,plist,order)
local fam, elist, lmp, lmo, lmc, ep, rem, noreduce, x, mon, y, mon2,
  z, pos, qmon, di,qmex;
  if IsMonomialOrdering(order) then
    order:=MonomialExtrepComparisonFun(order);
  fi;
  fam:=FamilyObj(poly);
  elist:=List(plist,ExtRepPolynomialRatFun);
  lmp:=List(elist,i->LeadingMonomialPosExtRep(fam,i,order));
  lmo:=List([1..Length(lmp)],i->elist[i][lmp[i]]);
  lmc:=List([1..Length(lmp)],i->elist[i][lmp[i]+1]);

  ep:=ExtRepPolynomialRatFun(poly);
  rem:=Zero(poly);
  while Length(ep)>0 do
    # now try whether we can reduce at x

    noreduce:=true;
    x:=LeadingMonomialPosExtRep(fam,ep,order);
    mon:=ep[x];
    y:=1;
    while y<=Length(plist) and noreduce do
      mon2:=lmo[y];
      #check whether the monomial at position x is a multiple of the
      #y-th leading monomial
      z:=1;
      pos:=1;
      qmon:=[]; # potential quotient
      noreduce:=false;
      while noreduce=false and z<=Length(mon2) and pos<=Length(mon) do
        if mon[pos]>mon2[z] then
          noreduce:=true; # indet in mon2 does not occur in mon -> does not
                          # divide
        elif mon[pos]<mon2[z] then
          Append(qmon,mon{[pos,pos+1]}); # indet only in mon
          pos:=pos+2;
        else
          # the indets are the same
          di:=mon[pos+1]-mon2[z+1];
          if di>0 then
            #divides and there is remainder
            Append(qmon,[mon[pos],di]);
          elif di<0 then
            noreduce:=true; # exponent to small
          fi;
          pos:=pos+2;
          z:=z+2;
        fi;
      od;

      # if there is a tail in mon2 left, cannot divide
      if z<=Length(mon2) then
        noreduce:=true;
      fi;
      y:=y+1;
    od;
    if noreduce then
      mon:=PolynomialByExtRepNC(fam,[ep[x],ep[x+1]]);
      rem:=rem+mon;
      ep:=ep{Difference([1..Length(ep)],[x,x+1])};
    else
      y:=y-1; # re-correct incremented numbers

      # is there a tail in mon? if yes we need to append it
      if pos<Length(mon) then
        Append(qmon,mon{[pos..Length(mon)]});
      fi;

      # reduce!
      qmex:=[qmon,-ep[x+1]/lmc[y]];
      qmex:=ZippedProduct(qmex,elist[y],
             fam!.zeroCoefficient,fam!.zippedProduct);
      qmex:=ZippedSum(ep,qmex,fam!.zeroCoefficient,fam!.zippedSum);

      #qmon:=PolynomialByExtRepNC(fam,[qmon,ep[x+1]/lmc[y]]); #quotient monomial
      #poly:=PolynomialByExtRep(fam,ep);
      #poly:=poly-qmon*plist[y]; # reduce
      #ep:=ExtRepPolynomialRatFun(poly);
      #if ep<>qmex then Error("RED0!"); fi;
      ep:=qmex;
    fi;
  od;
  return rem;
end);

#############################################################################
##
#F  PolynomialDivisionAlgorithm(poly,plist,order)
##
InstallGlobalFunction(PolynomialDivisionAlgorithm,function(poly,plist,order)
local fam,quot,elist,lmp,lmo,lmc,x,y,z,mon,mon2,qmon,noreduce,
      ep,pos,di,rem;
  if IsMonomialOrdering(order) then
    order:=MonomialExtrepComparisonFun(order);
  fi;
  fam:=FamilyObj(poly);
  quot:=List(plist,i->Zero(poly));
  elist:=List(plist,ExtRepPolynomialRatFun);
  lmp:=List(elist,i->LeadingMonomialPosExtRep(fam,i,order));
  lmo:=List([1..Length(lmp)],i->elist[i][lmp[i]]);
  lmc:=List([1..Length(lmp)],i->elist[i][lmp[i]+1]);

  rem:=Zero(poly);
  ep:=ExtRepPolynomialRatFun(poly);
  while Length(ep)>0 do
    # now try whether we can reduce the leading monomial
    x:=LeadingMonomialPosExtRep(fam,ep,order);
    mon:=ep[x];
    y:=1;
    noreduce:=true;
    while y<=Length(plist) and noreduce do
      mon2:=lmo[y];
      #check whether the monomial at position x (leading mon of poly)
      #is a multiple of the y-th leading monomial
      z:=1;
      pos:=1;
      qmon:=[]; # potential quotient
      noreduce:=false;
      while noreduce=false and z<=Length(mon2) and pos<=Length(mon) do
        if mon[pos]>mon2[z] then
          noreduce:=true; # indet in mon2 does not occur in mon -> does not
                          # divide
        elif mon[pos]<mon2[z] then
          Append(qmon,mon{[pos,pos+1]}); # indet only in mon
          pos:=pos+2;
        else
          # the indets are the same
          di:=mon[pos+1]-mon2[z+1];
          if di>0 then
            #divides and there is remainder
            Append(qmon,[mon[pos],di]);
          elif di<0 then
            noreduce:=true; # exponent to small
          fi;
          pos:=pos+2;
          z:=z+2;
        fi;
      od;

      # if there is a tail in mon2 left, cannot divide
      if z<=Length(mon2) then
        noreduce:=true;
      fi;
      y:=y+1;
    od;

    if noreduce=false then
      y:=y-1; # re-correct incremented numbers

      # is there a tail in mon? if yes we need to append it
      if pos<Length(mon) then
        Append(qmon,mon{[pos..Length(mon)]});
      fi;

      # reduce!
      qmon:=PolynomialByExtRepNC(fam,[qmon,ep[x+1]/lmc[y]]); #quotient monomial

      quot[y]:=quot[y]+qmon;
      poly:=poly-qmon*plist[y]; # reduce
    else
      # remove leading monomial
      qmon:=PolynomialByExtRepNC(fam,[mon,ep[x+1]]);
      rem:=rem+qmon;
      poly:=poly-qmon;
    fi;
    ep:=ExtRepPolynomialRatFun(poly);
  od;
  return [rem,quot];
end);

BindGlobal("SyzygyCriterion",function(baslte,i,j,t,B)
local li, lj, lcm, a, b, k;
  lcm:=false;
  for k in [1..t] do
    if k<>i and k<>j and
      (not Set([i,k]) in B) and (not Set([j,k]) in B) then

        if lcm=false then
          li:=baslte[i];
          lj:=baslte[j];
          lcm:=[];
          a:=1;
          b:=1;
          while a<Length(li) and b<Length(lj) do
            if li[a]<lj[b] then
              # li variable is smaller
              Add(lcm,li[a]);
              Add(lcm,li[a+1]);
              a:=a+2;
            elif li[a]>lj[b] then
              # lj-variable is smaller
              Add(lcm,lj[b]);
              Add(lcm,lj[b+1]);
              b:=b+2;
            else
              # same variable
              Add(lcm,li[a]);
              Add(lcm,Maximum(li[a+1],lj[b+1]));
              a:=a+2;
              b:=b+2;
            fi;
          od;
          # add remaining tails. Only one of these loops is run
          while a<Length(li) do
            Add(lcm,li[a]);
            Add(lcm,li[a+1]);
            a:=a+2;
          od;
          while b<Length(lj) do
            Add(lcm,lj[b]);
            Add(lcm,lj[b+1]);
            b:=b+2;
          od;
        fi;

        # does baslte[k] divide?
        li:=baslte[k];
        a:=1;
        b:=1;
        while a<Length(li) and b<Length(lcm) do
          # lcm has extra variables?
          while b<Length(lcm) and li[a]>lcm[b] do
            b:=b+2;
          od;
          # test whether variable OK and variable power not bigger
          if b<Length(lcm) then
            if li[a]=lcm[b] and li[a+1]<=lcm[b+1] then
              a:=a+2;
              b:=b+2;
            else
              # either a has an extra (smaller) variable or a bigger
              # exponent. In both cases division fails which we indicate by
              # only b running out
              b:=Length(lcm)+1;
            fi;
          fi;
        od;
        # if b has variables left or a and b both ran out, we're fine
        if b<Length(lcm) or (b>Length(lcm) and a>Length(li)) then
          return true;
        fi;
    fi;
  od;
  return false;
end);

BindGlobal("GAPGBASIS",MakeImmutable(rec(
  name:="naive GAP version of Buchberger's algorithm",
  GroebnerBasis:=function(elms,order)
  local orderext, bas, baslte, fam, t, B, i, j, s;
    orderext:=MonomialExtrepComparisonFun(order);
    bas:=Filtered(elms,x->not IsZero(x));
    baslte:=List(bas,ExtRepPolynomialRatFun);
    fam:=FamilyObj(bas[1]);
    baslte:=List(baslte,i->i[LeadingMonomialPosExtRep(fam,i,orderext)]);
    t:=Length(bas);
    B:=Concatenation(List([1..t],i->List([1..i-1],j->[j,i])));
    while Length(B)>0 do
      j:=B[1][1];
      i:=B[1][2];
      # remove first entry of B
      Remove(B, 1);

      if Length(Intersection(baslte[i]{[1,3..Length(baslte[i])-1]},
                            baslte[j]{[1,3..Length(baslte[j])-1]}))=0 then
        Info(InfoGroebner,2,"Pair (",i,",",j,") avoided by product criterion");
      elif SyzygyCriterion(baslte,i,j,t,B) then
        Info(InfoGroebner,2,"Pair (",i,",",j,") avoided by chain criterion");
      else
        s:=SPolynomial(bas[i],bas[j],order);
        if InfoLevel(InfoGroebner)<3 then
          Info(InfoGroebner,2,"Spol(",i,",",j,")");
        else
          Info(InfoGroebner,3,"Spol(",i,",",j,")=",s);
        fi;
        s:=PolynomialReducedRemainder(s,bas,orderext);
        if not IsZero(s) then
          Info(InfoGroebner,3,"reduces to ",s);
          Add(bas,s);
          s:=ExtRepPolynomialRatFun(s);
          Add(baslte,s[LeadingMonomialPosExtRep(fam,s,orderext)]);
          t:=t+1;
          # add new pairs
          for i in [1..t-1] do
            Add(B,[i,t]);
          od;
          Info(InfoGroebner,1,"|bas|=",t,", ",Length(B)," pairs left");
        fi;
      fi;
    od;
    return bas;
  end)
  ));

#############################################################################
##
#V  GBASIS
##
##  This variable is assigned to a record which determines which
##  implementation is used to compute Groebner bases. By default it is
##  assigned to `GAPGBASIS', a naive implementation of Buchberger's
##  algorithm, which is only provided for educational purposes. For serious
##  work a better implementation should be used.
GBASIS:=GAPGBASIS;

InstallGlobalFunction(GroebnerBasisNC,
function(elms,order)
  return GBASIS.GroebnerBasis(elms,order);
end);

InstallMethod(GroebnerBasis,"polynomials",true,
  [IsHomogeneousList and IsRationalFunctionCollection,IsMonomialOrdering],0,
function(elms,order)
local ov,i,d;
  # do some tests
  if not ForAll(elms,IsPolynomial) then
    Error("<elms> must be a list of polynomials");
  fi;
  ov:=OccuringVariableIndices(order);
  if ov<>true then
    for i in elms do
      d:=Difference(OccuringVariableIndices(i),ov);
      if Length(d)>0 then
        Error("Ordering is undefined for variables ",
          List(d,j->Indeterminate(DefaultRing([FamilyObj(i)!.zeroCoefficient]),j)));
      fi;
    od;
  fi;
  return GroebnerBasisNC(elms,order);
end);

InstallOtherMethod(GroebnerBasis,"fix function",true,
  [IsObject,IsFunction],0,
function(obj,f)
  if f=MonomialLexOrdering or f=MonomialGrlexOrdering or
    f=MonomialGrevlexOrdering then
    return GroebnerBasis(obj,f());
  fi;
  TryNextMethod();
end);

InstallMethod(StoredGroebnerBasis,"ideal",true,
  [IsPolynomialRingIdeal],0,function(I)
local ord;
  ord:=MonomialGrlexOrdering();
  return [ReducedGroebnerBasis(GeneratorsOfTwoSidedIdeal(I),ord),ord];
end);

InstallMethod(GroebnerBasis,"ideal",true,
  [IsPolynomialRingIdeal,IsMonomialOrdering],0,
function(I,order)
local bas;
  if HasStoredGroebnerBasis(I) then
    bas:=StoredGroebnerBasis(I);
    if IsIdenticalObj(bas[2],order) then return bas[1];fi;
  fi;
  # do some tests
  bas:=ReducedGroebnerBasis(GeneratorsOfIdeal(I),order);
  if not HasStoredGroebnerBasis(I) then
    SetStoredGroebnerBasis(I,[bas,order]);
  fi;
  return bas;
end);

InstallMethod(GroebnerBasis,"ideal with stored GB",true,
  [IsPolynomialRingIdeal and HasStoredGroebnerBasis,IsMonomialOrdering],0,
function(I,order)
  # do some tests
  if not IsIdenticalObj(StoredGroebnerBasis(I)[2],order) then
    TryNextMethod();
  fi;
  return StoredGroebnerBasis(I)[1];
end);

InstallMethod(ReducedGroebnerBasis,"polynomials",true,
  [IsHomogeneousList and IsRationalFunctionCollection,IsMonomialOrdering],0,
function(elms,order)
local orderext, bas, i, l, nomod, pol;
  orderext:=MonomialExtrepComparisonFun(order);
  # do some tests
  bas:=ShallowCopy(GBASIS.GroebnerBasis(elms,order));
  i:=1;
  l:=Length(bas);
  repeat
    nomod:=true;
    while i<=l do
      pol:=PolynomialReducedRemainder(bas[i],
             bas{Difference([1..l],[i])},orderext);
      if pol<>bas[i] then nomod:=false;fi;
      if IsZero(pol) then
        bas[i]:=bas[l];
        Unbind(bas[l]);
        l:=l-1;
      else
        bas[i]:=pol;
        i:=i+1;
      fi;
    od;
  until nomod;
  for i in [1..Length(bas)] do
     bas[i]:=bas[i]/LeadingCoefficientOfPolynomial(bas[i],order);
  od;
  Sort(bas,MonomialComparisonFunction(order));
  return bas;
end);

InstallMethod(ReducedGroebnerBasis,"ideal",true,
  [IsPolynomialRingIdeal,IsMonomialOrdering],0,
function(I,order)
local bas;
  # do some tests
  if HasStoredGroebnerBasis(I)
    and IsIdenticalObj(StoredGroebnerBasis(I)[2],order) then
    bas:=StoredGroebnerBasis(I)[1];
  else
    bas:=GeneratorsOfIdeal(I);
  fi;
  # reduce
  bas:=ReducedGroebnerBasis(bas,order);
  if not HasStoredGroebnerBasis(I) then
    SetStoredGroebnerBasis(I,[bas,order]);
  fi;
  return bas;
end);

InstallOtherMethod(ReducedGroebnerBasis,"fix function",true,
  [IsObject,IsFunction],0,
function(obj,f)
  if f=MonomialLexOrdering or f=MonomialGrlexOrdering or
    f=MonomialGrevlexOrdering then
    return ReducedGroebnerBasis(obj,f());
  fi;
  TryNextMethod();
end);

InstallMethod(\in,"polynomial ideal",true,
  [IsPolynomial,IsPolynomialRingIdeal],0,function(p,I)
local g;
  g:=StoredGroebnerBasis(I);
  p:=PolynomialReducedRemainder(p,g[1],MonomialExtrepComparisonFun(g[2]));
  return IsZero(p);
end);

# We only provide a single GcdOp method (taking three arguments) for the
# general case, and no specialized two argument version, which we usually
# provide to avoid costly construction of the polynomial ring object, simply
# because in this case the cost of Gcd computation dwarfs the cost for
# creating the polynomial ring.
InstallOtherMethod(GcdOp,"multivariate Gcd based on Groebner bases",
  IsCollsElmsElms,[IsPolynomialRing,IsPolynomial,IsPolynomial],0,
# Input: f, g are multivariate polys in R=F[x1,...,xn]
# Output: a gcd of f,g in R
function(R,f,g)
local basis_elt,t,F,vars,vars2,GB,coeff_t;
  F:=CoefficientsRing(R);
  vars:=IndeterminatesOfPolynomialRing(R);
  t:=Indeterminate(F,vars);
  vars2:=Concatenation([t],vars);
  GB:=ReducedGroebnerBasis([t*f,(1-t)*g],MonomialLexOrdering(vars2));
  for basis_elt in GB do
    coeff_t:=PolynomialCoefficientsOfPolynomial(basis_elt,t);
    if Length(coeff_t)=1 then
      return StandardAssociate(f*g/coeff_t[1]);
    fi;
  od;
  return One(F);
end);

InstallOtherMethod(LcmOp,"multivariate Lcm based on Groebner bases",
  IsCollsElmsElms,[IsPolynomialRing,IsPolynomial,IsPolynomial],0,
function(R,f,g)
  return f*g/GcdOp(R,f,g);
end);

BindGlobal("NaiveBuchberger",function(elms,order)
local orderext, bas, baslte, fam, t, B, i, j, s;
  orderext:=MonomialExtrepComparisonFun(order);
  bas:=ShallowCopy(elms);
  baslte:=List(bas,ExtRepPolynomialRatFun);
  fam:=FamilyObj(bas[1]);
  baslte:=List(baslte,i->i[LeadingMonomialPosExtRep(fam,i,orderext)]);
  t:=Length(bas);
  B:=Concatenation(List([1..t],i->List([1..i-1],j->[j,i])));
  while Length(B)>0 do
    i:=B[1]; # take one
    j:=i[1];
    i:=i[2];
      s:=SPolynomial(bas[i],bas[j],order);
      if InfoLevel(InfoGroebner)<3 then
        Info(InfoGroebner,2,"Spol(",i,",",j,")");
      else
        Info(InfoGroebner,3,"Spol(",i,",",j,")=",s);
      fi;
      s:=PolynomialReducedRemainder(s,bas,orderext);
      if not IsZero(s) then
        Info(InfoGroebner,3,"reduces to ",s);
        Add(bas,s);
        s:=ExtRepPolynomialRatFun(s);
        Add(baslte,s[LeadingMonomialPosExtRep(fam,s,orderext)]);
        t:=t+1;
        # add new pairs
        for i in [1..t] do
          Add(B,[i,t]);
        od;
        Info(InfoGroebner,1,"|bas|=",t,", ",Length(B)," pairs left");
      fi;
    # remove first entry of B
    Remove(B,1);
  od;
  return bas;
end);

# setup for quotient rings of polynomial rings

#############################################################################
##
#M  NaturalHomomorphismByIdeal(<R>,<I>)
##
InstallMethod( NaturalHomomorphismByIdeal,"polynomial rings",IsIdenticalObj,
    [ IsPolynomialRing,IsRing],
function(R,I)
local ord,b,ind,num,c,corners,i,j,a,rem,bound,mon,n,monb,dim,sc,k,l,char,hom;
  if not IsIdeal(R,I) then
    Error("I is not an ideal!");
  fi;
  if not IsField(LeftActingDomain(R)) then
    TryNextMethod();
  fi;
  char:=Characteristic(LeftActingDomain(R));
  ord:=MonomialGrlexOrdering();
  b:=GroebnerBasis(I,ord);

  # special case: unit in ideal -- quotient is trivial
  if ForAny(b,IsUnit) then
    a:=Subring(R,[Zero(R)]);
    hom:=MappingByFunction(R,a,x->Zero(a));
    SetImagesSource(hom,a);
    return hom;
  fi;


  # determine all monomials bounded
  ind:=IndeterminatesOfPolynomialRing(R);
  n:=Length(ind);
  num:=List(ind,IndeterminateNumberOfUnivariateRationalFunction);
  c:=List(b,x->ExtRepNumeratorRatFun(LeadingMonomialOfPolynomial(x,ord))[1]);
  corners:=[];
  bound:=List(ind,x->infinity);
  for i in c do
    a:=List(ind,x->0);
    for j in [1,3..Length(i)-1] do
      a[Position(num,i[j])]:=i[j+1];
    od;
    # single variable bound
    if Number(a,x->x<>0)=1 then
      bound[PositionNonZero(a)]:=Sum(a);
    else
      Add(corners,a); # extra corner
    fi;
  od;
  if not ForAll(bound,IsInt) then
    Info(InfoWarning,1,"quotient ring has infinite dimension");
    TryNextMethod();
  fi;

  #run through bounded simplex
  a:=List(ind,x->0);
  mon:=[a];
  i:=Length(a);
  repeat
    a[i]:=a[i]+1;
    while i>0 and a[i]>=bound[i] do
      a[i]:=0;
      i:=i-1;
      if i>0 then
        a[i]:=a[i]+1;
      fi;
    od;

    if i>0 then
      if ForAny(corners,x->ForAll([1..n],j->x[j]<=a[j])) then
        # set last coordinate to become 0 again
        a[n]:=bound[n];
        i:=n;
      else
        Add(mon,ShallowCopy(a));
        i:=Length(a);
      fi;
    fi;
  until i=0;

  # basis of the quotient as vector space
  mon:=List(mon,x->Product([1..n],y->ind[y]^x[y]));
  monb:=Basis(VectorSpace(LeftActingDomain(R),mon));

  # now form the quotient
  dim:=Length(mon);
  sc:=EmptySCTable(dim,0);
  for i in [1..dim] do
    for j in [1..dim] do
      rem:=PolynomialReducedRemainder(mon[i]*mon[j],b,ord);
      a:=rem;
      if not IsZero(a) then
        a:=Coefficients(monb,a);
        if char>0 then
          a:=List(a,Int);
        fi;
        l:=[];
        for k in [1..dim] do
          if not IsZero(a[k]) then
            Add(l,a[k]);
            Add(l,k);
          fi;
        od;
        SetEntrySCTable(sc,i,j,l);
      fi;
    od;
  od;
  l:=List(mon,x->Concatenation("(",
        Filtered(String(x),y->y<>'^' and y<>'*'),")"));
  a:=PositionProperty(mon,IsOne);
  if a<>fail then
    l[a]:="(1)";
  fi;

  a:=AlgebraByStructureConstants(LeftActingDomain(R),sc,l);
  if Length(l)<50 then
    j:=Concatenation("<ring ",String(LeftActingDomain(R)));
    for i in l do
      Append(j,",");
      Append(j,i);
    od;
    Append(j,">");
    SetName(a,j);
  fi;
  #k:=Concatenation([One(R)],IndeterminatesOfPolynomialRing(R));
  k:=IndeterminatesOfPolynomialRing(R);
  l:=[];
  for i in k do
    j:=Position(mon,i);
    if j<>fail then
      Add(l,GeneratorsOfLeftOperatorRing(a)[j]);
    else
      rem:=PolynomialReducedRemainder(i,b,ord);
      rem:=Coefficients(monb,rem);
      Add(l,GeneratorsOfLeftOperatorRing(a)*rem);
    fi;
  od;

  hom:=AlgebraWithOneHomomorphismByImagesNC(R,a,k,l);
  SetIsSurjective(hom,true);
  SetKernelOfAdditiveGeneralMapping(hom,I);

  j:=AlgebraWithOneGeneralMappingByImages(a,R,l,k);
  SetInverseGeneralMapping(hom,j);

  return hom;
  #x*y^3-x^2,x^3*y^2-y

end);


# BindGlobal("CANGB",function(elms,order)
#local orderext, bas, i, l, nomod, pol;
#  orderext:=MonomialExtrepComparisonFun(order);
#  # do some tests
#  bas:=ShallowCopy(elms);
#  i:=1;
#  l:=Length(bas);
#  repeat
#    nomod:=true;
#    while i<=l do
#      pol:=PolynomialReducedRemainder(bas[i],
#             bas{Difference([1..Length(bas)],[i])},orderext);
#      if pol<>bas[i] then nomod:=false;fi;
#      if IsZero(pol) then
#        bas[i]:=bas[l];
#        Unbind(bas[l]);
#        l:=l-1;
#      else
#        bas[i]:=pol;
#        i:=i+1;
#      fi;
#    od;
#  until nomod;
#  for i in [1..Length(bas)] do
#     bas[i]:=bas[i]/LeadingCoefficientOfPolynomial(bas[i],order);
#  od;
#  Sort(bas,MonomialComparisonFunction(order));
#  return bas;
#end);
#
#DoTest:=function(l,ord)
#local a,b,t1,t2;
#  t1:=Runtime();
#  a:=NaiveBuchberger(l,ord);
#  t1:=Runtime()-t1;
#  t2:=Runtime();
#  b:=GroebnerBasis(l,ord);
#  t2:=Runtime()-t2;
#  a:=CANGB(a,ord);
#  b:=CANGB(b,ord);
#  return [t1,t2,a=b];
#end;

[ Verzeichnis aufwärts0.65unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge