Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/numericalsgps/gap/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 30.7.2024 mit Größe 27 kB image not shown  

Quelle  arf-med.gi   Sprache: unbekannt

 
#############################################################################
##
#W  arf-med.gi              Manuel Delgado <mdelgado@fc.up.pt>
#W                          Pedro A. Garcia-Sanchez <pedro@ugr.es>
#W                          Jose Morais <josejoao@fc.up.pt>
##
##
#Y  Copyright 2005 by Manuel Delgado,
#Y  Pedro Garcia-Sanchez and Jose Joao Morais
#Y  We adopt the copyright regulations of GAP as detailed in the
#Y  copyright notice in the GAP manual.
##
#############################################################################



#####################################################################
##                        ARF
## See [RGGB04]
#####################################################################
##
#F ArfNumericalSemigroupClosure(arg)
##
## The argument may be a numerical semigroup or a list of relatively prime
## positive integers
## The output is the Arf-closure of arg (the smallest Arf-semigroup
## containing arg)
##
#####################################################################
InstallGlobalFunction(ArfNumericalSemigroupClosure, function(arg)
    local   set,  min,  A,  i,  MIN,  small, ac;

    if Length(arg) = 1 and IsNumericalSemigroup(arg[1]) then
        if HasMinimalGeneratingSystemOfNumericalSemigroup(arg[1]) then
            set := MinimalGeneratingSystemOfNumericalSemigroup(arg[1]);
        else
            set := GeneratorsOfNumericalSemigroup(arg[1]);
        fi;
    elif Length(arg) = 1 then
        if  Gcd(arg[1]) <> 1 then
            Error("The greatest common divisor is not 1");
        fi;
        set := arg[1];
    else
        if  Gcd(arg) <> 1 then
            Error("The greatest common divisor is not 1");
        fi;
        set := arg;
    fi;
    set := Set(set);
    min := Minimum(set);
    if min <= 0 then
        Error("The elements of the list must be positive integers");
    fi;

    A := [set];
    i := 1;
    while true do
        if (1 in A[i]) then
            MIN := List(A, x -> Minimum(x));
            small := List([0..Length(MIN)], i -> Sum(MIN{[1..i]}));
            ac:=NumericalSemigroupBySmallElements(small);
            Setter(IsArfNumericalSemigroup)(ac,true);
            return ac;
        fi;

        A[i+1] := Union([min],Difference(Set(A[i], x -> x-min),[0]));
        i := i+1;
        min := Minimum(A[i]);
    od;
end);

InstallMethod(ArfClosure,
"Computes the Arf closure of a numerical semigroup",
[IsNumericalSemigroup],
  ArfNumericalSemigroupClosure
);

#####################################################################
##
#P IsArfNumericalSemigroup(s)
##
## The argument s is a numerical semigroup
## returns true if s is an Arf-semigroup and false otherwise
##
#####################################################################
InstallMethod(IsArfNumericalSemigroup,
        "Tests if a Numerical Semigroup is an Arf-semigroup",
        [IsNumericalSemigroup],
        function(s)
    return (s = ArfNumericalSemigroupClosure(s));
end);

InstallTrueMethod(IsMEDNumericalSemigroup,IsArfNumericalSemigroup);
InstallTrueMethod(IsAcuteNumericalSemigroup,IsArfNumericalSemigroup);

#####################################################################
##
#A MinimalArfGeneratingSystemOfArfNumericalSemigroup(s)
##
## The argument s is an Arf numerical semigroup
## returns the minimal Arf-generating system of s.
## Implemented with G. Zito
#############################################################################
InstallMethod(MinimalArfGeneratingSystemOfArfNumericalSemigroup,
  "Returns the minimal Arf-generating system of an Arf-semigroup",
  [IsNumericalSemigroup],
  function(s)
    local char,  ms,i,j,  m, r, b;


    if not(IsArfNumericalSemigroup(s)) then
      Error("The argument must be an Arf numerical semigroup");
    fi;

    ms:=Concatenation(MultiplicitySequenceOfNumericalSemigroup(s),[1]);
    r:=List(ms,_->0);
    for i in [1..Length(ms)] do
      b:=First([i+1..Length(ms)], j->ms[i]=Sum(ms{[i+1..j]}));
      if b=fail then
        b:=Length(ms);
      fi;
      for j in [i+1..b] do
        r[j]:=r[j]+1;
      od;
    od;
    i:=Filtered([1..Length(ms)-1], j->r[j]<r[j+1]);
    return List(i, j->Sum(ms{[1..j]}));

end);

