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


Quelle  polynomials.gi   Sprache: unbekannt

 
#############################################################################
##
#W  polynomials.gi              Manuel Delgado <mdelgado@fc.up.pt>
#W                          Pedro A. Garcia-Sanchez <pedro@ugr.es>
##
##
#Y  Copyright 2015 by Manuel Delgado and  Pedro Garcia-Sanchez
#Y  We adopt the copyright regulations of GAP as detailed in the
#Y  copyright notice in the GAP manual.
##
#############################################################################

#################################################
##
#F NumericalSemigroupPolynomial(s,x)
## s is a numerical semigroup, and x a variable (or a value)
## returns the polynomial (1-x)\sum_{s\in S}x^s
##
##################################################
InstallGlobalFunction(NumericalSemigroupPolynomial, function(s,x)
 local gaps, p;

    if not IsNumericalSemigroup(s) then
        Error("The first argument must be a numerical semigroup.\n");
    fi;

 gaps:=GapsOfNumericalSemigroup(s);
 p:=List(gaps, g-> x^g);
 return 1+(x-1)*Sum(p);
end);

##############################################################
##
#F IsNumericalSemigroupPolynomial(f) detects
## if there exists S a numerical semigroup such that P_S(x)=f
## f is a polynomial
##############################################################
InstallGlobalFunction(IsNumericalSemigroupPolynomial, function(f)
local x, coef, gaps, small,  s, p,c;

if not(IsUnivariatePolynomial(f)) then
  Error("The argument must be a univariate polynomial");
fi;

if not(IsListOfIntegersNS(CoefficientsOfUnivariatePolynomial(f))) then
  return false;
fi;

if not(IsOne(LeadingCoefficient(f))) then
  return false;
fi;


x:=IndeterminateOfUnivariateRationalFunction(f);
p:=(f-1)/(x-1);
if not(IsUnivariatePolynomial(p)) then
  return false;
fi;
coef:=CoefficientsOfUnivariatePolynomial(p);
if Set(coef)<>Set([0,1]) then
  return false;
fi;
c:=Length(coef);
gaps:=Filtered([0..c-1], i->coef[i+1]<>0);
#Print("gaps ", gaps,"\n");
small:=Difference([0..c],gaps);
#Print("small ",small,"\n");

return RepresentsSmallElementsOfNumericalSemigroup(small);
end);

##############################################################
##
#F NumericalSemigroupFromNumericalSemigroupPolynomial(f) outputs
## a numerical semigroup S such that P_S(x)=f; error if no such
## S exists
## f is a polynomial
##############################################################
InstallGlobalFunction(NumericalSemigroupFromNumericalSemigroupPolynomial, function(f)
local x, coef, gaps,small, s, p,c;

if not(IsUnivariatePolynomial(f)) then
 Error("The argument must be a univariate polynomial");
fi;

if not(IsListOfIntegersNS(CoefficientsOfUnivariatePolynomial(f))) then
 Error("The argument is not a numerical semigroup polynomial");
fi;

if not(IsOne(LeadingCoefficient(f))) then
 Error("The argument is not a numerical semigroup polynomial");
fi;


x:=IndeterminateOfUnivariateRationalFunction(f);
p:=(f-1)/(x-1);
if not(IsUnivariatePolynomial(p)) then
 Error("The argument is not a numerical semigroup polynomial");
fi;
coef:=CoefficientsOfUnivariatePolynomial(p);
if Set(coef)<>Set([0,1]) then
 Error("The argument is not a numerical semigroup polynomial");
fi;
c:=Length(coef);
gaps:=Filtered([0..c-1], i->coef[i+1]<>0);
small:=Difference([0..c],gaps);
if not(RepresentsSmallElementsOfNumericalSemigroup(small)) then
 Error("The argument is not a numerical semigroup polynomial");
fi;
return NumericalSemigroupBySmallElements(small);
end);

###################################################
#F HilbertSeriesOfNumericalSemigroup(s,x)
## Computes the Hilber series of s in x : \sum_{s\in S}x^s
###################################################
InstallGlobalFunction(HilbertSeriesOfNumericalSemigroup,function(s,x)
 local m,ap;
    if not IsNumericalSemigroup(s) then
        Error("The first argument must be a numerical semigroup.\n");
    fi;

 if HasAperyList(s) then #uses J.Ramirez-Alfonsin trick
  m:=MultiplicityOfNumericalSemigroup(s);
  ap:=AperyListOfNumericalSemigroup(s);
  return 1/(1-x^m)*Sum(List(ap, w->x^w));
 fi;
 return NumericalSemigroupPolynomial(s,x)/(1-x);
end);


######################################################
##
#F Computes the Graeffe polynomial of p
##  see for instance [BD-cyclotomic]
##
######################################################
InstallGlobalFunction(GraeffePolynomial,function(p)
 local coef, h, g, i, f1,x;

 if not(IsUnivariatePolynomial(p)) then
  Error("The argument must be a univariate polynomial");
 fi;
 x:=IndeterminateOfUnivariateRationalFunction(p);
 coef:=CoefficientsOfUnivariatePolynomial(p);
 h:=[]; g:=[];
 for i in [1..Length(coef)] do
  if (i-1) mod 2 = 0 then
   Add(g,coef[i]);
  else
   Add(h,coef[i]);
  fi;
 od;
 #Print(g," ,",h,"\n");
 g:=UnivariatePolynomial(Rationals,g);
 h:=UnivariatePolynomial(Rationals,h);
 f1:=Value(g,x)^2-x*Value(h,x)^2;
 return f1/LeadingCoefficient(f1);
end);


