|
#############################################################################
##
#W good-semigroups.gd Manuel Delgado <mdelgado@fc.up.pt>
#W Pedro A. Garcia-Sanchez <pedro@ugr.es>
##
#Y Copyright 2016-- Centro de Matemática da Universidade do Porto, Portugal and IEMath-GR, Universidad de Granada, Spain
#############################################################################
####################################################
##
#F NumericalDuplication(S,E,b)
## returns 2S\cup(2E+b)
####################################################
InstallGlobalFunction(NumericalDuplication, function(S,E,b)
local smallS, doubS, smallE, f, small, mgsE, mgsS;
if not(IsNumericalSemigroup(S)) or not(IsIdealOfNumericalSemigroup(E)) then
Error("The first argument must be a numerical semigroup, and the second an ideal");
fi;
if not(IsInt(b)) then
Error("The third argument must be an integer");
fi;
if not(b mod 2=1) then
Error("The third argument must be an odd integer");
fi;
# if not(b in S) then
# Error("The third argument must belong to the first argument");
# fi;
mgsE:=MinimalGeneratingSystem(E);
# if not(ForAll(mgsE, x -> x in S)) then
# Error("The second argument must be a integral ideal of the first");
# fi;
mgsS:=MinimalGenerators(S);
if not(ForAll(Cartesian(mgsE,mgsE), p->Sum(p)+b in S)) then
Error("The arguments do not define a semigroup (E+E+b is not included in S)");
fi;
return NumericalSemigroup(Union(2*mgsS, 2*mgsE+b));
end);
####################################################
##
#F AsNumericalDublication(T)
## Detects whether a numerical semigroup T can be obtained
## as a numerical duplication (with a proper ideal).
## It returns fail or the list [S,I,b], such that
## T=NumericalDuplication(S,I,b)
####################################################
InstallGlobalFunction(AsNumericalDuplication,
function(T)
local G, Ev, O, j, S, x, Sm, B, b, H1, N, k, I;
if ((Multiplicity(T) mod 2)=0) then
G:=MinimalGenerators(T);
O:=[];
Ev:=[];
for j in [1..Length(G)] do
if ((G[j] mod 2)=1) then
Append(O,[G[j]]);
fi;
if ((G[j] mod 2)=0) then
Append(Ev,[G[j]]);
fi;
od;
if Gcd(Ev/2)=1 then
S:=NumericalSemigroup(Ev/2);
Sm:=SmallElements(S);
B:=[];
x:=Minimum(O)-Multiplicity(T);
for j in [1..Length(Sm)] do
if ((Sm[j] mod 2)=1) and (Sm[j]<=x) then
Append(B,[Sm[j]]);
fi;
od;
for j in [Sm[Length(Sm)]..x] do
if ((j mod 2)=1) then
Append(B,[j]);
fi;
od;
for b in [1..Length(B)] do
if B[b]<=Minimum(O) then
H1:=[];
H1:=(O-B[b])/2;
N:=0;
for k in [1..Length(H1)] do
if (H1[k] in S) then
N:=N+1;
fi;
od;
if (N=Length(H1)) then
I:=H1+S;
return([S,I,B[b]]);
fi;
fi;
od;
fi;
fi;
return(fail);
end);
###################################################
##
#F NumericalSemigroupDuplication(S,E)
## returns S\bowtie E
###################################################
InstallGlobalFunction(NumericalSemigroupDuplication,function(S,E)
local M, mgsE;
if not(IsNumericalSemigroup(S)) or not(IsIdealOfNumericalSemigroup(E)) then
Error("The first argument must be a numerical semigroup, and the second an ideal");
fi;
mgsE:=MinimalGeneratingSystem(E);
if not(ForAll(mgsE, x -> x in S)) then
Error("The second argument must be an integral ideal of the first");
fi;
M:=Objectify(GoodSemigroupsType, rec());
SetNumericalSemigroupGS(M,S);
SetIdealGS(M,E);
SetDefinedByDuplication(M,true);
return M;
end);
###################################################
##
#F AmalgamationOfNumericalSemigroups(S,E,c)
## returns S\bowtie^f E, f multiplication by c
###################################################
InstallGlobalFunction(AmalgamationOfNumericalSemigroups, function(S,E,c)
local M, T, msg;
if not(IsNumericalSemigroup(S)) or not(IsIdealOfNumericalSemigroup(E)) then
Error("The first argument must be a numerical semigroup, and the second an ideal");
fi;
if not(IsPosInt(c)) then
Error("The third argument must be a positive integer");
fi;
T:=AmbientNumericalSemigroupOfIdeal(E);
msg:=MinimalGeneratingSystem(S);
if not(ForAll(msg, x-> c*x in T)) then
Error("Multiplication by the third argument must be a morphism from the first argument to the ambient semigroup of the second");
fi;
M:=Objectify(GoodSemigroupsType, rec());
SetNumericalSemigroupGS(M,S);
SetIdealGS(M,E);
SetMorphismGS(M,c);
SetDefinedByAmalgamation(M,true);
return M;
end);
###################################################
##
#F CartesianProductOfNumericalSemigroups(S1,S2)
## Computes the cartesian product of S1 and S2, which
## is a good semigroup
###################################################
InstallGlobalFunction(CartesianProductOfNumericalSemigroups, function(S1,S2)
local M;
if not(IsNumericalSemigroup(S1)) or not(IsNumericalSemigroup(S2)) then
Error("The arguments must be numerical semigroups");
fi;
M:=Objectify(GoodSemigroupsType, rec());
SetNumericalSemigroupListGS(M,[S1,S2]);
SetDefinedByCartesianProduct(M,true);
return M;
end);
###################################################
##
#F RepresentsSmallElementsOfGoodSemigroup(X)
## detects if X is a good semiring
###################################################
InstallGlobalFunction(RepresentsSmallElementsOfGoodSemigroup, function(X)
local c, inf, conG2, C;
inf:=function(x,y)
return [Minimum(x[1],y[1]), Minimum(x[2],y[2])];
end;
if not(IsRectangularTable(X)) and ForAll(X, x->Length(x)=2) then
Error("The argument must be a list of pairs of positive integers");
fi;
if not(ForAll(X, x->IsInt(x[1]) and IsInt(x[2]) and x[1]>=0 and x[2]>=0)) then
Error("The argument must be a list of pairs of positive integers");
fi;
C:=[0,0];
if not(C in X) then
Info(InfoNumSgps,2,"Zero is not in the set.");
return false;
fi;
C[1]:=Maximum(List(X,x->x[1]));
C[2]:=Maximum(List(X,x->x[2]));
if not(C in X) then
Info(InfoNumSgps,2,"The maximum is not in the set.");
return false;
fi;
c:=Cartesian(X,X);
if ForAny(c, p->not(inf(p[1]+p[2],C) in X)) then
Info(InfoNumSgps,2,"The set is not closed under addition modulo inf the maximum.");
return false;
fi;
if ForAny(c, p->not(inf(p[1], p[2]) in X)) then
Info(InfoNumSgps,2,"The set is not closed under infimums.");
return false;
fi;
conG2:=First(X, x->x[1]<C[1] and ForAny(X,y-> x[1]=y[1] and x[2]<y[2] and not(ForAny(X, z->x[2]=z[2] and z[1]>x[1]))));
if conG2<>fail then
Info(InfoNumSgps,2,"The set is not a good semiring: ",conG2);
return false;
fi;
conG2:=First(X, x->x[2]<C[2] and ForAny(X,y-> x[2]=y[2] and x[1]<y[1] and not(ForAny(X, z->x[1]=z[1] and z[2]>x[2]))));
if conG2<>fail then
Info(InfoNumSgps,2,"The set is not a good semiring: ",conG2);
return false;
fi;
return true;
end);
###################################################
##
#F GoodSemigroup(X,C)
## define the good semigroup from the set of points G
## with conductor C
###################################################
InstallGlobalFunction(GoodSemigroup, function(Gn,C)
local M, p1, p2, c, CC, sm, SemiRing_NS, gen, inf, G;
if not(IsRectangularTable(Gn)) and ForAll(Gn, x->IsList(x) and Length(x)=2) then
Error("The first argument must be a list of pairs of positive integers");
fi;
if not(ForAll(Gn, x->IsInt(x[1]) and IsInt(x[2]) and x[1]>=0 and x[2]>=0)) then
Error("The first argument must be a list of pairs of positive integers");
fi;
if not(IsList(C)) and Length(C)=2 then
Error("The second argument must be a list (pair) of nonnegative integers");
fi;
if not(IsInt(C[1]) and IsInt(C[2]) and C[1]>=0 and C[2]>=0) then
Error("The second argument must be a list (pair) of nonnegative integers");
fi;
inf:=function(u,v)
return [Minimum(u[1],v[1]),Minimum(u[2],v[2])];
end;
###############################################################
##
#F SemiRing_NS(G,C)
## G is a set of points;
## computes the saturation wrt sum (cutted by C) and inf
################################################################
SemiRing_NS:=function(G,C)
local O, OO, new,i,j, o;
O:=G;
# sum saturation
repeat
new:=[];
for i in [1..Length(O)] do
for j in [i.. Length(O)] do
o:=inf(C,O[i]+O[j]);
if not(o in O) then
Add(new, o);
fi;
od;
od;
O:=Union(O,new);
until new=[];
O:=Union(O,[[0,0]]);
#inf saturation
repeat
new:=[];
for i in [1..Length(O)] do
for j in [i.. Length(O)] do
o:=inf(O[i],O[j]);
if not(o in O) then
Add(new, o);
fi;
od;
od;
O:=Union(O,new);
until new=[];
# #good saturation x coordinate
# repeat
# new:=First(O, x->x[1]<C[1] and ForAny(O,y-> x[1]=y[1] and x[2]<y[2] and not(ForAny(O, z->x[2]=z[2] and z[1]>x[1]))));
# if new<>fail then
# Add(O,[C[1],new[2]]);
# fi;
# until new=fail;
# #good saturation y coordinate
# repeat
# new:=First(O, x->x[2]<C[2] and ForAny(O,y-> x[2]=y[2] and x[1]<y[1] and not(ForAny(O, z->x[1]=z[1] and z[2]>x[2]))));
# if new<>fail then
# Add(O,[new[1],C[2]]);
# fi;
# until new=fail;
return O;
end; # of SemiRing_NS
G:=ShallowCopy(Gn);
p1:=List(G,x->x[1]);
p2:=List(G,x->x[2]);
CC:=[Maximum(p1), Maximum(p2)];
if not(C[1]>=CC[1] and C[2]>=CC[2]) then
Info(InfoNumSgps, 2, "The conductor is not larger than the maximum of the given set");
G:=List(G, x->inf(x,C));
fi;
sm:=Union(SemiRing_NS(G,C),[C]);
if not(RepresentsSmallElementsOfGoodSemigroup(sm)) then
Error("The given set does not generate a good semigroup");
fi;
c:=C;
while ((c-[0,1]) in sm) or ((c-[1,0]) in sm) do
if ((c-[0,1]) in sm) and ((c-[1,0]) in sm) then #c-[1,1] also in sm
c:=c-[1,1];
elif c-[0,1] in sm then
c:=c-[0,1];
else
c:=c-[1,0];
fi;
od;
if C<>c then #sm must be redefined, and gens
Info(InfoNumSgps,2,"Conductor redefined");
sm:=Filtered(sm, x->x[1]<=c[1] and x[2]<=c[2]);
gen:=List(G, x->inf(x,c));#x[1]<=c[1] and x[2]<=c[2]);
else
gen:=ShallowCopy(G);
fi;
M:=Objectify(GoodSemigroupsType, rec());
SetGenerators(M,gen);
SetConductor(M,c);
SetSmallElements(M,sm);
return M;
end);
###################################################
##
#M ConductorOfGoodSemigroup(M)
#M Conductor(M)
## returns the conductor of M
##################################################
InstallMethod(ConductorOfGoodSemigroup,
"Calculates the conductor of the semigroup",
[IsGoodSemigroup ],50,
function(M)
local e,s,c,ce,cs,c1,c2;
if HasConductor(M) then
return(Conductor(M));
fi;
if HasSmallElements(M) then
s:=SmallElements(M);
c:=s[Length(s)];
SetConductor(M,c);
return c;
fi;
if IsGoodSemigroupByDuplication(M) then
Info(InfoNumSgps,2,"Using semigroup duplication formula");
e:=IdealGS(M);
ce:=Conductor(e);
SetConductor(M,[ce,ce]);
return [ce,ce];
fi;
if IsGoodSemigroupByAmalgamation(M) then
Info(InfoNumSgps,2,"Using amalgamation formula");
e:=IdealGS(M);
ce:=Conductor(e);
s:=NumericalSemigroupGS(M);
c:=MorphismGS(M);
cs:=CeilingOfRational(ce/c);
while true do
cs:=cs-1;
if (cs in s) and not(2*cs in e) then
SetConductor(M,[cs+1,ce]);
return [cs+1,ce];
fi;
if cs<0 then
SetConductor(M,[0,ce]);
return [0,ce];
fi;
od;
fi;
if IsGoodSemigroupByCartesianProduct(M) then
Info(InfoNumSgps,2,"This is a cartesian product, so the two conductors in a list");
return([Conductor(NumericalSemigroupListGS(M)[1]),
Conductor(NumericalSemigroupListGS(M)[2])]);
fi;
return fail;
end);
###################################################
##
#A SmallElements(M)
#A SmallElementsOfGoodSemigroup(M)
## returns de small elements of M, that is,
## the elements below the conductor
##################################################
InstallMethod(SmallElementsOfGoodSemigroup,
"Calculates the small elements of the semigroup",
[IsGoodSemigroup ],50,
function(M)
local C,box, sm;
if HasSmallElements(M) then
return SmallElements(M);
fi;
if IsGoodSemigroupByCartesianProduct(M) then
sm:=Cartesian(SmallElements(NumericalSemigroupListGS(M)[1]),
SmallElements(NumericalSemigroupListGS(M)[2]));
SetSmallElements(M,sm);
return sm;
fi;
C:=Conductor(M);
box:=Cartesian([0..C[1]],[0..C[2]]);
sm:=Intersection(box,M);
SetSmallElements(M,sm);
return sm;
end);
###############################################################
##
#A IsSymmetric(M)
## Determines if M is symmetric
###############################################################
InstallMethod(IsSymmetricGoodSemigroup,
"Determines if the good semigroup is symmetric",
[IsGoodSemigroup], function(M)
local sm, w1, w2, b1,b2, c;
c:=Conductor(M);
sm:=SmallElementsOfGoodSemigroup(M);
w1:=Length(Set(sm,x->x[1]));
w2:=Length(Set(sm,x->x[2]));
b1:=Length(Filtered(sm, x-> x[1]=c[1] and x[2]<c[2]));
b2:=Length(Filtered(sm, x-> x[2]=c[2] and x[1]<c[1]));
return Sum(c)=w1+w2+b1+b2-2;
end);
###################################################
##
#A MinimalGenerators(M)
#A MinimalGoodGeneratingSystemOfGoodSemigroup(M)
## returns the unique minimal good generating of the
## good semigroup M
###################################################
InstallMethod(MinimalGoodGeneratingSystemOfGoodSemigroup,
"Calculates the minimal generating system of the semigroup",
[IsGoodSemigroup ],50,
function(M)
local filter,mingen,C;
## G is a given set of small elements
## filter outputs a subset that generates all
filter:=function(G,C)
local member1, member2, gen, g, gg, visited, left;
member1:=function(X,x)
if x[1]*x[2]=0 then
return x[2]<=0 and x[1]=0;
fi;
if x[1]<0 or x[2]< 0 then
return false;
fi;
return ForAny(X, y->member1(X,x-y));
end;
member2:=function(X,x)
if x[1]*x[2]=0 then
return x[1]<=0 and x[2]=0;
fi;
if x[1]<0 or x[2]< 0 then
return false;
fi;
return ForAny(X, y->member2(X,x-y));
end;
gen:=Set(ShallowCopy(G));
RemoveSet(gen,[0,0]);
# removing those that can be infimums of two others to make faster
# the next test
for g in G do
if g[1]<C[1] then
if First(gen, x->x[1]=g[1] and x[2]>g[2])<>fail then
RemoveSet(gen,g);
continue;
fi;
fi;
if g[2]<C[2] then
if First(gen, x->x[2]=g[2] and x[2]>g[2])<>fail then
RemoveSet(gen,g);
continue;
fi;
fi;
od;
if gen=[] then
return [];
fi;
visited:=[];
left:=gen;
while left<>[] and gen<>[] do
g:=left[1];
AddSet(visited,g);
left:=Difference(gen,visited);
gg:=Difference(gen,[g]);
if g[1]=C[1] then
if member2(gg,g) then
RemoveSet(gen,g);
fi;
elif g[2]=C[2] then
if member1(gg,g) then
RemoveSet(gen,g);
fi;
else
if member1(gg,g) and member2(gg,g) then
RemoveSet(gen,g);
fi;
fi;
od;
return gen;
end;
if IsGoodSemigroupByCartesianProduct(M) then
Print("ToDo\n");
return fail;
fi;
C:=Conductor(M);
if HasGenerators(M) then
mingen:=filter(Generators(M),C);
#SetGenerators(M,mingen);
return mingen;
fi;
mingen:=filter(SmallElementsOfGoodSemigroup(M),C);
SetGenerators(M,mingen);
return mingen;
end);
###############################################################
##
#F GoodSemigroupBySmallElements(M)
## Constructs good semigroup from a set of small elements
###############################################################
InstallGlobalFunction(GoodSemigroupBySmallElements, function(X)
local M, C, c, sm;
if not(IsRectangularTable(X)) and ForAll(X, x->Length(x)=2) then
Error("The argument must be a list of pairs of positive integers");
fi;
if not(ForAll(X, x->IsInt(x[1]) and IsInt(x[2]) and x[1]>=0 and x[2]>=0)) then
Error("The argument must be a list of pairs of positive integers");
fi;
if not(RepresentsSmallElementsOfGoodSemigroup(X)) then
Error("This set is not the set of small elements of a good semigroup");
fi;
C:=[Maximum(List(X,x->x[1])),Maximum(List(X,x->x[2]))];
#now we see if C is the minimum conductor
c:=C;
sm:=ShallowCopy(X);
while ((c-[0,1]) in sm) or ((c-[1,0]) in sm) do
if ((c-[0,1]) in sm) and ((c-[1,0]) in sm) then #c-[1,1] also in sm
c:=c-[1,1];
elif c-[0,1] in sm then
c:=c-[0,1];
else
c:=c-[1,0];
fi;
od;
if C<>c then #small elements must be redefined
Info(InfoNumSgps,2,"Conductor redefined");
sm:=Filtered(X, x->x[1]<=c[1] and x[2]<=c[2]);
fi;
M:=Objectify(GoodSemigroupsType, rec());
#SetGenerators(M,gen);
SetConductor(M,c);
SetSmallElements(M,sm);
return M;
end);
###############################################################
##
#F ArfGoodSemigroupClosure(M)
## Constructs Arf good semigroup closure of M
###############################################################
InstallGlobalFunction(ArfGoodSemigroupClosure,function(s)
local CompatibilityLevelOfMultiplicitySequences, s1, s2, t1, t2, sm, sma, c, included, i, cand, ca, c1, c2, k, seq1, seq2, tail1, tail2, car;
CompatibilityLevelOfMultiplicitySequences:=function(M)
local ismultseq, k, s, max, D, i,j, inarf;
# 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;
# tests if m is a multiplicity sequence
ismultseq := function(m)
local n;
n:=Length(m);
return ForAll([1..n-1], i-> inarf(m[i], m{[i+1..n]}));
end;
if not(IsTable(M)) then
Error("The first argument must be a list of multiplicity sequences");
fi;
if Length(M)<>2 then
Error("We are so far only considering Arf good semigroups in N^2");
fi;
if not(ForAll(Union(M), IsPosInt)) then
Error("The first argument must be a list of multiplicity sequences");
fi;
if not(ForAll(M, ismultseq)) then
Error("The first argument must be a list of multiplicity sequences");
fi;
s:=[];
max:= Maximum(List(M, Length));
for i in [1..2] do
s[i]:=[];
for j in [1..Length(M[i])] do
s[i][j]:=First([j+1..Length(M[i])], k-> M[i][j]=Sum(M[i]{[j+1..k]}));
if s[i][j]=fail then
s[i][j]:=M[i][j]-Sum(M[i]{[j+1..Length(M[i])]})+Length(M[i])-j;
else
s[i][j]:=s[i][j]-j;
fi;
od;
od;
for i in [1..2] do
s[i]:=Concatenation(s[i],List([Length(s[i])+1..max],_->1));
od;
D:=Filtered([1..max], j->s[1][j]<>s[2][j]);
k:=[];
if D=[] then
k:=infinity;
else
k:=Minimum(Set(D, j->j+Minimum(s[1][j],s[2][j])));
fi;
return k;
end;
if not(IsGoodSemigroup(s)) then
Error("The argument must be a good semigroup");
fi;
sm := SmallElementsOfGoodSemigroup(s);
c:= Conductor(s);
s1:=Set(sm, x->x[1]);
s2:=Set(sm, x->x[2]);
s1:=NumericalSemigroupBySmallElements(s1);
s2:=NumericalSemigroupBySmallElements(s2);
t1:=ArfNumericalSemigroupClosure(s1);
t2:=ArfNumericalSemigroupClosure(s2);
c1:=Conductor(t1);
c2:=Conductor(t2);
seq1:=MultiplicitySequenceOfNumericalSemigroup(t1);
seq2:=MultiplicitySequenceOfNumericalSemigroup(t2);
k:=CompatibilityLevelOfMultiplicitySequences([seq1,seq2]);
t1:=Intersection([0..c[1]],t1);
t2:=Intersection([0..c[2]],t2);
ca:=[c1,c2];
i:=1;
included:=true;
while included do
if i>Length(t1) or i>Length(t2) then
i:=i-1;
sma:=List([1..i], i->[t1[i],t2[i]]);
return GoodSemigroupBySmallElements(sma);
fi;
if i>k+1 then
i:=i-1;
sma:=List([1..i], i->[t1[i],t2[i]]);
return GoodSemigroupBySmallElements(sma);
fi;
sma:=Union(List([1..i], i->[t1[i],t2[i]]), Cartesian(t1{[i+1..Length(t1)]}, t2{[i+1..Length(t2)]}));
if First(sm, x->not(x in sma))<> fail then
included:=false;
else
i:=i+1;
fi;
od;
i:=i-1;
tail1:=Intersection(t1{[i+1..Length(t1)]},[0..c[1]]);
tail2:=Intersection(t2{[i+1..Length(t2)]},[0..c[2]]);
car:=Cartesian(tail1,tail2);
sma:=Union(List([1..i], i->[t1[i],t2[i]]), car);
return GoodSemigroupBySmallElements(sma);
end);
InstallMethod(ArfClosure,
"Computes the Arf closure of a good semigroup",
[IsGoodSemigroup],
ArfGoodSemigroupClosure
);
###############################################################
##
#F MaximalElementsOfGoodSemigroup(M)
## returns the set of maximal elements of M
###############################################################
InstallGlobalFunction(MaximalElementsOfGoodSemigroup,function(g)
local sm;
if not(IsGoodSemigroup(g)) then
Error("The argument must be a good semigroup");
fi;
sm:=SmallElements(g);
return Filtered(Difference(sm,[Conductor(g)]), x->not(ForAny(sm,
y->((y[1]=x[1] and y[2]>x[2]) or (y[1]>x[1] and y[2]=x[2])))));
end);
###############################################################
##
#F IrreducibleMaximalElementsOfGoodSemigroup(M)
## returns the set of irreducible maximal elements of M
###############################################################
InstallGlobalFunction(IrreducibleMaximalElementsOfGoodSemigroup,
function(g)
local mx;
mx:=MaximalElementsOfGoodSemigroup(g);
if Length(mx)=1 then
return mx;
fi;
return Filtered(Difference(mx,[[0,0]]), x->not(ForAny(Difference(mx,[[0,0]]), y->y<>x and (y[1]<=x[1]) and (y[2]<=x[2]) and ((x-y) in mx))));
end);
###############################################################
##
#F GoodSemigroupByMaximalElements(S1,S2,mx,c)
## returns the good semigroup determined by removing from
## S1 x S2 the set of points "above" a maximal element; c is
## the conductor
###############################################################
InstallGlobalFunction(GoodSemigroupByMaximalElements,
function(s1,s2,mx,c)
local l1,l2, m1,m2,c1,c2,q, v, cc, g1,g2;
if not(IsNumericalSemigroup(s1)) then
Error("The first argument must be a numerical semigroup");
fi;
if not(IsNumericalSemigroup(s2)) then
Error("The second argument must be a numerical semigroup");
fi;
l1:=List(mx,x->x[1]);
l2:=List(mx,x->x[2]);
q:=c;
# removed because this is true only for curves
#if ForAny(mx, x-> not(q-x in mx)) then
# Error("There is no symmetry in the third argument");
#fi;
g1:=Intersection([0..q[1]+1],s1);
g2:=Intersection([0..q[2]+1],s2);
cc:=Cartesian(g1,g2);
return GoodSemigroupBySmallElements(Difference(cc,
Filtered(cc, x->ForAny(mx,
y->((y[1]=x[1] and x[2]>y[2]) or (x[1]>y[1] and y[2]=x[2]))))
));
end);
###################################################
##
#M BelongsToGoodSemigroup
## decides if a vector is in the semigroup
##################################################
InstallMethod(BelongsToGoodSemigroup,
"Tests if the vector is in the semigroup",
[IsHomogeneousList, IsGoodSemigroup], 50,
function(v, a)
local S,T,E,c,s,t,sprime, X, saturation, C,edge1,edge2, sm, edge;
# G is a set of points;
# computes the saturation wrt sum (cutted by the edges) and inf
saturation:=function(G)
local inf, O, OO, new,i,j, o;
inf:=function(u,v)
return [Minimum(u[1],v[1]),Minimum(u[2],v[2])];
end;
O:=G;
# sum saturation
repeat
new:=[];
for i in [1..Length(O)] do
for j in [i.. Length(O)] do
o:=inf(C,O[i]+O[j]);
if not(o in O) then
Add(new, o);
fi;
od;
od;
O:=Union(O,new);
until new=[];
O:=Union(O,[[0,0]]);
#inf saturation
repeat
new:=[];
for i in [1..Length(O)] do
for j in [i.. Length(O)] do
o:=inf(O[i],O[j]);
if not(o in O) then
Add(new, o);
fi;
od;
od;
O:=Union(O,new);
until new=[];
# #good saturation x coordinate
# repeat
# new:=First(O, x->x[1]<C[1] and ForAny(O,y-> x[1]=y[1] and x[2]<y[2] and not(ForAny(O, z->x[2]=z[2] and z[1]>x[1]))));
# if new<>fail then
# Add(O,[C[1],new[2]]);
# fi;
# until new=fail;
# #good saturation y coordinate
# repeat
# new:=First(O, x->x[2]<C[2] and ForAny(O,y-> x[2]=y[2] and x[1]<y[1] and not(ForAny(O, z->x[1]=z[1] and z[2]>x[2]))));
# if new<>fail then
# Add(O,[new[1],C[2]]);
# fi;
# until new=fail;
return O;
end;
if Length(v)<>2 then
Error("The first argument must be a list with two integers (a pair)");
fi;
if not(ForAll(v, IsInt)) then
Error("The first argument must be a list with two integers (a pair)");
fi;
if IsGoodSemigroupByDuplication(a) then
S:=NumericalSemigroupGS(a);
E:=IdealGS(a);
if v[1]=v[2] then
return v[1] in S;
fi;
if v[1]<v[2] then
return (v[1] in E) and (v[2] in S);
fi;
if v[2]<v[1] then
return (v[2] in E) and (v[1] in S);
fi;
fi;
if IsGoodSemigroupByAmalgamation(a) then
S:=NumericalSemigroupGS(a);
E:=IdealGS(a);
c:=MorphismGS(a);
T:=UnderlyingNSIdeal(E);
s:=v[1];
t:=v[2];
if not(s in S) then
return false;
fi;
if not(t in T) then
return false;
fi;
if t=c*s then
return true;
fi;
if (c*s in E) and (t in E) then
return true;
fi;
if t< c*s then
return t in E;
fi;
if t>c*s then
if not(c*s in E) then
return false;
fi;
if t in E then
return true;
fi;
if not(IsInt(t/c)) then
return false;
fi;
return t/c in S;
fi;
fi;
if IsGoodSemigroupByCartesianProduct(a) then
return v[1] in NumericalSemigroupListGS(a)[1] and
v[2] in NumericalSemigroupListGS(a)[2];
fi;
if HasSmallElements(a) then
C:=Conductor(a);
if v[1]>=C[1] and v[2]>=C[2] then
return true;
fi;
sm:=SmallElements(a);
if v[1]>C[1] then
edge:=Filtered(sm,x->x[1]=C[1]);
return ForAny(edge, x->x[2]=v[2]);
fi;
if v[2]>C[2] then
edge:=Filtered(sm,x->x[2]=C[2]);
return ForAny(edge, x->x[1]=v[1]);
fi;
return v in sm;
fi;
if HasGenerators(a) then
X:=Generators(a);
C:=Conductor(a);
if v[1]>=C[1] and v[2]>=C[2] then
return true;
fi;
if not(HasSmallElements(a)) then
SetSmallElements(a,saturation(X));
fi;
sm:=SmallElements(a);
if v[1]>C[1] then
edge:=Filtered(sm,x->x[1]=C[1]);
return ForAny(edge, x->x[2]=v[2]);
fi;
if v[2]>C[2] then
edge:=Filtered(sm,x->x[2]=C[2]);
return ForAny(edge, x->x[1]=v[1]);
fi;
return v in sm;
fi;
return false;
end);
###################################################
##
#M BelongsToGoodSemigroup
## decides if a vector is in the semigroup
##################################################
InstallMethod( \in,
"for good semigroups",
[ IsHomogeneousList, IsGoodSemigroup],
function( v, a )
return BelongsToGoodSemigroup(v,a);
end);
###################################################
##
#M Equality of good semigroups
## decides if the two good semigroups are equal
##################################################
InstallMethod( \=,
"for good semigroups",
[ IsGoodSemigroup, IsGoodSemigroup],
function( a, b )
return Conductor(a)=Conductor(b) and SmallElements(a)=SmallElements(b);
end);
#############################################################################
##
#M ViewObj(S)
##
## This method for good semigroups.
##
#############################################################################
InstallMethod( ViewObj,
"Displays an Affine Semigroup",
[IsGoodSemigroup],
function( S )
Print("<Good semigroup>");
end);
#############################################################################
##
#M ViewString(S)
##
## This method for good semigroups.
##
#############################################################################
InstallMethod( ViewString,
"String of an Affine Semigroup",
[IsGoodSemigroup],
function( S )
return ("Good semigroup");
end);
#############################################################################
##
#M Display(S)
##
## This method for good semigroups. ## under construction... (= View)
##
#############################################################################
InstallMethod( Display,
"Displays an Affine Semigroup",
[IsGoodSemigroup],
function( S )
Print("<Good semigroup>");
end);
#####################################################
##
#F ProjectionOfGoodSemigroup:=function(S,num)
## Given a good semigroup S it returns the num-th numerical semigroup projection
#####################################################
InstallGlobalFunction(ProjectionOfGoodSemigroup,
function(S,num)
local small,S1,S2;
if not(IsGoodSemigroup(S)) then
Error("The first argument must be a good semigroup");
fi;
if not(num=1 or num=2) then
Error("The second argument must be 1 or 2");
fi;
small:=SmallElements(S);
if num=1 then
return NumericalSemigroupBySmallElements(Set([1..Length(small)],i->small[i][1]));
fi;
if num=2 then
return NumericalSemigroupBySmallElements(Set([1..Length(small)],i->small[i][2]));
fi;
end);
#####################################################
##
#F GenusOfGoodSemigroup:=function(S)
## Given a good semigroup S it returns its genus
#####################################################
InstallGlobalFunction(GenusOfGoodSemigroup,
function(S)
if not(IsGoodSemigroup(S)) then
Error("The argument must be a good semigroup");
fi;
return Length(MaximalElementsOfGoodSemigroup(S))+Genus(ProjectionOfGoodSemigroup(S,1))+Genus(ProjectionOfGoodSemigroup(S,2));
end);
InstallMethod(Genus,"Genus for a good semigroup",[IsGoodSemigroup], GenusOfGoodSemigroup );
#####################################################
##
#F LengthOfGoodSemigroup:=function(S)
## Given a good semigroup S it returns its length
#####################################################
InstallGlobalFunction(LengthOfGoodSemigroup,
function(S)
local c;
if not(IsGoodSemigroup(S)) then
Error("The argument must be a good semigroup");
fi;
c:=Conductor(S);
return c[1]+c[2]-GenusOfGoodSemigroup(S);
end);
InstallMethod(Length,"for a good semigroup",[IsGoodSemigroup], LengthOfGoodSemigroup );
#####################################################
#F AperySetOfGoodSemigroup:=function(S)
## Given a good semigroup S it returns a list with the elements of the Apery Set
#####################################################
InstallGlobalFunction(AperySetOfGoodSemigroup,
function(S)
local c,small,i,j,AddElementsOverTheConductor;
AddElementsOverTheConductor:=function(v,w)
local ags,i,j;
if Length(v)=1 then
ags:=[];
for i in [v[1]..w[1]] do
ags:=Union(ags,[[i]]);
od;
else
ags:=[];
for i in AddElementsOverTheConductor(v{[1..Length(v)-1]},w{[1..Length(v)-1]}) do
for j in [v[Length(v)]..w[Length(v)]] do
ags:=Union(ags,[Concatenation(i,[j])]);
od;
od;
fi;
return ags;
end;
if not(IsGoodSemigroup(S)) then
Error("The argument must be a good semigroup");
fi;
c:=Conductor(S);
small:=SmallElements(S);
#First we add to the small elements the elements on the infinite lines that can to become elements of the AperySet.
for i in Filtered(small,j->j[1]=c[1]) do
for j in [c[1]+1..c[1]+small[2][1]] do
small:=Union(small,[[j,i[2]]]);
od;
od;
for i in Filtered(small,j->j[2]=c[2]) do
for j in [c[2]+1..c[2]+small[2][2]] do
small:=Union(small,[[i[1],j]]);
od;
od;
return Filtered(Union(small,AddElementsOverTheConductor(c,c+small[2])),i-> not i-small[2] in small);
end);
#####################################################
#F StratifiedAperySetOfGoodSemigroup:=function(S)
## Given a good semigroup S, it returns a list
# where the elements are the levels of the AperySet
#####################################################
InstallGlobalFunction(StratifiedAperySetOfGoodSemigroup,
function(S)
local Dominance,ce,small,A,ags,temp,temp2;
Dominance:=function(v,w,cond)
return v=w or ForAll([1..Length(v)], i->v[i]<w[i] or w[i]=cond[i]);
end;
if not(IsGoodSemigroup(S)) then
Error("The argument must be a good semigroup");
fi;
small:=SmallElements(S);
ce:=Conductor(S)+small[2];
A:=AperySetOfGoodSemigroup(S);
ags:=[];
while A<>[] do
temp:=Filtered(A,i->Length(Filtered(A,j->Dominance(i,j,ce)))=1);
temp2:=Filtered(temp,i->Filtered(temp,j->j[1]=i[1] and j[2]>i[2])=[] or Filtered(temp,j->j[2]=i[2] and j[1]>i[1])=[]);
ags:=Union(ags,[temp2]);
A:=Filtered(A,i->not i in temp2);
od;
Info(InfoNumSgps,2,"Number of levels ", Length(ags));
return ags;
end);
#####################################################
#F AbsoluteIrreduciblesOfGoodSemigroup:=function(S)
## Given a good semigroup S, the function returns the irreducible absolutes of S.
# These are the elements that generates S as semiring.
#####################################################
InstallGlobalFunction(AbsoluteIrreduciblesOfGoodSemigroup,
function(S)
local ElementsOnTheEdge,TransformToInf,c,small,irrabsf,irrabsi,infi,edge,i;
if not(IsGoodSemigroup(S)) then
Error("The argument must be a good semigroup");
fi;
#This function check if an elements has a coordinate equal to the conductor.
ElementsOnTheEdge:=function(vs,c)
return vs[1]=c[1] or vs[2]=c[2];
end;
#This function transforms the elements with a coordinate equal to the conductor in infinities.
TransformToInf:=function(vs,c)
local a,i;
a:=ShallowCopy(vs);
for i in Filtered([1..2],j->vs[j]=c[j]) do
a[i]:=infinity;
od;
return a;
end;
c:=Conductor(S);
small:=Difference(SmallElements(S),[[0,0]]);
#Computation of finite irreducible absolutes.
irrabsf:=IrreducibleMaximalElementsOfGoodSemigroup(S);
#I take the elements of S different from the conductor but with a coordinate equal to this one.
edge:=Filtered(small,k->k<>c and ElementsOnTheEdge(k,c));
infi:=[];
#Here I add to Infi the infinities in the square over the conductor (built considering the multiplicity)
for i in [0..small[1][1]-1] do
infi:=Union(infi,[[c[1]+i,infinity]]);
od;
for i in [0..small[1][2]-1] do
infi:=Union(infi,[[infinity,c[2]+i]]);
od;
#Here I add the infinities under the conductor
for i in edge do
infi:=Union(infi,[TransformToInf(i,c)]);
od;
#Computation of infinite irreducible absolutes
irrabsi:=Filtered(infi,i->Filtered(small,j->i-j in infi)=[]);
return Union(irrabsi,irrabsf);
end);
#####################################################
#F TracksOfGoodSemigroup:=function(S)
## Given a good semigroup S, the function returns the tracks of S.
#####################################################
InstallGlobalFunction(TracksOfGoodSemigroup,
function(S)
local CompareGS,MinimumGS,I,RemoveLabels,GluePieceOfTrack,ComputePieceOfTrack,T,temp;
if not(IsGoodSemigroup(S)) then
Error("The argument must be a good semigroup");
fi;
CompareGS:=function(v,w)
return ForAll([1..Length(v)], i->v[i]<=w[i]);
end;
MinimumGS:=function(v,w)
return List([1..Length(v)],i->Minimum(v[i],w[i]));
end;
#It glues a new piece of track to an existing track. T is the list of all piece of track. V is a list of two elements,
# V[1] represents not complete tracks and V[2] the complete tracks.
#The function add a new piece to the incomplete tracks and returns the updated V.
GluePieceOfTrack:=function(T,V)
local ags,temp,i,j;
ags:=[[],[]];
ags[2]:=ShallowCopy(V[2]);
for i in V[1] do
temp:=i[Length(i)];
if temp="last" then
ags[2]:=Union(ags[2],[i]);
else
for j in Filtered(T,k->k[1]=temp) do
ags[1]:=Union(ags[1],[Concatenation(i,[j[2]])]);
od;
fi;
od;
return ags;
end;
#This funcion compute all possibles piece of track of a good semigroups having irreducible absolutes I
ComputePieceOfTrack:=function(I)
local IsAPOT,MaximalRed,ags,first,last,i;
#It check if between two irreducible absolutes there is a piece of track. It check if their minimum overcome
#the maximum in both direction or is equal to this one in entrambe le direzioni o coincide
IsAPOT:=function(a,b)
local min;
if CompareGS(a[1],b[1]) or CompareGS(b[1],a[1]) then return false; else if a[1][1]>b[1][1] then return false; else
min:=MinimumGS(a[1],b[1]); return min[2]>=a[3] and min[1]>=b[2];
fi; fi;
end;
#If (x,y) is an irreducible absolute it returns (x1,y1), where (x,y1) is the greatest irr. abs. under (x,y)
# and (x1,y) is the greatest irr. abs. on the left of (x,y).
MaximalRed:=function(v,I)
local Factorize,ind,temp,temp2,temp3;
Factorize:=function(n,l)
local a,b,ags,i,c,j,a1;
if l=[] then
return [];
else
a1:=Filtered([1..Length(l)],i->l[i]<>infinity);
a:=List(a1,k->l[k]);
b:=FactorizationsIntegerWRTList(n,a);
ags:=[];
for i in b do
c:=List([1..Length(l)],o->0);
j:=1;
while j<=Length(a1) do
c[a1[j]]:=i[j]; j:=j+1;
od;
ags:=Union(ags,[c]);
od;
return ags;
fi;
end;
if not v in I then
return [0,0];
else
if infinity in v then
temp3:=[0,0];
ind:=First([1,2],i->v[i]<>infinity);
temp3[3-ind]:=0;
temp:=Filtered(I,i->i[ind]<v[ind]);
temp2:=List(List(Factorize(v[ind],List(temp,i->i[ind])),j->Sum(List([1..Length(j)],k->j[k]*temp[k]))),k1->k1[3-ind]);
if temp2=[] then
temp3[ind]:=0;
return Reversed(temp3);
else
temp3[ind]:=Maximum(temp2);
return Reversed(temp3);
fi;
else
temp3:=[0,0];
for ind in [1,2] do
temp:=Filtered(I,i->i[ind]<v[ind]);
temp2:=List(List(Factorize(v[ind],List(temp,i->i[ind])),j->Sum(List([1..Length(j)],k->j[k]*temp[k]))),k1->k1[3-ind]);
if temp2=[] then
temp3[ind]:=0;
else
temp3[ind]:=Maximum(temp2);
fi;
od;
return Reversed(temp3);
fi;
fi;
end;
#If (x,y) is an irreducible absolute it returns ((x,y),x1,y1), where (x,y1) is the greatest irr. abs. under (x,y)
# and (x1,y) is the greatest irr. abs. on the left of (x,y).
I:=List(I,i->Concatenation([i],MaximalRed(i,I)));
#I add all the Piece Of Track
ags:=List(Filtered(Cartesian(I,I),i->IsAPOT(i[1],i[2])),k->[k[1][1],k[2][1]]);
#I add the point of start and the point of end
first:=Filtered(I,i->i[2]=0);
last:=Filtered(I,i->i[3]=0);
for i in first do
ags:=Union(ags,[["first",i[1]]]);
od;
for i in last do
ags:=Union(ags,[[i[1],"last"]]);
od;
return ags;
end;
#This function removes the label "first" and "last" in the tracks.
RemoveLabels:=function(T)
return List(T,i->Filtered(i,j->j<>"last" and j<>"first"));
end;
I:=AbsoluteIrreduciblesOfGoodSemigroup(S);
T:=ComputePieceOfTrack(I);
#The idea is to create the list of all tracks, adding one by one the piece of tracks in all possible way, reccalling
#GluePieceOfTrack until all possible track are completed (V[1]=[])
temp:=[[["first"]],[]];
temp:=GluePieceOfTrack(T,temp);
while temp[1]<>[] do
temp:=GluePieceOfTrack(T,temp);
od;
return RemoveLabels(temp[2]);
end);
###############################################################
##
#P IsLocal(S)
## Determines if S is local
###############################################################
InstallMethod(IsLocal,
"Determines if the good semigroup is local",
[IsGoodSemigroup], function(S)
local small;
small:=Difference(SmallElements(S),[[0,0]]);
return ForAll([1..Length(small)],i->small[i][1]<>0);
end);
###############################################################
##
#A Multiplicity(S)
## Determines the multiplicity of S
###############################################################
InstallMethod(Multiplicity,
"Returns the multiplicity of a local good semigroup",
[IsGoodSemigroup], function(S)
local small;
if not(IsLocal(S)) then
Error("The good semigroup must be local");
fi;
small:=SmallElements(S);
return small[2];
end);
[ Verzeichnis aufwärts0.52unsichere Verbindung
Übersetzung europäischer Sprachen durch Browser
]
|