#####################################################################
##
#F ArfNumericalSemigroupsWithFrobeniusNumber(f)
##
## The argument f is an integer
## Returns the set of Arf numerical semigroups with Frobenius number f
## as explained in the preprint
##    Rosales et al., Arf numerical semigroups with given genus and Frobenius number
## This version is due to Giuseppe Zito
#############################################################################
InstallGlobalFunction(ArfNumericalSemigroupsWithFrobeniusNumber, function(f)
  local n, T, Cond, i,j,k, inarf, filt, al, s;

  # tests whether x is in the Arf semigroup with multiplicity
  # sequence j
  inarf:=function(x,j)
      local l;
      if x>Sum(j) then
        return true;
      fi;
      if x=0 then
        return true;
      fi;
      if x<j[1] then
        return false;
      fi;
      l:=List([1..Length(j)], i-> Sum(j{[1..i]}));
      return x in l;
  end;

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

  n:=f+1;
  if (n<0) or (n=1) then
    return [];
  fi;

  if n=0 then
    s:=NumericalSemigroup(1);
    Setter(IsArfNumericalSemigroup)(s,true);
    return [s];
  fi;

  Cond:=List([[n]]);
  T:=[];
  for i in [2..n-2] do
    T[i]:=[[i]];
  od;

  for i in [2..n-2] do
    for j in T[i] do
      if inarf(n-i,j) then
          Add(Cond, Concatenation([n-i],j));
      fi;
      filt:= Filtered([j[1]..Int((n-i)/2)], x->inarf(x,j));
      for k in filt do
        Add(T[i+k],Concatenation([k],j));
      od;
    od;

  od;
  al := List(Cond, j-> NumericalSemigroupBySmallElementsNC(Concatenation([0],List([1..Length(j)], i-> Sum(j{[1..i]})))));
  for s in al do
    Setter(IsArfNumericalSemigroup)(s,true);
  od;
  return al;
end);

#####################################################################
##
#F ArfNumericalSemigroupsWithGenus(g)
##
## Returns the set of Arf numerical semigroups with genus g,
## This version is due to Giuseppe Zito
#############################################################################
InstallGlobalFunction(ArfNumericalSemigroupsWithGenus, function(g)
  local n, T, Gen, i,j,k, inarf, filt, al, s;

  # tests whether x is in the Arf semigroup with multiplicity
  # sequence j
  inarf:=function(x,j)
      local l;
      if x>Sum(j) then
        return true;
      fi;
      if x=0 then
        return true;
      fi;
      if x<j[1] then
        return false;
      fi;

      l:=List([1..Length(j)], i-> Sum(j{[1..i]}));
      return x in l;
  end;

  n:=g;

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

  if (g<0) then
    return [];
  fi;

  if n=0 then
    s:=NumericalSemigroup(1);
    Setter(IsArfNumericalSemigroup)(s,true);
    return [s];
  fi;

  Gen:=List([[n+1]]);
  T:=[];
  for i in [1..n-1] do
    T[i]:=[[i+1]];
  od;

  for i in [1..n-1] do
    for j in T[i] do
      if inarf(n-i+1,j) then
          Add(Gen, Concatenation([n-i+1],j));
      fi;
      filt:= Filtered([j[1]..Int((n-i+2)/2)], x->inarf(x,j));
      for k in filt do
        Add(T[i+k-1],Concatenation([k],j));
      od;
    od;

  od;
  al := List(Gen, j-> NumericalSemigroupBySmallElementsNC(Concatenation([0],List([1..Length(j)], i-> Sum(j{[1..i]})))));
  for s in al do
    Setter(IsArfNumericalSemigroup)(s,true);
  od;
  return al;
end);