#####################################################
##
#F IsCyclotomicPolynomial(f) detects
## if f is a cyclotomic polynomial using the method explained in
## BD-cyclotomic
#####################################################
InstallGlobalFunction(IsCyclotomicPolynomial,function(f)
 local f1, x, f2, mf;

 if not(IsUnivariatePolynomial(f)) then
  Error("The argument must be a univariate polynomial");
 fi;

 if not(IsListOfIntegersNS(CoefficientsOfUnivariatePolynomial(f))) then
  Error("The polynomial has not integer coefficients");
 fi;

 if not(IsOne(LeadingCoefficient(f))) then
  return false;
 fi;

 if not(IsIrreducible(f)) then
  return false;
 fi;

 x:=IndeterminateOfUnivariateRationalFunction(f);
 f1:=GraeffePolynomial(f);
 if (f=f1) then
  return true;
 fi;

 mf:=Value(f,-x);# Print(f1, ", ",f, ",", mf,"\n");

 if ((f1=mf) or (f1=-mf)) and IsCyclotomicPolynomial(mf/LeadingCoefficient(mf)) then
  return true;
 fi;

 f2:=Set(Factors(f1))[1];
 if f1=f2^2 and IsCyclotomicPolynomial(f2/LeadingCoefficient(f2)) then
  return true;
 fi;
 return false;
end);

########################################################################
##
#F IsKroneckerPolynomial(f) decides if
##   f is a Kronecker polynomial, that is,   a monic polynomial with integer coefficients
##   having all its roots in the unit circunference, equivalently, is a product of
##   cyclotomic polynomials
## New implementation with A. Herrera-Poyatos that does not need factoring
#########################################################################
InstallGlobalFunction(IsKroneckerPolynomial,function(f)

 local x, sf, f1, fs, fn, fp, factors_graeffe;

 if not(IsUnivariatePolynomial(f)) then
   Error("The argument must be a polynomial in one variable");
 fi;

 if IsZero(f) then
   return false;
 fi;

 x:=IndeterminateOfLaurentPolynomial(f);

 # Take the largest square free divisor.
 sf:=f/Gcd(f,Derivative(f));

 # Remove the factors x, x+1 and x-1.
 if Value(sf, 0) = 0 then
   sf := sf / x;
 fi;
 if Value(sf, 1) = 0 then
   sf := sf/(x-1);
 fi;
 if Value(sf, -1) = 0 then
   sf := sf/(x+1);
 fi;

 # Check if the polynomial is a constant.
 if Degree(sf) = 0 then
   return true;
 fi;

 # Check if the polynomial has even degree and is self reciprocal.
 if Degree(sf) mod 2 <> 0 or not(IsSelfReciprocalUnivariatePolynomial(sf)) then
   return false;
 fi;

 # Apply the graeffe method to sf. Note that if sf(+-x) = f1, then
 # sf is Kronecker.
 f1:= GraeffePolynomial(sf);
 if sf = f1 then
   return true;
 fi;
 if Value(sf,-x) = f1 then
   return true;
 fi;

 # Assume that sf is Kronecker.
 # Find the descomposition of sf = fs*fp*fn, where:
 # - fs is the part of sf which verifies Graeffe(fs) = (g(x))^2
 # - fp is the part of sf which verifies Graeffe(fs) = fs.
 # - fn is the part of sf which vefifies Graeffe(fs)(x) = fs(-x).
 fs := Value(Gcd(Derivative(f1), f1), x^2);
 fp := Gcd(sf / fs, f1);
 fn := sf / (fs * fp);

 factors_graeffe := Difference([fs, fp, fn], [1+0*x]);

 if Length(factors_graeffe) = 1 then
   if IsOne(fs) then
     # We must have f = fp or f = fs, but we obtained Graeffe(sf) != sf,
     # Graeffe(sf) != sf(-x), a contradiction. Hence sf is not Kronecker.
     return false;
   else
     # sf is Kronecker if and only if f1 / fs(\sqrt{x}) is Kronecker.
     return IsKroneckerPolynomial(f1 /  Gcd(f1,Derivative(f1)));
   fi;
 else
   # sf is Kronecker if and only if fs, fp and fn are Kronecker.
   return ForAll(factors_graeffe, IsKroneckerPolynomial);
 fi;
end);


###########################################
##
#P IsCyclotomicNumericalSemigroup(s)
## Checks if the polynomial fo s is Kronecker
###########################################
InstallMethod(IsCyclotomicNumericalSemigroup,
 "Detects if the polinomial semigroup of the semigroup is Kronecker",
 [IsNumericalSemigroup],
 function(s)
 local x, f;
 x:=X(Rationals,"x");
 f:=NumericalSemigroupPolynomial(s,x);
 return IsKroneckerPolynomial(f);# ForAll(Factors(f),IsCyclotomicPolynomial);
end);

InstallTrueMethod(IsCyclotomicNumericalSemigroup, IsACompleteIntersectionNumericalSemigroup);

#####################################################
##
#F IsSelfReciprocalUnivariatePolynomial(p)
## Checks if the univariate polynomial p is selfreciprocal
## New implementation by A. Herrera-Poyatos
#####################################################
InstallGlobalFunction(IsSelfReciprocalUnivariatePolynomial,function(p)
 local cf;

 if not(IsUnivariatePolynomial(p)) then
  Error("The argument must be a polynomial\n");
 fi;

 # Check if the polynomial is self-reciprocal.
 cf:=CoefficientsOfUnivariatePolynomial(p);
 return cf=Reversed(cf);
end);

