#############################################################################
##
#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)
    if not IsNumericalSemigroup(s) then
        Error("The argument must be a numerical semigroup");
    fi;
    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,  inarf,i,j,  m, r, b;

    # 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(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);


#####################################################################
##                        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)
    if not IsNumericalSemigroup(s) then
        Error("The argument must be a numerical semigroup");
    fi;
    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);