#####################################################################
##
#F ArfNumericalSemigroupsWithGenusUpTo(g)
##
## Returns the set of Arf numerical semigroups with genus less than
## or equal to g, as explained in
## -Rosales et al., Arf numerical semigroups with given genus and
##  Frobenius number
## New version by Giuseppe Zito (U Catania)
#############################################################################
InstallGlobalFunction(ArfNumericalSemigroupsWithGenusUpTo,function(g)
  local n, T, i,j,k, inarf, filt, al, s;

  # tests whether x is in the Arf semigroup with multiplicity
  # sequence j
  inarf:=function(x,j)
      local l;
      if x>Sum(j) then
        return true;
      fi;
      if x=0 then
        return true;
      fi;
      if x<j[1] then
        return false;
      fi;

      l:=List([1..Length(j)], i-> Sum(j{[1..i]}));
      return x in l;
  end;

  n:=g;

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

  if (g<0) then
    return [];
  fi;

  if n=0 then
    s:=NumericalSemigroup(1);
    Setter(IsArfNumericalSemigroup)(s,true);
    return [s];
  fi;

  T:=[];
  for i in [1..n] do
    T[i]:=[[i+1]];
  od;
  T[n+1]:=[[1]];

  for i in [1..n-1] do
    for j in T[i] do
      filt:= Filtered([j[1]..n-i+1], x->inarf(x,j));
      for k in filt do
        Add(T[i+k-1],Concatenation([k],j));
      od;
    od;

  od;
  al :=List(Union(T),j-> NumericalSemigroupBySmallElementsNC(Concatenation([0],List([1..Length(j)], i-> Sum(j{[1..i]})))));
  for s in al do
    Setter(IsArfNumericalSemigroup)(s,true);
  od;

  return al;
end);


#####################################################################
##
#F ArfNumericalSemigroupsWithFrobeniusNumberUpTo(f)
##
## Returns the set of Arf numerical semigroups with Frobenius number
## less than or equal to f, as explained in
##    Rosales et al., Arf numerical semigroups with given genus and Frobenius number
## New version by Giuseppe Zito (U Catania)
#############################################################################
InstallGlobalFunction(ArfNumericalSemigroupsWithFrobeniusNumberUpTo,function(f)
  local n, T, i,j,k, inarf, filt, al, s;


  # tests whether x is in the Arf semigroup with multiplicity
  # sequence j
  inarf:=function(x,j)
      local l;
      if x>Sum(j) then
        return true;
      fi;
      if x=0 then
        return true;
      fi;
      if x<j[1] then
        return false;
      fi;
      l:=List([1..Length(j)], i-> Sum(j{[1..i]}));
      return x in l;
  end;

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

  n:=f+1;
  if (n<0) or (n=1) then
    return [];
  fi;

  if n=0 then
    s:=NumericalSemigroup(1);
    Setter(IsArfNumericalSemigroup)(s,true);
    return [s];
  fi;

  T:=[];
  for i in [1..n] do
    T[i]:=[[i]];
  od;

  for i in [2..n-2] do
    for j in T[i] do
      filt:= Filtered([j[1]..n-i], x->inarf(x,j));
      for k in filt do
        Add(T[i+k],Concatenation([k],j));
      od;
    od;

  od;
  al:=List(Union(T),j-> NumericalSemigroupBySmallElementsNC(Concatenation([0],List([1..Length(j)], i-> Sum(j{[1..i]})))));
  for s in al do
    Setter(IsArfNumericalSemigroup)(s,true);
  od;
  return al;
end);

#####################################################################
##
#F ArfNumericalSemigroupsWithGenusAndFrobeniusNumber(g,f)
##
## Returns the set of Arf numerical semigroups with genus g and
## Frobenius number f, as explained in
##    Rosales et al., Arf numerical semigroups with given genus and Frobenius number
#############################################################################
InstallGlobalFunction(ArfNumericalSemigroupsWithGenusAndFrobeniusNumber,function(g,f)
 local par2sem, testArfSeq, arfsequences, n, al, s;

 #transforms a partition list of an element to the set of sums
 # which will correspond with the set of small elements of the semigroup
 par2sem:=function(l)
            local rl, n,sm, i;

            n:=Length(l);
            rl:=Reversed(l);
            sm:=[0];
            for i in [1..n] do;
                Add(sm,Sum(rl{[1..i]}));
            od;

            return sm;

 end;

 # computes all Arf sequences with sumset equal f+1
 arfsequences:=function(n)
            local l, k, lk, lkm1,bound,cand,s;

            l:=[List([2..Int(f+1)], x-> [x])];
            for k in [2..n] do
                lk:=[];
                lkm1:=l[Length(l)];
                for s in lkm1 do
                    bound:=Int((f+1-Sum(s))/(n-(k-1)));
                    cand:=Intersection(Union(Difference(par2sem(s),[0]), [Sum(s)..bound]),[s[Length(s)]..bound]);
                    lk:=Concatenation(lk,List(cand,x->Concatenation(s,[x])));
                od;

                if lk<>[] then
                    l:=Concatenation(l,[lk]);
                fi;
            od;
            l:=Filtered(l[n], x->Sum(x)=f+1);

            return l;
 end;

 if not(IsInt(g)) or not(IsInt(f)) then
  Error("The arguments must be an integers");
 fi;

 if g<0 then
  return [];
 fi;

 if g=0 and f=-1 then
    s:=NumericalSemigroup(1);
    Setter(IsArfNumericalSemigroup)(s,true);
    return [s];
 fi;

 if not(g<=f and f<=2*g-1) then
  return [];
 fi;

 n:=f+1-g;

 al:=List(List(arfsequences(n), par2sem),NumericalSemigroupBySmallElementsNC);
  for s in al do
    Setter(IsArfNumericalSemigroup)(s,true);
  od;
  return al;

end);