#################################################################
##
# F SemigroupOfValuesOfPlaneCurveWithSinglePlaceAtInfinity(f)
##  Computes the semigroup of values {mult(f,g) | g curve} of a plane curve
##   with one place at the infinity in the variables X(Rationals,1) and X(Rationals,2)
##  f must be monic on X(Rationals(2))
##  SemigroupOfValuesOfPlaneCurveWithSinglePlaceAtInfinity(f,"all")
##    The same as above, but the output are the approximate roots and
##    delta-sequence
##
#################################################################
InstallGlobalFunction(SemigroupOfValuesOfPlaneCurveWithSinglePlaceAtInfinity, function(arg)
 local monomials, degree, degreepol, polexprc, polexprs, polexpr, app, tt1, sv;
 #returns the set of monomials of a polynomial
 monomials:=function(f)
  local term, out,temp;
  out:=[];
  if IsZero(f) then
   return ([0]);
  fi;
  temp:=f;
  while not(IsZero(temp)) do
   term:=LeadingTermOfPolynomial(temp,MonomialLexOrdering());
   Add(out,term);
   temp:=temp-term;
  od;
  return out;

 end;

 #returns the total weighted degree of a monomial wrt l
 degree:=function(mon,l)
  local n;
  n:=Length(l);
  if IsRat(mon) then
   return 0;
  fi;
  return Sum(List([1..n], i->DegreeIndeterminate(mon,i)*l[i]));
 end;

 #returns the total weighted degree of a polynomial wrt l
 degreepol:=function(pol,l)
  return Maximum(List(monomials(pol), t->degree(t,l)));
 end;
 #finds an expression of f in terms of p, and outputs it as a polynomial in x, var is the list of variables in f and p
 polexpr:=function(f,p,var,x)
  local rem, quo, pr;

  pr:=PolynomialDivisionAlgorithm(f,[p],MonomialLexOrdering(var));
  rem:=[pr[1]];
  quo:=pr[2][1];
  while not(IsZero(quo)) do
   pr:=PolynomialDivisionAlgorithm(quo,[p],MonomialLexOrdering(var));
   Add(rem,pr[1]);
   quo:=pr[2][1];
  od;
  return Sum(List([1..Length(rem)],i->rem[i]*x^(i-1)));
 end;
 #uses the previous function to apply recurrently the procedure for all polynomials in ps and variables in xs
 polexprs:=function(f,ps,var,xs)
  local i, len, out;

  len:=Length(ps);
  out:=f;
  for i in [1..len] do
   out:=polexpr(out,ps[i],var,xs[i]);
  od;
  return out;
 end;
 #expression of f in terms of p; both in variables x and y...
 polexprc:=function(f,p)
  local rem, quo, pr;

  pr:=PolynomialDivisionAlgorithm(f,[p],MonomialLexOrdering([X(Rationals,2),X(Rationals,1)]));
  rem:=[pr[1]];
  quo:=Value(pr[2][1],[],[]);
  while not(IsZero(quo)) do
   pr:=PolynomialDivisionAlgorithm(quo,[p],MonomialLexOrdering([X(Rationals,2),X(Rationals,1)]));
   Add(rem,pr[1]);
   quo:=pr[2][1];
  od;
  return Reversed(rem);
 end;
 ##TT1
 tt1:=function(f,g,y)
  local d;
  d:=DegreeIndeterminate(f,y)/DegreeIndeterminate(g,y);
  if d>0 then
   return g+polexprc(f,g)[2]/d;
  fi;
  return f;
 end;
 #approximate root
 app:=function(f,y,d)
  local G,S,F,P,e,t,coef;

  e:=DegreeIndeterminate(f,y)/d;
  G:=tt1(f,y^e,y);
  S:=polexprc(f,G);
  P:=S[2];
  #tschirnhausen transform
  while not(IsZero(P)) do
   F:=G+P/e;
   G:=tt1(f,F,y);
   S:=polexprc(f,G);
   P:=S[2];
  od;
  return G;
 end;
 #semigroup of values
 sv:=function(f)
  local  m, d,dd, n,g,it, max, lt, e, coef, deg, tsti,rd, var, id, R, aroots;

  if not(IsPolynomial(f)) then
   Error("The argument must be a polynomial\n");
  fi;

  R:=PolynomialRing(Rationals,[X(Rationals,1),X(Rationals,2)]);
  if not(f in R) then
      Error("The argument must be a polynomial in ", R,"\n");
  fi;

  coef:=PolynomialCoefficientsOfPolynomial(f,X(Rationals,1));
  if not(IsConstantRationalFunction(coef[Length(coef)])) then
   Error("The polynomial does not have a single place at infinity or the leading coefficient in ", X(Rationals,1)," is not a rational number\n");
  fi;
  coef:=PolynomialCoefficientsOfPolynomial(f,X(Rationals,2));
  if not(IsConstantRationalFunction(coef[Length(coef)])) then
   Error("The polynomial does not have a single place at infinity or or the leading coefficient in ", X(Rationals,2)," is not a rational number\n");
  fi;
  f:=f/coef[Length(coef)];
  m:=[];
  coef:=PolynomialCoefficientsOfPolynomial(f,X(Rationals,2));
  Info(InfoNumSgps,2,"f ",f);
  Info(InfoNumSgps,2,"f ",coef);
  it:=coef[1];
  if IsZero(it) then
   Error("The polynomial is not irreducible\n");
  fi;

  m[1]:=DegreeIndeterminate(f,X(Rationals,2));
  m[2]:=DegreeIndeterminate(PolynomialCoefficientsOfPolynomial(f,X(Rationals,2))[1],X(Rationals,1));
  n:=2;
  d:=Gcd(m);
  e:=m[1]/d;
  g:=f;
  var:=[X(Rationals,2),X(Rationals,1)];
  aroots:=[X(Rationals,2)];
  while d>1  do
   Add(var,X(Rationals,n+1));
   rd:=app(f,X(Rationals,2),d);
   Add(aroots,rd);
   g:=polexprs(f,Reversed(aroots),var,Reversed(List([2..n+1],i->X(Rationals,i))));
   coef:=PolynomialCoefficientsOfPolynomial(g, X(Rationals,n+1));
   Info(InfoNumSgps,2,"We obtain coefficients: ",coef);
   it:=coef[1];
   Info(InfoNumSgps,2,"Independent term ", it);
   max:=degreepol(it,m/Gcd(m));
   if (max=0) then #or (d=Gcd(d,max)) or (max in m) then
    Error("The polynomial is not irreducible or it has not a single place at infinity (deg 0)\n");
   fi;
   #irreducibility test
   tsti:=First(coef{[2..Length(coef)]}, t->degreepol(t,m/d)>=max);
   if tsti<>fail then
    Info(InfoNumSgps,1,"Term ", tsti," produces error");
    Error("The polynomial is not irreducible", "\n");
   fi;
   dd:=Gcd(d,max);
   Info(InfoNumSgps,2,"New candidate: ",max);
   if (d=Gcd(d,max)) or (max in m) then
    Error("The polynomial is not irreducible or it has not a single place at infinity\n");
   fi;
   m[n+1]:=max;
   if(m[n]*Gcd(m{[1..n-1]})<=max*d)then
    Error("The polynomial is not irreducible (not subdescending sequence)", m,"\n");
   fi;
   e:=d/Gcd(d,max);
   d:=dd;
   n:=n+1;
  od;
  return [m,aroots];
 end;

 if Length(arg)=1 then
  return NumericalSemigroup(sv(arg[1])[1]);
 fi;
 if Length(arg)=2  and arg[2] = "all" then
  return sv(arg[1]);
 fi;
 Error("Wrong number of arguments\n");
end);


