Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418346############################################################################# ## #W numsgp-def.gi Manuel Delgado <[email protected]> #W Pedro A. Garcia-Sanchez <[email protected]> #W Jose Morais <[email protected]> ## ## #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. ## ############################################################################# ############################################################################# ## #F NumericalSemigroupByGenerators(arg) ## ## Returns the numerical semigroup generated by arg. ## ############################################################################# InstallGlobalFunction(NumericalSemigroupByGenerators, function(arg) local L, M, a, b, fr, u, small, i; if IsList(arg[1]) then L := Difference(Set(arg[1]),[0]); else L := Difference(Set(arg),[0]); fi; if L=[] then Error("There should be at list one generator.\n"); fi; if not ForAll(L, x -> IsPosInt(x)) then Error("The arguments should be positive integers.\n"); fi; if Gcd(L) <> 1 then Error("The greatest common divisor is not 1.\n"); fi; M:= Objectify( NumericalSemigroupsType, rec()); SetGenerators(M,L); if 1 in L then SetMinimalGenerators(M,[1]); SetModularConditionNS(M,[1,2]); SetGaps(M,Set([])); SetSmallElements(M,Set([0])); elif Length(L) = 2 then # a non-trivial numerical semigroup has at least 2 generators SetMinimalGenerators(M, L); a := L[1]; b := L[2]; fr := a*b - a - b; #(Sylvester) SetFrobeniusNumberOfNumericalSemigroup(M,fr); # M is modular... u:=PowerModInt(b,-1,a);#the inverse ou b mod a SetModularConditionNS(M,[b*u,a*b]); fi; #when the set of generators is an interval, using Rosales and Garcia-Sanchez (pacific), the Frobenius number and the "small elements" are easily computed if not (1 in L) and (Length(L) = Maximum(L) - Minimum(L)+1) then a := L[1]; b := L[Length(L)]-a; fr := CeilingOfRational((a-1)/b)*a-1; # removed the computation for small elements # this should be put in a separate method # small := [0]; # i := 1; # while i*(a+b) < fr+1 do # Append(small,[i*a..i*(a+b)]); # i := i+1; # od; # Append(small,[fr+1]); # # SetSmallElements(M,small); SetFrobeniusNumber(M,fr); SetMinimalGenerators(M,[a..Minimum(2*a-1,a+b)]); # M is proportionaly modular... SetProportionallyModularConditionNS(M, [a+b,a*(a+b),b]); SetClosedIntervalNS(M,[L[1],L[Length(L)]]); fi; return M; end); ############################################################################# ## #F NumericalSemigroupByMinimalGenerators(arg) ## ## Returns the numerical semigroup minimally generated by arg. ## If the generators given are not minimal, the minimal ones ## are computed and used. ## ############################################################################# InstallGlobalFunction(NumericalSemigroupByMinimalGenerators, function(arg) local L, S, M, l, minimalGSNS, sumNS; ##################################################### # Computes the sum of subsets of numerical semigroups sumNS := function(S,T) local mm, s, t, R; R := []; mm := Minimum(Maximum(S),Maximum(T)); for s in S do for t in T do if s+t > mm then break; else AddSet(R,s+t); fi; od; od; return R; end; ## End of sumNS(S,T) -- minimalGSNS := function(L) local res, gen, ss, sss, ssss, i, ngen; if 1 in L then return [1]; fi; gen := ShallowCopy(L); # a naive reduction of the number of generators ss := sumNS(gen,gen); gen := Difference(gen,ss); if ss <> [] then sss := sumNS(ss,gen); gen := Difference(gen,sss); if sss <> [] then ssss := sumNS(sss,gen); gen := Difference(gen,ssss); fi; fi; if Length(gen) = 2 then return gen; fi; i := Length(gen); while i >= 2 do ngen := Difference(gen, [gen[i]]); if Gcd(ngen) = 1 and BelongsToNumericalSemigroup(gen[i], NumericalSemigroup(ngen)) then gen := ngen; i := i - 1; else i := i - 1; fi; od; return gen; end; ## End of minimalGSNS(L) -- if IsList(arg[1]) then L := Difference(Set(arg[1]),[0]); else L := Difference(Set(arg),[0]); fi; if L=[] then Error("There should be at least one generator.\n"); fi; if not ForAll(L, x -> IsPosInt(x)) then Error("The arguments should be positive integers.\n"); fi; if Gcd(L) <> 1 then Error("The greatest common divisor is not 1"); fi; l := minimalGSNS(L); if not Length(L) = Length(l) then Info(InfoWarning,1,"The list ", L, " can not be the minimal generating set. The list ", l, " will be used instead."); L := l; fi; M:= Objectify( NumericalSemigroupsType, rec() ); # Setter(GeneratorsOfNumericalSemigroup)( M, AsList( L ) ); SetMinimalGenerators(M,L); SetGenerators(M,L); return M; end); ############################################################################# ## #F NumericalSemigroupByMinimalGeneratorsNC(arg) ## ## Returns the numerical semigroup minimally generated by arg. ## No test is made about args' minimality. ## ############################################################################# InstallGlobalFunction(NumericalSemigroupByMinimalGeneratorsNC, function(arg) local L, S, M; if IsList(arg[1]) then L := Difference(Set(arg[1]),[0]); else L := Difference(Set(arg),[0]); fi; if not ForAll(L, x -> IsPosInt(x)) then Error("The arguments should be positive integers"); fi; if Gcd(L) <> 1 then Error("The greatest common divisor is not 1"); fi; M:= Objectify( NumericalSemigroupsType, rec() ); # Setter(GeneratorsOfNumericalSemigroup)( M, AsList( L ) ); SetMinimalGenerators(M,L); SetGenerators(M,L); return M; end); ############################################################################# ## #F ModularNumericalSemigroup(a,b) ## ## Returns the modular numerical semigroup satisfying ax mod b <= x ## ############################################################################# InstallGlobalFunction(ModularNumericalSemigroup, function(a,b) local M; if not IsPosInt(a) or not IsPosInt(b) then Error("ModularNumericalSemigroup has 2 positive integers as arguments"); fi; M:= Objectify( NumericalSemigroupsType, rec() ); SetModularConditionNS(M,[a,b]); if (a = 1) or (b = 1) then #the semigroup is the entire N SetMinimalGenerators(M,[1]); fi; # a modular semigroup is also a proportionally modular semigroup SetProportionallyModularConditionNS(M, [a,b,1]); # a modular semigroup is generated by an interval if a > 1 then SetClosedIntervalNS(M,[b/a,b/(a-1)]); fi; return M; end); ############################################################################# ## #F ProportionallyModularNumericalSemigroup(a,b,c) ## ## Returns the proportionally modular numerical semigroup ## satisfying ax mod b <= cx ## ############################################################################# InstallGlobalFunction(ProportionallyModularNumericalSemigroup, function(a,b,c) local M, m; if not IsPosInt(a) or not IsPosInt(b) or not IsPosInt(c) then Error("ProportionallyModularNumericalSemigroup has 3 positive integers as arguments"); fi; M:= Objectify( NumericalSemigroupsType, rec() ); SetProportionallyModularConditionNS(M,[a,b,c]); if a > c then SetClosedIntervalNS(M, [b/a,b/(a-c)]); else SetClosedIntervalNS(M, [1,2]); fi; m := CeilingOfRational(b/a); if a <> c and b/(a-c) > 2*m -1 then #the semigroup is a halfline SetSmallElementsOfNumericalSemigroup(M,Set([0,m])); SetFrobeniusNumberOfNumericalSemigroup(M,m-1); # SetMinimalGeneratorsNS(M, [m,2*m-1]); # bug pointed out by Ilya Frolov (fixed from version 1.0.1) SetMinimalGenerators(M, [m..2*m-1]); fi; if b = 1 then #the semigroup is the entire N SetMinimalGenerators(M, [1]); fi; if c = 1 then SetModularConditionNS(M, [a,b]); fi; return M; end); ############################################################################# ## #F NumericalSemigroupByInterval(arg) ## ## Returns the numerical semigroup ## ############################################################################# InstallGlobalFunction(NumericalSemigroupByInterval, function(arg) local r, s, M, b1, a1, b2, a2, m; if IsList(arg[1]) and Length(arg[1])=2 then r := arg[1][1]; s := arg[1][2]; elif Length(arg)=2 then r := arg[1]; s := arg[2]; else Error("The argument of NumericalSemigroupByInterval must consist of a pair of rational numbers, <r> and <s> and with r < s"); fi; if IsInt(r) and IsInt(s) and r < s then return NumericalSemigroupByGenerators([r..s]); fi; if not (IsRat(r) and IsRat(s) and r < s) then Error("The argument of NumericalSemigroupByInterval must consist of a pair of rational numbers, <r> and <s> and with r < s"); fi; M:= Objectify( NumericalSemigroupsType, rec() ); SetClosedIntervalNS(M,[r,s]); ## the semigroup is proportionally modular (Lemma 4.12 [Rosales & Garcia-Sanchez - book]) b1 := NumeratorRat(r); a1 := DenominatorRat(r); b2 := NumeratorRat(s); a2 := DenominatorRat(s); SetProportionallyModularConditionNS(M, [a1*b2,b1*b2,a1*b2-a2*b1]); if b1*b2 = 1 then #the semigroup is the entire N SetMinimalGenerators(M,[1]); fi; if a1*b2-a2*b1 = 1 then SetModularConditionNS(M, [a1*b2,b1*b2]); fi; m := CeilingOfRational(r); if s > 2*m -1 then #the semigroup is a halfline SetSmallElements(M,Set([0,m])); SetFrobeniusNumberOfNumericalSemigroup(M,m-1); SetMinimalGenerators(M, [m,2*m-1]); fi; return M; end); ############################################################################# ## #F NumericalSemigroupByOpenInterval(arg) ## ## Returns the numerical semigroup ## ############################################################################# InstallGlobalFunction(NumericalSemigroupByOpenInterval, function(arg) local M, r, s; if IsList(arg[1]) and Length(arg[1])=2 then r := arg[1][1]; s := arg[1][2]; elif Length(arg)=2 then r := arg[1]; s := arg[2]; else Error("The argument of NumericalSemigroupByOpenInterval must consist of a pair of rational numbers"); fi; if not (IsRat(r) and IsRat(s) and r < s) then Error("The argument of NumericalSemigroupByOpenInterval must consist of a pair of rational numbers, <r> and <s> and with r < s"); fi; M:= Objectify( NumericalSemigroupsType, rec() ); SetOpenIntervalNS(M,[r,s]); return M; end); ############################################################################# ## #F NumericalSemigroupBySubAdditiveFunction(L) ## ## Returns the numerical semigroup specified by the subadditive ## function L. ## ############################################################################# InstallGlobalFunction(NumericalSemigroupBySubAdditiveFunction, function(L) local M; if not RepresentsPeriodicSubAdditiveFunction(L) then Error("The argument of NumericalSemigroupBySubAdditiveFunction must be a subadditive function"); fi; M:= Objectify( NumericalSemigroupsType, rec() ); SetSubAdditiveFunctionNS(M,L); return M; end); ############################################################################# ## #F NumericalSemigroupByAperyList(L) ## ## Returns the numerical semigroup specified by the Apery list L. ## ############################################################################# InstallGlobalFunction(NumericalSemigroupByAperyList, function(L) local i, M; if not IsAperyListOfNumericalSemigroup(L) then Error("The argument of NumericalSemigroupByAperyList must be The Apery List of some numerical semigroup"); fi; M:= Objectify( NumericalSemigroupsType, rec() ); SetAperyList(M,L); return M; end); ############################################################################# ## #F NumericalSemigroupBySmallElements(L) ## ## Returns the numerical semigroup specified by L, ## which must be the list of elements of a numerical semigroup, ## not greater than the Frobenius number + 1. ## ############################################################################# InstallGlobalFunction(NumericalSemigroupBySmallElements, function(L) local i, M, K, R; if not RepresentsSmallElementsOfNumericalSemigroup(L) then Error("The argument does not represent a numerical semigroup"); fi; if L = [0] or 1 in L then return NumericalSemigroup(1); fi; K := Difference([1..L[Length(L)]],L); R := Intersection([0..K[Length(K)]+1],L); M:= Objectify( NumericalSemigroupsType, rec() ); SetGaps(M,Difference([1..R[Length(R)]], R)); SetSmallElements(M,R); return M; end); ############################################################################# ## #F NumericalSemigroupBySmallElementsNC(L) ## ## NC version of NumericalSemigroupBySmallElements ## ############################################################################# InstallGlobalFunction(NumericalSemigroupBySmallElementsNC, function(L) local i, M, K, R; if L = [0] or 1 in L then return NumericalSemigroup(1); fi; K := Difference([1..L[Length(L)]],L); R := Intersection([0..K[Length(K)]+1],L); M:= Objectify( NumericalSemigroupsType, rec() ); SetGaps(M,Difference([1..R[Length(R)]], R)); SetSmallElements(M,R); return M; end); ############################################################################# ## #F NumericalSemigroupByGaps(L) ## ## Returns the numerical semigroup specified by L, ## which must be the list of gaps of a numerical semigroup. ## ############################################################################# InstallGlobalFunction(NumericalSemigroupByGaps, function(L) local i, M, K; K := Difference([0..L[Length(L)]+1],L); if not RepresentsSmallElementsOfNumericalSemigroup(K) then Error("The argument does not represent the gaps of a numerical semigroup"); fi; M:= Objectify( NumericalSemigroupsType, rec() ); SetGaps(M,L); SetSmallElements(M,K); return M; end); ############################################################################# ## #F NumericalSemigroupByFundamentalGaps(L) ## ## Returns the numerical semigroup specified by L, ## which must be the list of fundamental gaps of a numerical semigroup. ## ############################################################################# InstallGlobalFunction(NumericalSemigroupByFundamentalGaps, function(L) local i, M, K, G; G := Set(Flat(List(L,i->DivisorsInt(i)))); K := Difference([0..G[Length(G)]+1],G); if not RepresentsSmallElementsOfNumericalSemigroup(K) then Error("The argument does not represent the fundamental gaps of a numerical semigroup"); fi; M:= Objectify( NumericalSemigroupsType, rec() ); SetFundamentalGaps(M,L); SetGaps(M,G); SetSmallElements(M,K); return M; end); ############################################################################# ## #F NumericalSemigroupByAffineMap(a,b,c) ## Computes the smallest numerical semigroup ## containing c and closed under x->ax+b ## see http://arxiv.org/pdf/1505.06580v4.pdf ############################################################################# InstallGlobalFunction(NumericalSemigroupByAffineMap,function(a,b,c) local gs,gen, t ,sk; if not(ForAll([a,b,c],x-> IsInt(x) and x>=0)) then Error("The arguments must be integers"); fi; if not(Gcd(b,c)=1)then Error("The second and third arguments must be coprime"); fi; if not(a>0) then Error("The first argument must be a positive integer"); fi; if c=1 then return NumericalSemigroup(1); fi; t:=function(x) return a*x+b; end; gs:=[c]; gen:=c; sk:=0; while sk<c do gen:=t(gen); Add(gs,gen); sk:=a*sk+1; od; return NumericalSemigroup(gs); end); ############################################################################# ## #F NumericalSemigroup(arg) ## ## This function's first argument may be one of: ## "generators", "minimalgenerators", "modular", ## "propmodular", "elements", "gaps", ## "fundamentalgaps", "subadditive" or "apery" according to ## how the semigroup is being defined. ## The following arguments must conform to the arguments of ## the corresponding function defined above. ## By default, the option "generators" is used, so, ## gap> NumericalSemigroup(3,7); ## <Numerical semigroup with 2 generators> ## ############################################################################# InstallGlobalFunction(NumericalSemigroup, function(arg) local L, S, M; if IsString(arg[1]) then if arg[1] = "modular" then if Length(arg) = 3 then return ModularNumericalSemigroup(arg[2],arg[3]); else Error("For the modular case NumericalSemigroup must have 3 arguments"); fi; elif arg[1] = "propmodular" then if Length(arg) = 4 then return ProportionallyModularNumericalSemigroup(arg[2],arg[3],arg[4]); else Error("For the proportionally modular case NumericalSemigroup must have 4 arguments"); fi; elif arg[1] = "affinemap" then if Length(arg) = 4 then return NumericalSemigroupByAffineMap(arg[2],arg[3],arg[4]); else Error("For the affine map case NumericalSemigroup must have 4 arguments"); fi; elif arg[1] = "interval" then if Length(arg) = 3 then return NumericalSemigroupByInterval(arg[2],arg[3]); elif Length(arg) = 2 then return NumericalSemigroupByInterval(arg[2]); else Error("For the interval case NumericalSemigroup must have 2 or 3 arguments"); fi; elif arg[1] = "openinterval" then if Length(arg) = 3 then return NumericalSemigroupByOpenInterval(arg[2],arg[3]); elif Length(arg) = 2 then return NumericalSemigroupByOpenInterval(arg[2]); else Error("For the open interval case NumericalSemigroup must have 2 or 3 arguments"); fi; elif arg[1] = "fundamentalgaps" then return NumericalSemigroupByFundamentalGaps(arg[2]); elif arg[1] = "gaps" then return NumericalSemigroupByGaps(arg[2]); elif arg[1] = "elements" then return NumericalSemigroupBySmallElements(arg[2]); elif arg[1] = "subadditive" then return NumericalSemigroupBySubAdditiveFunction(arg[2]); elif arg[1] = "apery" then return NumericalSemigroupByAperyList(arg[2]); elif arg[1] = "generators" then return NumericalSemigroupByGenerators(Flat(arg{[2..Length(arg)]})); elif arg[1] = "minimalgenerators" then return NumericalSemigroupByMinimalGenerators(Flat(arg{[2..Length(arg)]})); else Error("Invalid first argument, it should be one of: \"modular\", \"propmodular\", \"interval\", \"openinterval\", \"fundamentalgaps\", \"gaps\", \"elements\", \"subadditive\", \"apery\", \"generators\", \"minimalgenerators\" "); fi; else if Length(arg) = 1 and IsList(arg[1]) then return NumericalSemigroupByGenerators(arg[1]); else return NumericalSemigroupByGenerators(arg{[1..Length(arg)]}); fi; fi; end); ######################################################################## ######################################################################## ############################################################################# ## #M PrintObj(S) ## ## This method for numerical semigroups. ## ############################################################################# InstallMethod( PrintObj, "prints a Numerical Semigroup", [ IsNumericalSemigroup], function( S ) if HasModularConditionNS(S) then Print("ModularNumericalSemigroup( ", ModularConditionNS(S), " )\n"); elif HasProportionallyModularConditionNS(S) then Print("ProportionallyModularNumericalSemigroup( ", ProportionallyModularConditionNS(S), " )\n"); elif HasGenerators(S) then Print("NumericalSemigroup( ", Generators(S), " )\n"); else Print("NumericalSemigroup( ", GeneratorsOfNumericalSemigroup(S), " )\n"); fi; end); ############################################################################# ## #M ViewString(S) ## ## This method for numerical semigroups. ## ############################################################################# InstallMethod( ViewString, "displays a Numerical Semigroup", [IsNumericalSemigroup], function( S ) if HasMinimalGenerators(S) and 1 in MinimalGenerators(S) then return ("The numerical semigroup N"); elif HasMinimalGenerators(S) then return Concatenation("Numerical semigroup with ", String(Length(MinimalGenerators(S))), " generators"); elif HasGenerators(S) then return Concatenation("Numerical semigroup with ", String(Length(Generators(S))), " generators"); elif HasModularConditionNS(S) then return Concatenation("Modular numerical semigroup satisfying ", String(ModularConditionNS(S)[1]),"x mod ",String(ModularConditionNS(S)[2]), " <= x"); elif HasProportionallyModularConditionNS(S) then return Concatenation("Proportionally modular numerical semigroup satisfying ", String(ProportionallyModularConditionNS(S)[1]),"x mod ",String(ProportionallyModularConditionNS(S)[2]), " <= ",String(ProportionallyModularConditionNS(S)[3]),"x"); else return ("Numerical semigroup"); fi; end); ############################################################################# ## #M ViewObj(S) ## ## This method for numerical semigroups. ## ############################################################################# InstallMethod( ViewObj, "displays a Numerical Semigroup", [IsNumericalSemigroup], function( S ) if HasMinimalGenerators(S) and 1 in MinimalGenerators(S) then Print("<The numerical semigroup N>"); elif HasMinimalGenerators(S) then Print("<Numerical semigroup with ", Length(MinimalGenerators(S)), " generators>"); elif HasGenerators(S) then Print("<Numerical semigroup with ", Length(Generators(S)), " generators>"); elif HasModularConditionNS(S) then Print("<Modular numerical semigroup satisfying ", ModularConditionNS(S)[1],"x mod ",ModularConditionNS(S)[2], " <= x >"); elif HasProportionallyModularConditionNS(S) then Print("<Proportionally modular numerical semigroup satisfying ", ProportionallyModularConditionNS(S)[1],"x mod ",ProportionallyModularConditionNS(S)[2], " <= ",ProportionallyModularConditionNS(S)[3],"x >"); else Print("<Numerical semigroup>"); fi; end); ############################################################################# ## #M Display(S) ## ## This method for numerical semigroups. ## ############################################################################# InstallMethod( Display, "displays a Numerical Semigroup", [IsNumericalSemigroup], function( S ) local M, u, L, condensed; condensed := function(L) local c, C,j, n, search, bool; C := []; bool := true; j := 0; c := L[1]; search := function(n) # searches the greatest subinterval starting in n local i, k; k := 0; for i in [Position(L,n).. Length(L)-1] do if not (L[i]+1 = L[i+1]) then c := L[i+1]; return [n..n+k]; fi; k := k+1; od; bool := false; return [n..L[Length(L)]]; end; while bool do Add(C,search(c)); od; return C; end; ## End of condensed() -- L := SmallElementsOfNumericalSemigroup(S); M := condensed(L); u := [M[Length(M)][1],"->"]; M[Length(M)] := u; return M; end); #################################################### #################################################### ## #P IsProportionallyModularNumericalSemigroup(S) ## ## Tests if a numerical semigroup is proportionally modular. ## ############################################################################# # this implementation is based in Theorem 5.35 of [RGbook] ############################################################################# InstallMethod(IsProportionallyModularNumericalSemigroup, "Tests if a Numerical Semigroup is proportionally modular", [IsNumericalSemigroup], function( S ) local gens, arrangements, gs, k, addgenerator, g, arrangement, b1, a1, b2, a2; if HasProportionallyModularConditionNS(S) then return true; fi; gens := MinimalGeneratingSystemOfNumericalSemigroup(S); # if Length(gens) <= 2 then # return true; # fi; if Length(gens) = 1 then SetClosedIntervalNS(S, [1,2]); SetProportionallyModularConditionNS(S, [1,1,1]); SetModularConditionNS(S, [1,1]); return true; else arrangements := [[gens[1],gens[2]]]; gs := gens{[3..Length(gens)]}; fi; k := 2; addgenerator := function(h) local newarrangement, a, left, right; k:=k+1; newarrangement := []; for a in arrangements do left := Concatenation([h],a); right := Concatenation(a,[h]); if (left[1]+left[3]) mod left[2] = 0 then Add(newarrangement, left); fi; if (right[k]+right[k-2]) mod right[k-1] = 0 then Add(newarrangement, right); fi; od; return newarrangement; end; for g in gs do arrangements := addgenerator(g); if arrangements = [] then return false; fi; od; # Print(arrangement,"\n"); arrangement := arrangements[1]; b1 := arrangement[1]; a1 := (arrangement[2])^-1 mod b1; b2 := arrangement[k]; a2 := (-arrangement[k-1])^-1 mod b2; SetClosedIntervalNS(S, [b1/a1,b2/a2]); SetProportionallyModularConditionNS(S, [a1*b2,b1*b2,a1*b2-a2*b1]); if b1*b2 = 1 then #the semigroup is the entire N SetMinimalGenerators(S,[1]); fi; if a1*b2-a2*b1 = 1 then SetModularConditionNS(S, [a1*b2,b1*b2]); fi; return true; end); ############################################################################# # this function has been replaced by the above one in version 0.971. ############################################################################# # InstallMethod(IsProportionallyModularNumericalSemigroup, # "Tests if a Numerical Semigroup is proportionally modular", # [IsNumericalSemigroup], # function( S ) # local pm, gens, bzs, gg, r, s, b1, a1, b2, a2; # # ############# local function ########## # # returns a Bezout sequence in case S is proportionally modular and false otherwise # pm:=function(bs,gs) #bs contains a bezout sequence, gs contains the set of generators not added to it # # local generators, a, b, first, inverse, bezoutseq, last; # # if gs=[] then # return bs; # fi; # # generators:=Set(ShallowCopy(gs)); # # if bs = [] then # a:=Minimum(generators); # RemoveSet(generators,a); # b:=Minimum(generators); # RemoveSet(generators,b); # if GcdInt(a,b) <> 1 then # return false; # fi; # return pm([[a,PowerMod(b,-1,a)], [b,b-PowerMod(a,-1,b)]], generators); # fi; # # # a:=Minimum(generators); # first:=bs[1]; # # inverse:=(1+a*first[2])/first[1]; # # if IsInt(inverse) then # RemoveSet(generators,a); # bezoutseq:=Concatenation([[a,inverse]],bs); # return pm(bezoutseq,generators); # fi; # # a:=Minimum(generators); # last:=bs[Length(bs)]; # # inverse:=(-1+a*last[2])/last[1]; # # if IsInt(inverse) then # RemoveSet(generators,a); # bezoutseq:=Concatenation(bs,[[a,inverse]]); # return pm(bezoutseq,generators); # fi; # # return false; # end; # ######### end of local function ######### # # gens := MinimalGeneratingSystemOfNumericalSemigroup(S); # if Length(gens) = 1 then # S!.closedinterval := [1,2]; # Setter(IsNumericalSemigroupByInterval)(S,true); # S!.proportionallymodularcondition := [1,1,1]; # Setter(IsProportionallyModularNumericalSemigroup)(S,true); # S!.modularcondition := [1,1]; # Setter(IsModularNumericalSemigroup)(S,true); # return true; # else # bzs := pm([],gens); # the test... # fi; # # if bzs = false then # return false; # else # gg := List(bzs, l -> l[1]/l[2]); # r := Minimum(gg); # s := Maximum(gg); # S!.closedinterval := [r,s]; # Setter(IsNumericalSemigroupByInterval)(S,true); # b1 := NumeratorRat(r); # a1 := DenominatorRat(r); # b2 := NumeratorRat(s); # a2 := DenominatorRat(s); # Setter(IsProportionallyModularNumericalSemigroup)(S,true); # S!.proportionallymodularcondition := [a1*b2,b1*b2,a1*b2-a2*b1]; # if b1*b2 = 1 then #the semigroup is the entire N # S!.minimalgenerators := [1]; # Setter(IsNumericalSemigroupByMinimalGenerators)(S,true); # fi; # if a1*b2-a2*b1 = 1 then # Setter(IsModularNumericalSemigroup)(S,true); # S!.modularcondition := [a1*b2,b1*b2]; # fi; # # return true; # fi; # end); # ############################################################################# ## #P IsModularNumericalSemigroup(S) ## ## Tests if a numerical semigroup is modular. ## ############################################################################# InstallMethod(IsModularNumericalSemigroup, "Tests if a Numerical Semigroup is modular", [IsNumericalSemigroup], function( S ) local lhs, gs, ms, b, A, a, C, c, Ac; if HasModularConditionNS(S) then return true; fi; lhs := Length(GapsOfNumericalSemigroup(S)); gs := FrobeniusNumberOfNumericalSemigroup(S); ms := MultiplicityOfNumericalSemigroup(S); #the least positive integer in S b := gs + ms; A := []; for a in [2..Int((b+1)/2)] do if b = 2*lhs + GcdInt(a,b) + GcdInt(a-1,b)-1 and ms < Minimum(b/GcdInt(a,b),b/GcdInt(a-1,b)) then Add(A,a); fi; od; for a in A do if Display(S) = Display(ModularNumericalSemigroup(a,b)) then SetModularConditionNS(S, [a,b]); SetProportionallyModularConditionNS(S, [a,b,1]); return(true); fi; od; C := []; for c in [2 * lhs +1 .. 12 * lhs -6] do if RemInt(c,ms) = 0 then Add(C,c); fi; od; for c in C do Ac := []; for a in [2..Int((c+1)/2)] do if c = 2*lhs + GcdInt(a,c) + GcdInt(a-1,c)-1 and ms = Minimum(c/GcdInt(a,c),c/GcdInt(a-1,c)) then Add(Ac,a); fi; od; for a in Ac do if Display(S) = Display(ModularNumericalSemigroup(a,c)) then SetModularConditionNS(S, [a,c]); SetProportionallyModularConditionNS(S, [a,c,1]); return(true); fi; od; od; return(false); end); InstallOtherMethod( One, "partial method for a Numerical Semigroup", true, [ IsMagmaWithOne and IsNumericalSemigroup ], 100, #T high priority? function( M ) return(0); end ); InstallMethod(MultiplicativeNeutralElement, "for a magma-with-one", true, [HasMultiplicativeNeutralElement and IsMagmaWithOne and IsNumericalSemigroup], GETTER_FLAGS+1, function(S) return(0); end); InstallMethod( Size, "for a collection", [ IsCollection and IsNumericalSemigroup ], function(S) return(infinity); return(Length(AsSSortedList(S))); end); ############################################################################ ## #M Methods for the comparison of numerical semigroups. ## InstallMethod( \=, "for two numerical semigroups", [IsNumericalSemigroup and IsNumericalSemigroupRep, IsNumericalSemigroup and IsNumericalSemigroupRep], function(x, y ) if Set(GeneratorsOfNumericalSemigroup(x)) = Set(GeneratorsOfNumericalSemigroup(y)) then return(true); elif HasMinimalGenerators(x) and HasMinimalGenerators(y) then return MinimalGenerators(x)=MinimalGenerators(y); elif HasModularConditionNS(x) and HasModularConditionNS(y) and ModularConditionNS(x) = ModularConditionNS(y) then return true; elif HasProportionallyModularConditionNS(x) and HasProportionallyModularConditionNS(y) and ProportionallyModularConditionNS(x) = ProportionallyModularConditionNS(y) then return true; elif HasAperyList(x) and HasAperyList(y) then return AperyList(x) = AperyList(y); elif HasGaps(x) and HasGaps(y) then return Gaps(x) = Gaps(y); elif HasFundamentalGaps(x) and HasFundamentalGaps(y) then return FundamentalGaps(x) = FundamentalGaps(y); elif HasSmallElements(x) and HasSmallElements(y) then return SmallElements(x) = SmallElements(y); else return SmallElementsOfNumericalSemigroup(x) = SmallElementsOfNumericalSemigroup(y); fi; end); InstallMethod( \<, "for two numerical semigroups", [IsNumericalSemigroup,IsNumericalSemigroup], function(x, y ) return(SmallElementsOfNumericalSemigroup(x) < SmallElementsOfNumericalSemigroup(y)); end );