#####################################################################
##
## ArfSpecialGaps(s)
##
## returns the set of gaps g of s such that s cup {g} is again Arf
##
#####################################################################
InstallMethod(ArfSpecialGaps,
  "Returns Arf special gaps",
  [IsNumericalSemigroup],
function(s)
    local ag, sg, g, se, rse, e1, e2;

    if not(IsArf(s)) then
        Error("The argument must be an Arf numerical semigroup");
    fi;

    ag:=[];

    sg:=SpecialGaps(s);
    se:=SmallElements(s);
    rse:=Reversed(se);
    for g in sg do
        e1:=First(rse, e->g-e>0);
        e2:=First(se, e->g-e<0);
        if (2*g-e1 in s) and (2*e2-g in s) then
            Add(ag,g);
        fi;
    od;    
    return ag;
end);

#####################################################################
##
## ArfOverSemigroups(s)
##
## returns the set of Arf oversemigroups of s
##
#####################################################################
InstallMethod(ArfOverSemigroups,
  "Returns the set of Arf oversemigroups of the given numerical semigroup",
  [IsNumericalSemigroup],
  function(s)
    local   t,  sg,  A,  O, g, a;

    if(not(IsArf(s))) then
        Error("The argument must be an Arf numerical semigroup");
    fi;

    if(s=NumericalSemigroup(1)) then
        return [s];
    fi;

    t:=s;
    sg:=ArfSpecialGaps(t); #which must be different from [-1]
    A:=[NumericalSemigroup(1),t];
    O:=[];
    for g in sg do #List(sg,g->AddSpecialGapOfNumericalSemigroup(g,t));
        a:=AddSpecialGapOfNumericalSemigroup(g,t);
        Setter(IsArf)(a,true);
        AddSet(O,a);
    od;
    
    while(not(O=[])) do
        t:=O[1];
        O:=O{[2..Length(O)]};
        if(not(t in A)) then
            A:=Union(A,[t]);
            sg:=ArfSpecialGaps(t);
            for g in sg do #O:=Union(O,List(sg,g->AddSpecialGapOfNumericalSemigroup(g,t)));
                a:=AddSpecialGapOfNumericalSemigroup(g,t);
                Setter(IsArf)(a,true);
                AddSet(O,a);
            od;
        fi;
    od;
    return A;
end);

#####################################################################
##
## IsArfIrreducible(s)
##
## detects it s can be written as the intersection of two or more 
## Arf semigroups containing it
##
#####################################################################
InstallMethod(IsArfIrreducible,
  "Tests wether the semigroup is Arf irreducible",
  [IsNumericalSemigroup],
  function(s)
     if not(IsArf(s)) then
        Error("The argument must be an Arf numerical semigroup");
    fi;
    return Length(ArfSpecialGaps(s))<=1;
end);

InstallTrueMethod(IsArfIrreducible, IsArf and IsArfIrreducible);