#########################################################################
##
#F IsDeltaSequence(l)
## tests whether or not l is a \delta-sequence (see for instancd [AGS14])
#########################################################################
InstallGlobalFunction(IsDeltaSequence,function(l)
 local d,e,h;

 if not(IsListOfIntegersNS(l)) then
  Error("The argument must be a list of positive integers\n");
 fi;
 if Gcd(l)<>1 then
  Info(InfoNumSgps,2,"The gcd of the list is not one");
  return false;
 fi;
 h:=Length(l)-1;
 d:=List([1..h+1], i->Gcd(l{[1..i]}));
 e:=List([1..h], i->d[i]/d[i+1]);
 if Length(l)=1 then
  return true;
 fi;
 if (l[1]<=l[2]) or (d[2]=l[2]) then
  Info(InfoNumSgps,2,"Either the first element is smaller than or equal to the second, or the gcd of the first to equals the second");
  return false;
 fi;
 if Length(Set(d))<h+1 then
  Info(InfoNumSgps,2,"The list of gcds is not strctitly decreasing");
  return false;
 fi;

 return ForAll([1..h], i->l[i+1]/Gcd(l{[1..i+1]}) in NumericalSemigroup(l{[1..i]}/Gcd(l{[1..i]})))
     and
     ForAll([2..h], i->l[i]*Gcd(l{[1..i-1]}) >l[i+1]*Gcd(l{[1..i]}));
end);


#########################################################
##
#F DeltaSequencesWithFrobeniusNumber(f)
##   Computes  the list of delta-sequences with Frobenius number f
##
#########################################################
InstallGlobalFunction(DeltaSequencesWithFrobeniusNumber,function(f)
 local abs, test;

 if not(IsInt(f)) then
  Error("The argument must be an integer\n");
 fi;

 if (f<-1) or IsEvenInt(f) then
  return [];
 fi;

 if f=-1 then
  return [[1]];
 fi;

 abs:=function(f)
  local dkcand, dk, rk, fp, candr, bound, total;

  if (f<-1) or (f mod 2=0) then
   return [];
  fi;

  if (f=-1) then
   return [[1]];
  fi;

  if (f=1) then
   return [[2,3],[3,2]];
  fi;

  total:=[[f+2,2],[2,f+2]];
  for rk in Reversed([2..f-1]) do
   bound:=(Int((f+1)/(rk-1)+1));
   dkcand:=Filtered([2..bound],d->(Gcd(d,rk)=1)and((f+rk) mod d=0));
   for dk in dkcand do
    fp:=(f+rk*(1-dk))/dk;
    candr:=Filtered(abs(fp), l->  rk in NumericalSemigroup(l));
    candr:=List(candr, l-> Concatenation(l*dk, [rk]));
    candr:=Filtered(candr, test);
    candr:=Filtered(candr,l->l[1]>l[2]);
    total:=Union(total,candr);
   od;
  od;
  return total;
 end;

 test:=function(l)
  local len;
  len:=Length(l);
  return ForAll([3..len], k-> l[k-1]*Gcd(l{[1..k-2]})>l[k]*Gcd(l{[1..k-1]}));
 end;

 return Difference(abs(f),[[2,f+2]]);
end);

#####################################################
##
#F CurveAssociatedToDeltaSequence(l)
##  computes the curve associated to a delta-sequence l in
##  the variables X(Rationals,1) and X(Rationals,2)
##  as explained in [AGS14]
##
#####################################################
InstallGlobalFunction(CurveAssociatedToDeltaSequence,function(l)
 local n, d, f, fact,facts, g, e, k, ll, len, dd, x,y;

 if not(IsDeltaSequence(l)) then
  Error("The sequence is not valid\n");
 fi;
 x:=X(Rationals,1);
 y:=X(Rationals,2);
 len:=Length(l);
 if len<2 then
  Error("The sequence must have at least two elements\n");
 fi;
 if Gcd(l)<>1 then
  Error("The sequence must have gcd equal to one\n");
 fi;
 if len=2 then
  return y^(l[1])-x^(l[2]);
 fi;

 e:=List([1..len-1],k->Gcd(l{[1..k]})/Gcd(l{[1..k+1]}));
 g:=[]; g[1]:=x; g[2]:=y;
 for k in [2..len] do
  d:=Gcd(l{[1..k-1]});
  dd:=Gcd(l{[1..k]});
  ll:=l{[1..k-1]}/d;
  fact:=First(FactorizationsIntegerWRTList(l[k]/dd, ll),ff->ForAll([2..k-1], i->ff[i]<e[i-1]));

  if fact=fail then
   Error("The sequence is not valid\n");
  fi;
  g[k+1]:=g[k]^e[k-1]-Product(List([1..k-1], i->g[i]^fact[i]));
  Info(InfoNumSgps,2,"Temporal curve: ",g[k+1]);
 od;
 return g[Length(g)];
end);