#####################################################################
##
## DecomposeIntoArfIrreducibles(s)
##
## retuns a set of Arf irreducible numerical semigroups whose
## intersection is s; this representation is minimal in the sense
## that no semigroup can be removed
##
#####################################################################
InstallMethod(DecomposeIntoArfIrreducibles,
  "retuns the Arf irreducible numerical semigroups whose intersection is the arguement",
  [IsNumericalSemigroup],
  function(s)

    local   sg,  caux,  I,  C,  B,  pair,  i,  I2,  j,  l, dec, si;

    #sg contains the special gaps of s
    #B auxiliar ser used to construct C and I
    #I will include Arf irreducibles containing s
    #C non irreducibles
    #caux(t) is to compute those elements in gs that are not in t
    #II auxiliar set of Arf irreducibles

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

    if(not(IsArf(s))) then
        Error("The argument must be an Arf numerical semigroup.\n");
    fi;


    if(s=NumericalSemigroup(1)) then
        Setter(IsIrreducibleNumericalSemigroup)(s,true);
        return [s];
    fi;

    sg:=ArfSpecialGaps(s);
    if (Length(sg)=1) then
        #Setter(IsIrreducibleNumericalSemigroup)(s,true);
        return [s];
    fi;

    caux:=function(t)
        return Filtered(sg,g->not(BelongsToNumericalSemigroup(g,t)));
    end;

    I:=[];
    C:=[s];
    B:=[];
    while(not(C=[])) do
        B:=Union(List(C,sp->List(ArfSpecialGaps(sp),g->AddSpecialGapOfNumericalSemigroup(g,sp))));
        B:=Filtered(B,b->not(caux(b)=[]));
        B:=Filtered(B,b->Filtered(I,i->IsSubsemigroupOfNumericalSemigroup(i,b))=[]);
        C:=Filtered(B,b->not(Length(ArfSpecialGaps(b))=1));
        I:=Union(I,Difference(B,C));
    od;
    I:=List(I,i->[i,caux(i)]);
    while(true) do
        pair := fail;
        for i in I do
            I2 := [];
            for j in I do
                if not j = i then
                    Add(I2, j);
                fi;
            od;

            l := [];
            for j in I2 do
                Add(l, j[2]);
            od;
            if Union(l) = sg then
                pair := i;
                break;
            fi;
        od;

        if(pair=fail) then
            dec:=List(I, x -> x[1]);
            for si in dec do
               Setter(IsArfIrreducible)(si,true);
            od;
            return dec;
        fi;

        I2 := [];
        for j in I do
            if not j = pair then
                Add(I2, j);
            fi;
        od;

        I := I2;
        Unbind(I2);
    od;
    dec:=List(I, x -> x[1]);
    for si in dec do
      Setter(IsArfIrreducible)(si,true);
    od;
    return dec;

end);

#####################################################################
##                        MED
## See [RGGB03]
#####################################################################
##
#A IsMEDNumericalSemigroup(s)
##
## The argument s is a numerical semigroup
## returns true if s is a MED-semigroup and false otherwise
##
#####################################################################
InstallMethod(IsMEDNumericalSemigroup,
        "Tests if a numerical semigroup is a MED-semigroup",
        [IsNumericalSemigroup],
        function(s)
    local e, m;
    m := MultiplicityOfNumericalSemigroup(s);
    e := Length(MinimalGeneratingSystemOfNumericalSemigroup(s));
    return e = m;
end);


#####################################################################
##
#F MEDNumericalSemigroupClosure(arg)
##
## The argument may be a numerical semigroup or a list of relatively prime
## positive integers
## The output is the MED-closure of arg (the smallest MED-semigroup
## containing arg)
##
#####################################################################
InstallGlobalFunction(MEDNumericalSemigroupClosure, function(arg)
    local   set,  min,  A,  small, s;

    if Length(arg) = 1 and IsNumericalSemigroup(arg[1]) then
        if HasMinimalGeneratingSystemOfNumericalSemigroup(arg[1]) then
            set := MinimalGeneratingSystemOfNumericalSemigroup(arg[1]);
        else
            set := GeneratorsOfNumericalSemigroup(arg[1]);
        fi;
    elif Length(arg) = 1 then
        if  Gcd(arg[1]) <> 1 then
            Error("The greatest common divisor is not 1");
        fi;
        set := arg[1];
    else
        if  Gcd(arg) <> 1 then
            Error("The greatest common divisor is not 1");
        fi;
        set := arg;
    fi;
    set := Set(set);
    min := Minimum(set);
    if min <= 0 then
        Error("The elements of the list must be positive integers");
    fi;

    A := set - min;
    A[1] := min;
    small := Union([0], min +
                   SmallElementsOfNumericalSemigroup(NumericalSemigroup(A)));
    s:= NumericalSemigroupBySmallElements(small);
    Setter(IsMEDNumericalSemigroup)(s,true);
    return s;
end);

InstallMethod(MEDClosure,
"Computes the MED closure of a numerical semigroup",
[IsNumericalSemigroup],
  MEDNumericalSemigroupClosure
);