#################################################################
##
#F SemigroupOfValuesOfCurve_Local(arg)
## Computes the semigroup of values of R=K[pols],
## that is, the set of possible order of series in this ring
## pols is a set of polynomials in a single variable
## The semigroup of values is a numerical semigroup if l(K[[x]]/R) is finite
## If this length is not finite, the output is fail
## If the second argument "basis" is given, then the output is a basis B of
## R such that o(B) minimally generates o(R), and it is reduced
## If the second argument is an integer, then the output is a polynomial f in R
## with o(f) that value (if there is none, then the output is fail)
## Implementation based in [AGSM14]
###########################################################
InstallGlobalFunction(SemigroupOfValuesOfCurve_Local, function(arg)
    local G, F, n, T, max, s, d, newG, c, kernel,var, tomoniclocal, order, subduction, t,tt, TT, narg,val,facts,pols, msg,reduce;

    ### the order of the series (polynomial)
    order:=function(p)
        local cl;

        if IsInt(p) or IsZero(p) then
            return 0;
        fi;

        cl:=CoefficientsOfUnivariatePolynomial(p);
        return First([1..Length(cl)], i->cl[i]<>0)-1;
    end;

    #### transforms to monic
    tomoniclocal:=function(p)
        local cl;
        if IsZero(p) then
            return 0*X(Rationals,var);
        fi;
        if IsConstantRationalFunction(p) or IsRat(p) then
            return 1;
        fi;
        cl:=CoefficientsOfUnivariatePolynomial(p);
        return p/First(cl,i->i<>0);
    end;

    #### subduction: tries to express p as a polynomial in pols
    #### pols are supposed to be monic
    subduction:=function(p)
        local initial, facts, ord;

        ord:=order(p);

        if d<>1 and (ord mod d)<>0 then
          return p;
        fi;

        if order(p)=0 then
            return 0*X(Rationals,var);
        fi;

        if order(p)>c then
          if d=1 then
            return 0*X(Rationals,var);
          else
            return p;
          fi;
        fi;

        initial:=List(F,order);

        facts:=FactorizationsIntegerWRTList(order(p), initial);
        if facts=[] then
            return p;
        fi;

        Info(InfoNumSgps,2,"Reducing ",p, " to ",
             tomoniclocal(p-Product(List([1..Length(F)],i->F[i]^(facts[1][i])))));

        return subduction(tomoniclocal(p-Product(List([1..Length(F)],i->F[i]^(facts[1][i])))));
    end;

    #### reduces the elements in the minimal basis F, p is monic

    reduce:=function(p)
        local ords, cfs, cf, fact, reduced, head, tail;

        head:=X(Rationals,var)^order(p);
        tail:=p-head;

        ords:=List(F,order);

        repeat
            reduced:=false;
            #Print(p," ");

            cfs:=CoefficientsOfUnivariatePolynomial(tail);
            cf:=First([1..Length(cfs)], i->(cfs[i]<>0) and ((i-1) in s));


            if cf<>fail then
                fact:=FactorizationsIntegerWRTList(cf-1,ords)[1];
                tail:=(tail-cfs[cf]*Product(List([1..Length(F)],i->F[i]^(fact[i])))) mod X(Rationals,var)^c;
                cfs:=CoefficientsOfUnivariatePolynomial(tail);
            else
                reduced:=true;
            fi;
        until reduced;
        return head+tail;


    end;


    #### computes the relations among the polynomials in pols
    kernel:=function(pols)
        local  p,  msg,  ed,  mp, minp, eval, candidates, c, pres, rclass, exps;


        eval:=function(pair)
            local m1,m2;
            m1:=tomoniclocal(Product(List([1..ed],i-> pols[i]^pair[1][i])));
            m2:=tomoniclocal(Product(List([1..ed],i-> pols[i]^pair[2][i])));
            return tomoniclocal(-m1+m2);
        end;

        msg:=List(pols,order);
        ed:=Length(msg);
        if ed=0 then
            return [];
        fi;
        minp:=GeneratorsOfKernelCongruence(List(msg,x->[x]));
        Info(InfoNumSgps,2,"The exponents of the binomials of the kernel are ",minp);
        # Contrary to the global case, here it is faster not to compute a minimal presentation
        # candidates:=Set(minp, x->x[1]*msg);
        # pres:=[];
        # for c in candidates do
        #     exps:=FactorizationsIntegerWRTList(c,msg);
        #     rclass:=RClassesOfSetOfFactorizations(exps);
        #     if Length(rclass)>1 then
        #         pres:=Concatenation(pres,List([2..Length(rclass)],
        #                       i->[rclass[1][1],rclass[i][1]]));
        #     fi;
        # od;
        return List(minp,p->eval(p));
    end; #end of kernel

    narg:=Length(arg);

    if narg=2 then
        pols:=arg[1];
        val:=arg[2];
        if not(IsInt(val)) and not(val="basis") then
           Error("The second argument must be an integer or the string 'basis'");
        fi;
    fi;
    if narg=1 then
        pols:=arg[1];
    fi;

    if narg>2 then
        Error("Wrong number of arguments (two or one)");
    fi;



    if not(IsHomogeneousList(pols)) then
        Error("The argument must be a list of polynomials.");
    fi;

    if not(ForAll(pols, IsUnivariatePolynomial)) then
        Error("The argument must be a list of polynomials.");
    fi;
    if Length(Set(pols, IndeterminateOfLaurentPolynomial))<>1 then
        Error("The arguments must be polynomials in the same variable; constants not allowed nor the empty list.");
    fi;

    var:=IndeterminateNumberOfLaurentPolynomial(pols[1]);

    F:=ShallowCopy(pols);
    Sort(F,function(a,b) return order(a)< order(b); end);
    F:=List(F,tomoniclocal);
    G:=List(F,order);
    n:=0;

    while true do
        d:=Gcd(G);
        s:=NumericalSemigroup(G/d);
        c:=d*ConductorOfNumericalSemigroup(s);
        T:=kernel(F);
        T:=Filtered(T, x->not(IsZero(x)));
        Info(InfoNumSgps,2,"The kernel evaluated in the polynomials is ",T);
        T:=Set(T,subduction);
        T:=Filtered(T, x->not(IsZero(x)));
        Info(InfoNumSgps,2,"After subduction: ",T);
        if Gcd(G) = 1 then
            T:=Filtered(T, t->order(t)<c);
        fi;

        if T=[] or F=Union(F,T) then
            d:=Gcd(G);
            if d=1 then
                s:=NumericalSemigroup(G);
                if narg=1 then
                    return s;
                fi;
                msg:=MinimalGeneratingSystem(s);
                F:=Filtered(F,f->order(f) in msg);
                if val="basis" then
                    return List(F,reduce);
                fi;

                if IsInt(val) then
                    Info(InfoNumSgps,2,"The generators of the algebra are ",F);
                    facts:=FactorizationsIntegerWRTList(val,List(F,order));
                    if facts=[] then
                        return fail;
                    fi;
                    return reduce(Product(List([1..Length(facts[1])],i->F[i]^facts[1][i])));
                fi;
            fi;
            Info(InfoNumSgps,2,"The monoid is not a numerical semigroup and it is generated by ",
                 G);
            #d*MinimalGeneratingSystem(NumericalSemigroup(G/d)));
            #return fail;
        fi;
        Info(InfoNumSgps,2,"Adding ",T," to my list of polynomials");
        F:=Union(F,T);
        newG:=Set(T,order);
        G:=Union(G,newG);
        Info(InfoNumSgps,2,"The set of possible values uptates to ",G);
        n:=n+1;
        d:=Gcd(G);
        s:=NumericalSemigroup(G/d);
        Info(InfoNumSgps,2,"Small elements ",d*SmallElements(s));
    od;

    return fail;
end);