#####################################################################
##
#A MinimalMEDGeneratingSystemOfMEDNumericalSemigroup(s)
##
## The argument s is a MED numerical semigroup
## returns the minimal MED-generating system of s.
##
#############################################################################
InstallMethod(MinimalMEDGeneratingSystemOfMEDNumericalSemigroup,
        "Returns the minimal MED-generating system of a MED numerical semigroup",
        [IsNumericalSemigroup],
        function(s)
    local   gen,  len,  ngen;

    if not IsMEDNumericalSemigroup(s) then
        Error("s must be a MED numerical semigroup");
    fi;
    gen := MinimalGeneratingSystemOfNumericalSemigroup(s);

    len := Length(gen);
    if len = 2 then
        return gen;
    fi;

    while len >= 2 do
        ngen  := Difference(gen, [gen[len]]);
        if Gcd(ngen) = 1 and s = MEDNumericalSemigroupClosure(ngen) then
            gen := ngen;
            len := len - 1;
        else
            len := len -1;
        fi;
    od;
    return gen;
end);

#####################################################################
##                        Saturated
## See [book]
#####################################################################
##
#F SaturatedfNumericalSemigroupClosure(arg)
##
## The argument may be a numerical semigroup or a list of relatively prime
## positive integers
## The output is the saturated-closure of arg (the smallest saturated-semigroup
## containing arg)
##
#####################################################################
InstallGlobalFunction(SaturatedNumericalSemigroupClosure, function(arg)
    local   set,  gen,  min,  ne,  edim,  dis,  small,  i,  kjs, s;

    if Length(arg) = 1 and IsNumericalSemigroup(arg[1]) then
        if HasMinimalGeneratingSystemOfNumericalSemigroup(arg[1]) then
            set := MinimalGeneratingSystemOfNumericalSemigroup(arg[1]);
        else
            set := GeneratorsOfNumericalSemigroup(arg[1]);
        fi;
    elif Length(arg) = 1 then
        if  Gcd(arg[1]) <> 1 then
            Error("The greatest common divisor is not 1");
        fi;
        set := arg[1];
    else
        if  Gcd(arg) <> 1 then
            Error("The greatest common divisor is not 1");
        fi;
        set := arg;
    fi;
    gen := Set(set);
    min := gen[1];
    ne := Maximum(gen);
    if not IsPosInt(min) then
        Error("The elements of the list must be positive integers");
    fi;
    edim := Length(gen); #embedding dimension
    dis := List([1..edim], i -> Gcd(gen{[1..i]}));

    small := Set([0]);
    for i in [1..edim-1] do
        kjs := 0;
        if (dis[i] = 1) then
            return NumericalSemigroupBySmallElements(Union(small,[gen[i]]));
        fi;
        while(gen[i] + kjs*dis[i] < gen[i+1]) do
            AddSet(small,gen[i]+kjs*dis[i]);
            kjs := kjs+1;
        od;
    od;
    s:=NumericalSemigroupBySmallElements(Union(small,[ne]));
    Setter(IsSaturatedNumericalSemigroup)(s,true);
    return s;
end);

InstallMethod(SaturatedClosure,
"Computes the Saturated closure of a numerical semigroup",
[IsNumericalSemigroup],
  SaturatedNumericalSemigroupClosure
);


#####################################################################
##
#P IsSaturatedNumericalSemigroup(s)
##
## The argument s is a numerical semigroup
## returns true if s is a saturated-semigroup and false otherwise
##
#####################################################################
InstallMethod(IsSaturated,
        "Tests if a Numerical Semigroup is a saturated semigroup",
        [IsNumericalSemigroup],
        function(s)
    return (s = SaturatedNumericalSemigroupClosure(s));
end);

# InstallMethod(IsSaturated,
#   "Tests if a Numerical Semigroup is a saturated semigroup",
#   [IsNumericalSemigroup],IsSaturatedNumericalSemigroup);
#solution by Sebastian Gutsche to

InstallTrueMethod(IsArfNumericalSemigroup, IsSaturatedNumericalSemigroup);

#####################################################################
##
#F SaturatedNumericalSemigroupsWithFrobeniusNumber(f)
##
## The argument f is an integer
## returns the the set of saturated numerical semigroups with Frobenius number f
## as explained in the preprint
##    Rosales et al., Arf numerical semigroups with given genus and Frobenius number
#############################################################################
InstallGlobalFunction(SaturatedNumericalSemigroupsWithFrobeniusNumber,function(f)
 local alg23, alg24, satpart, listsatseq, L, C, Ll, l, t, satsystem, i, ls, s;

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

 if f=0 or f<-1 then
  return [];
 fi;
 if f=-1 then
    s:=NumericalSemigroup(1);
    Setter(IsSaturatedNumericalSemigroup)(s,true);
    return [s];
 fi;

 #returns the set nonnegative integer of solutions x
 # with l.x=c; l is a (saturated) sequence
 # l[i+1]|l[i], l[i+1]<>l[i], l[Length(l)]=1
 satpart:=function(l,c)
  local sols, len, i, j, sol, next, cand;

  len:=Length(l);
   sol:=[];
  for i in [1..len-1] do Add(sol, 0); od;
  sol[len]:=c;
  sols:=[sol];

  while true do
   j:=First(Reversed([1..len-1]), i-> sol{[i+1..len]}*l{[i+1..len]}>=l[i]);
   if j=fail then
    return sols;
   fi;
   next:=[];
   for i in [1..j-1] do next[i]:=sol[i]; od;
   next[j]:=sol[j]+1;
   for i in [j+1..len-1] do next[i]:=0; od;
   next[len]:=sol{[j+1..len]}*l{[j+1..len]}-l[j];
   sol:=next;#sol:=ShallowCopy(next);
   Add(sols, sol);
  od;

 end;

 #returns saturated semigroups associated to a saturaded sequence
 # with Frobenius number f
 listsatseq:=function(d, f)
  local c, l, ok, sum, len, ones, i;

  l:=[];
  ok:=false;
  sum:=Sum(d);
  len:=Length(d);

  if (f+1>=sum) and (Gcd(f+1,d[len-1])=1) and (((f+1) mod d[len-1])<>1) then
   ok:=true;
   c:=f+1-sum;
  fi;

  if (f+2>=sum) and (((f+2) mod d[len-1])=1) then
   ok:=true;
   c:=f+2-sum;
  fi;

  if not(ok) then
   return [];
  fi;
  ones:=[];
  for i in [1..len] do ones[i]:=1; od;

  l:=satpart(d,c);
  l:=l+ones;
  l:=Filtered(l, t-> ForAll([1..len-1], i-> Gcd(d[i]/d[i+1],t[i+1])=1));
  return l;

 end;

 #implements Algorithm 23
 alg23:=function(f)
  local tot, A, AA, cand, d, x, dd;

  cand:=Filtered([2..f], x-> Gcd(f+1,x)=1 and f mod x<> 0);
  A:=List(cand, x-> [x,1]);
  tot:=A;

  while (A<>[]) do
   AA:=[];
   for d in A do
    for x in [2..Int((f+1-Sum(d))/d[1])] do
     dd:=ShallowCopy(d);
     dd[1]:=x*d[1];
     dd{[2..Length(d)+1]}:=d;
     Add(AA, dd);
    od;
   od;
   A:=AA;
   tot:=Union(tot,A);
  od;

  return tot;

 end;

 #implements Algorithm 24
 alg24:=function(f)
  local tot, A, AA, cand, d, x, dd;

  cand:=Difference(DivisorsInt(f+1),[1]);
  A:=List(cand, x-> [x,1]);
  tot:=A;

  while (A<>[]) do
   AA:=[];
   for d in A do
    for x in [2..Int((f+2-Sum(d))/d[1])] do
     dd:=ShallowCopy(d);
     dd[1]:=x*d[1];
     dd{[2..Length(d)+1]}:=d;
     Add(AA, dd);
    od;
   od;
   A:=AA;
   tot:=Union(tot,A);
  od;

  return tot;

 end;
 #main
 L:=Union(alg23(f),alg24(f));
 C:=[];
 for l in L do
  Ll:=listsatseq(l,f);
  for t in Ll do
   satsystem:=[];
   satsystem[1]:=l[1];
   for i in [2..Length(l)] do
    satsystem[i]:=l{[1..i]}*t{[1..i]};
   od;
   Add(C,satsystem);
  od;
 od;
  ls:=Set(C, SaturatedNumericalSemigroupClosure);
  for s in ls do
    Setter(IsSaturatedNumericalSemigroup)(s,true);
  od;
  return ls;
end);

[ Dauer der Verarbeitung: 0.40 Sekunden  (vorverarbeitet)  ]