#################################################################
##
#F SemigroupOfValuesOfCurve_Global(arg)
## Computes the semigroup of values of R=K[pols],
## that is, the set of possible degrees of polynomials in this ring
## pols is a set of polynomials in a single variable
## The semigroup of values is a numerical semigroup if l(K[x]/R) is finite
## If this length is not finite, the output is fail
## If the second argument "basis" is given, then the output is a basis B of
## R such that deg(B) minimally generates deg(R), and it is reduced
## If the second argument is an integer, then the output is a polynomial f in R
## with deg(f) that value (if there is none, then the output is fail)
## Implementation based in [AGSM14]
###########################################################
InstallGlobalFunction(SemigroupOfValuesOfCurve_Global, function(arg)
    local G, F, n, T, max, s, d, newG, c, kernel,var, tomonicglobal, degree, subduction, pols, val, narg, degs, facts, reduce, msg;

    ### the degree of the polynomial
    degree:=function(p)
        return DegreeOfUnivariateLaurentPolynomial(p);

    end;

    #### transforms to monic
    tomonicglobal:=function(p)
        if IsZero(p) then
            return 0*X(Rationals,1);
        fi;
        return p/LeadingCoefficient(p);
    end;

    #### subduction: tries to express p as a polynomial in pols
    #### pols are supposed to be monic
    subduction:=function(p)
        local initial, facts;


        if IsZero(p) then
            return p;
        fi;

        if degree(p)=0 then
            return 0*X(Rationals,1);
        fi;

        initial:=List(F,degree);

        facts:=FactorizationsIntegerWRTList(degree(p), initial);
        if facts=[] then
            return p;
        fi;

        Info(InfoNumSgps,2,"Reducing ",p, " to ",
             tomonicglobal(p-Product(List([1..Length(F)],i->F[i]^(facts[1][i])))));

        return subduction(tomonicglobal(
          p-Product(List([1..Length(F)],i->F[i]^(facts[1][i])))));
    end;

    #### reduces the elements in the minimal basis F, p is monic

    reduce:=function(p)
    local degs, cfs, cf, fact, reduced, head, tail;

    head:=X(Rationals,var)^degree(p);
    tail:=p-head;

    degs:=List(F,degree);

    repeat
      reduced:=false;
      #Print(p," ");

      cfs:=CoefficientsOfUnivariatePolynomial(tail);
      cf:=First([1..Length(cfs)], i->(cfs[i]<>0) and ((i-1) in s));
      #Error("blabla");
      #Print("cf",cf,"\n");
      if cf<>fail then
        fact:=FactorizationsIntegerWRTList(cf-1,degs)[1];
        tail:=(tail-cfs[cf]*Product(List([1..Length(F)],i->F[i]^(fact[i]))));
        cfs:=CoefficientsOfUnivariatePolynomial(tail);
      else
        reduced:=true;
      fi;
    until reduced;

    return head+tail;
    end;


    #### computes the relations among the polynomials in pols
    kernel:=function(pols)
        local  p,  msg,  ed,  mp, minp, eval, candidates, c, pres, rclass, exps;

        eval:=function(pair)
            local m1,m2;
            m1:=tomonicglobal(Product(List([1..ed],i-> pols[i]^pair[1][i])));
            m2:=tomonicglobal(Product(List([1..ed],i-> pols[i]^pair[2][i])));
            return tomonicglobal(-m1+m2);
        end;

        msg:=List(pols,degree);
        ed:=Length(msg);
        if ed=0 then
            return [];
        fi;

        minp:=GeneratorsOfKernelCongruence(List(msg,x->[x]));
        Info(InfoNumSgps,2,"The exponents of the binomials of the kernel are ",minp);
        candidates:=Set(minp, x->x[1]*msg);
        pres:=[];
        for c in candidates do
            exps:=FactorizationsIntegerWRTList(c,msg);
            rclass:=RClassesOfSetOfFactorizations(exps);
            if Length(rclass)>1 then
                pres:=Concatenation(pres,List([2..Length(rclass)],
                              i->[rclass[1][1],rclass[i][1]]));
            fi;
        od;
        return List(pres,p->tomonicglobal(eval(p)));


    end; #end of kernel

    narg:=Length(arg);

    if narg>2 then
        Error("Wrong number of arguments (two or one)");
    fi;
    if narg=1 then
        pols:=arg[1];
    fi;

    if narg=2 then
      pols:=arg[1];
      val:=arg[2];
      if not(IsInt(val)) and not(val="basis") then
        Error("The second argument must be an integer or the string 'basis'");
      fi;
    fi;

    if not(IsHomogeneousList(pols)) then
        Error("The argument must be a list of polynomials.");
    fi;

    if not(ForAll(pols, IsUnivariatePolynomial)) then
        Error("The argument must be a list of polynomials.");
    fi;
    if Length(Set(pols, IndeterminateOfLaurentPolynomial))<>1 then
        Error("The arguments must be polynomials in the same variable; constants not allowed nor the empty list.");
    fi;

    var:=IndeterminateNumberOfLaurentPolynomial(pols[1]);

    F:=ShallowCopy(pols);
    Sort(F,function(a,b) return degree(a)< degree(b); end);
    F:=List(F,tomonicglobal);
    G:=List(F,degree);
    n:=0;

    while true do
        T:=kernel(F);
        T:=Filtered(T, x->not(IsZero(x)));
        Info(InfoNumSgps,2,"The kernel evaluated in the polynomials is ",T);
        T:=Set(T,subduction);
        T:=Filtered(T, x->not(IsZero(x)));
        Info(InfoNumSgps,2,"After subduction: ",T);
        if Gcd(G) = 1 then
            s:=NumericalSemigroup(G);
            c:=ConductorOfNumericalSemigroup(s);
            T:=Filtered(T, t->degree(t)<c);
        fi;

        if T=[] or F=Union(F,T) then
            d:=Gcd(G);
            if d=1 then
              s:=NumericalSemigroup(G);
              if narg=1 then
              return s;
              fi;
              msg:=MinimalGeneratingSystem(s);
              F:=Filtered(F,f->degree(f) in msg);
              if val="basis" then
                return List(F,reduce);
              fi;

              if IsInt(val) then
                Info(InfoNumSgps,2,"The generators of the algebra are ",F);
                facts:=FactorizationsIntegerWRTList(val,List(F,degree));
                if facts=[] then
                  return fail;
                fi;
                return reduce(Product(List([1..Length(facts[1])],i->F[i]^facts[1][i])));
              fi;
            fi;
            Info(InfoNumSgps,2,"The monoid is not a numerical semigroup and it is generated by ",
                 G);
            #d*MinimalGeneratingSystem(NumericalSemigroup(G/d)));
            return fail;
        fi;
        Info(InfoNumSgps,2,"Adding ",T," to my list of polynomials");
        F:=Union(F,T);
        newG:=Set(T,degree);
        G:=Union(G,newG);
        if narg=2 and val in G then
            return First(F,f->degree(f)=val);
        fi;

        Info(InfoNumSgps,2,"The set of possible values uptates to ",G);
        n:=n+1;
        d:=Gcd(G);
        s:=NumericalSemigroup(G/d);
        Info(InfoNumSgps,2,"Small elements ",d*SmallElements(s));
    od;
    return fail;
end);


##################################################################
##
#F GeneratorsModule_Global(A,M)
##
## A and M are lists of polynomials in the same variable
## Computes a basis of the ideal MK[A], that is, a set F such that
## deg(F) generates the ideal deg(MK[A]) of deg(K[A]), where deg
## stands for degree
##################################################################
InstallGlobalFunction(GeneratorsModule_Global, function(Al,M)

local S, gens, gM, a, b, da, db, i, j, rs, rd, rel, fcta, fctb, C, pair, reduction, n, reduce,  A, R, t;

R:=function(a,b,s)
 local i, mg;
 i:=IntersectionIdealsOfNumericalSemigroup(a+s,b+s);
 mg:=MinimalGenerators(i);
 return List(mg, m->[m-a,m-b]);
end;

# improve to reducing all terms, not only the leading term
reduce:=function(A,M,f)
 local gens,geni,cand,d, fact, c, r, s,a, ds, cs, csa;
 gens:=List(A, DegreeOfLaurentPolynomial);
 s:=NumericalSemigroup(gens);
 geni:=List(M,DegreeOfLaurentPolynomial);
 if IsZero(f) then
  return f;
 fi;
 r:=f;
 cs:=CoefficientsOfUnivariatePolynomial(r);
 ds:=Filtered([1..Length(cs)],i->not(IsZero(cs[i])))-1;
 c:=First([1..Length(geni)], i->ForAny(ds, d->d-geni[i] in s));
 if c<>fail then
  d:=First(ds,x->x-geni[c] in s);
 fi;
 while c<>fail do
  fact:=FactorizationsIntegerWRTList(d-geni[c],gens);
  a:=M[c]*Product(List([1..Length(gens)],i->A[i]^fact[1][i]));
  csa:=CoefficientsOfUnivariatePolynomial(a);
  r:=csa[Length(csa)]*r-cs[d+1]*a;#r-cs[d+1]*a/csa[Length(csa)];
  #Info(InfoNumSgps,2,"New reduction ",r," degree ",d," coeff ",cs[d+1]);
  if IsZero(r) then
   return r;
  fi;
  cs:=CoefficientsOfUnivariatePolynomial(r);
  ds:=Filtered([1..Length(cs)],i->not(IsZero(cs[i])))-1;
  c:=First([1..Length(geni)], i->ForAny(ds, d->d-geni[i] in s));
  if c<>fail then
   d:=First(ds,x->x-geni[c] in s);
  fi;
 od;

 return r/cs[Length(cs)];
end;

if not(IsHomogeneousList(Al)) then
  Error("The first argument must be a list of polynomials.");
fi;

if not(IsHomogeneousList(M)) then
  Error("The second argument must be a list of polynomials.");
fi;

if not(ForAll(Union(Al,M), IsUnivariatePolynomial)) then
  Error("The arguments must be lists of polynomials.");
fi;
if Length(Set(Union(Al,M), IndeterminateOfLaurentPolynomial))<>1 then
  Error("The arguments must be lists of polynomials in the same variable; constants not allowed nor the empty list.");
fi;

t:=IndeterminateNumberOfLaurentPolynomial(Al[1]);


A:=SemigroupOfValuesOfCurve_Global(Al,"basis");#List(A, DegreeOfLaurentPolynomial);
 gens:=List(A, DegreeOfLaurentPolynomial);
 S:=NumericalSemigroup(gens);
 n:=Length(A);

 gM:=ShallowCopy(M);
 C:=[];
 for i in [1..Length(gM)] do
  for j in [i+1..Length(gM)] do
   Add(C,[gM[i],gM[j]]);
  od;
 od;
 while C<>[] do
  pair:=Remove(C,1);
  a:=pair[1];
  b:=pair[2];
  da:=DegreeOfLaurentPolynomial(a);
  db:=DegreeOfLaurentPolynomial(b);
  rs:=R(da,db,S);
  reduction:=true;
  for rel in rs do
   fcta:=FactorizationsIntegerWRTList(rel[1],gens)[1];
   fctb:=FactorizationsIntegerWRTList(rel[2],gens)[1];
   #rd:=reduce(A,gM,a*Product(List(fcta, e->t^e))-b*Product(List(fctb, e->t^e)));
   rd:=reduce(A,gM,a*Product(List([1..n], i->A[i]^fcta[i]))-b*Product(List([1..n], i->A[i]^fctb[i])));
   if not(IsZero(rd)) then
     Info(InfoNumSgps,2,"new generator ",rd," of degreee ",DegreeIndeterminate(rd,t));
     C:=Union(C,List(gM, x->[x,rd]));
     Add(gM,rd);
     reduction:=false;
   fi;
  od;
  while not reduction do
   #Info(InfoNumSgps,2,"Reducing...");
   reduction:=true;
   a:=First(gM, x->x<>reduce(A,Difference(gM,[x]),x));
   if a<>fail then
    rd:=reduce(A,Difference(gM,[a]),a);
    if IsZero(rd) then
     gM:=Difference(gM,[a]);
     Info(InfoNumSgps,2,"Removing redundant generator: ",a);
    else
     gM:=Union(Difference(gM,[a]),[rd]);
     Info(InfoNumSgps,2,"Replacing ",a," by ",rd);
    fi;
    reduction:=false;
   fi;
  od;
 od;
 Info(InfoNumSgps,2,"Reducing...");
 reduction:=false;
 while not reduction do
  reduction:=true;
  a:=First(gM, x->x<>reduce(A,Difference(gM,[x]),x));
  if a<>fail then
   rd:=reduce(A,Difference(gM,[a]),a);
   if IsZero(rd) then
    gM:=Difference(gM,[a]);
    Info(InfoNumSgps,2,"Removing redundant:",a);
   else
    gM:=Union(Difference(gM,[a]),[rd]);
    Info(InfoNumSgps,2,"Replacing ",a," by ",rd);
   fi;
   reduction:=false;
  fi;
 od;
 return gM;
end);

##################################################################
##
#F GeneratorsKahlerDifferentials(A)
##
## A synonym for GeneratorsModule_Global(A,M), with M the set of
## derivatives of the elements in A
##################################################################
InstallGlobalFunction(GeneratorsKahlerDifferentials, function(A)
 local M, t;

 if not(IsHomogeneousList(A)) then
   Error("The argument must be a list of polynomials.");
 fi;


 if not(ForAll(A, IsUnivariatePolynomial)) then
   Error("The argument must be list of polynomials.");
 fi;
 if Length(Set(A, IndeterminateOfLaurentPolynomial))<>1 then
   Error("The argument must be a list of polynomials in the same variable; constants not allowed nor the empty list.");
 fi;

 t:=IndeterminateNumberOfLaurentPolynomial(A[1]);


 M:=List(A,p->Derivative(p,t));
 return GeneratorsModule_Global(A,M);
end);


##################################################################
##
#O CyclotomicExponentSequence(s,k)
##
## s is a numerical semigroup and k a positive integer, the 
## output is the list of the first k elements of the cyclotomic
## exponent sequence of s (see [C-GS-M]).
## The sequence will be truncated if the semigroup is cyclotomic
## and k is bigger than the last nonzero element in its sequence.
##################################################################
InstallMethod(CyclotomicExponentSequence,[IsNumericalSemigroup, IsPosInt],

function(s,k)
    local invs, i, sec, e, n, left, right,p, x;
  
  x:=Indeterminate(Rationals,"x");
  p:=NumericalSemigroupPolynomial(s,x);
    sec :=[];
  left:=1;
  right:=p;
    for i in [1..k] do
        invs:=p mod x^(i+2);
        for n in [1..i-1] do
            invs:=(invs*PowerMod((1-x^n),sec[n],x^(i+2))) mod x^(i+2);
        od;
        e:=CoefficientsOfUnivariatePolynomial(invs+x^(i+2))[i+1];
    if e>0 then 
     right:=right*(1-x^i)^e;
    else
     left:=left*(1-x^i)^-e;
    fi;
        sec[i]:=e;    

        if left = right then
            return -sec;
        fi; 
    od;  
    return -sec;
end

);

##################################################################
##
#O WittCoefficients(p,k)
##
## p is a univariate polynomial with integer coefficientas and 
## p(1)=1. Then p(x)=\prod_{n\ge 0}(1-x^n)^{e_n}.
## output is the list [e_1,..,e_k], and it is computed bu using 
## [C-GS-HP-M]
##################################################################
InstallMethod(WittCoefficients,[IsUnivariatePolynomial, IsPosInt],
function(p,k)
    local e, s, divisors, j, a;

    a:=CoefficientsOfUnivariatePolynomial(p);
    if a[1]<> 1 then
        Error("The value of the first argument in 1 must be 1");
    fi;
    
    if not(IsSubset(Integers,a)) then
        Error("The firs argument must be a polynomial with integer coefficients");
    fi;

    a:=Concatenation(a{[2..Length(a)]},List([Length(a)-1..k],_->0));
    s:=[-a[1]];
    for j in [2..k] do
        s[j]:=-Reversed(a{[1..j-1]})*s{[1..j-1]}-j*a[j];
    od;

    e:=[];
    for j in [1..k] do
        divisors:=DivisorsInt(j);
        e[j]:=1/j*s{divisors}*List(divisors, i->MoebiusMu(j/i));
    od;

    return e;
end);

##################################################################
##
#F LegendrianGenericNumericalSemigroup(n,m)
## n and m are coprime integers with m>=2n+1. The output is the 
## semigroup of a generic element in the class of irreducible 
## Legendrian singularities with equisingularity equial to the 
## topological type of y^n=x^m. 
################################################################
InstallGlobalFunction(LegendrianGenericNumericalSemigroup,
function(n,m)
    local gamma, i, ni, wi, c, s, li, smg;

    if not(IsPosInt(n) and IsPosInt(m) and Gcd(n,m)=1 and m>2*n) then
        Error("The arguments are two positive coprime integers such that the second is larger than twice the first");
    fi;

    s:=NumericalSemigroup(n,m-n);
    c:=Conductor(s);
    gamma:=MultipleOfNumericalSemigroup(NumericalSemigroup(1),n,c);
    i:=0;
    while(i<>m-n) do
        i:=Maximum(Difference(s,gamma));
        smg:=SmallElements(gamma);
        li:=Difference([i..Conductor(gamma)], smg);
        ni:=Minimum(NrRestrictedPartitions(i,[n,m,m-n]),Length(li));
        wi:=li[ni];
        gamma:=NumericalSemigroupBySmallElements(Union(smg,[i..wi]));
    od;

    return gamma;
end);

[ Dauer der Verarbeitung: 0.44 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


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