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 basics.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. ## ############################################################################# ############################################################################# ## #A MultiplicityOfNumericalSemigroup(S) ## ## Returns the multiplicity of the numerical ## semigroup S. ## ############################################################################# InstallMethod(MultiplicityOfNumericalSemigroup, "Returns the multiplicity of a numerical semigroup", [IsNumericalSemigroup and HasGenerators],10, function(S) return GeneratorsOfNumericalSemigroup(S)[1]; end); InstallMethod(MultiplicityOfNumericalSemigroup, "Returns the multiplicity of a numerical semigroup", [IsNumericalSemigroup and HasAperyList],1, function(S) return Minimum(Difference(S!.aperylist,[0]),Length(S!.aperylist)); end); InstallMethod(MultiplicityOfNumericalSemigroup, "Returns the multiplicity of a modular numerical semigroup", [IsNumericalSemigroup and HasModularConditionNS], function(S) local a, b; a := ModularConditionNS(S)[1]; b := ModularConditionNS(S)[2]; return First([1..b], i-> a*i mod b <= i); end); InstallMethod(MultiplicityOfNumericalSemigroup, "Returns the multiplicity of a proportionally modular numerical semigroup", [IsNumericalSemigroup and HasProportionallyModularConditionNS], function(S) local a, b, c; a := ProportionallyModularConditionNS(S)[1]; b := ProportionallyModularConditionNS(S)[2]; c := ProportionallyModularConditionNS(S)[3]; return First([1..b], i-> a*i mod b <= c*i); end); # Agorithm in RosalesVasco2008MIA InstallMethod(MultiplicityOfNumericalSemigroup, "Returns the multiplicity of a numerical semigroup given by a closed interval", [IsNumericalSemigroup and HasClosedIntervalNS], function(S) local r, s, ListReducedIntervalsNC, P, list, j, i, n; r := ClosedIntervalNS(S)[1]; s := ClosedIntervalNS(S)[2]; ############# ## local function ListReducedIntervalsNC := function(r,s) local list, x, y, b1, a1, b2, a2; list := [[r,s]]; x := r; y := s; while not x <= Int(y) do b1 := NumeratorRat(x); a1 := DenominatorRat(x); b2 := NumeratorRat(y); a2 := DenominatorRat(y); # note that neither (b2 mod a2) nor (b1 mod a1) is zero x := a2/(b2 mod a2); y := a1/(b1 mod a1); Append(list, [[x,y]]); od; return list; end; # of local function P := []; list := ListReducedIntervalsNC(r,s); j := Length(list); P[j] := CeilingOfRational(list[j][1]); if j >1 then for i in [2..j] do n := j-i+2; P[n-1] := 1/P[n] + Int(list[n-1][1]); od; fi; return NumeratorRat(P[1]); end); InstallMethod(MultiplicityOfNumericalSemigroup, "Returns the multiplicity of a numerical semigroup", [IsNumericalSemigroup], function(S) if Length(SmallElementsOfNumericalSemigroup(S)) > 1 then return SmallElementsOfNumericalSemigroup(S)[2]; else return 1; fi; end); ############################################################################# ## #A FrobeniusNumber(S) #A FrobeniusNumberOfNumericalSemigroup(S) ## ## Returns the Frobenius number of the numerical ## semigroup S. ## ############################################################################# InstallMethod(FrobeniusNumberOfNumericalSemigroup, "Returns the Frobenius Number of the numerical sgp", [IsNumericalSemigroup and HasGaps],100, function(S) if Gaps(S) = [] then return -1; fi; return(Gaps(S)[Length(Gaps(S))]); end); InstallMethod(FrobeniusNumberOfNumericalSemigroup, "Returns the Frobenius Number of the numerical sgp", [IsNumericalSemigroup and HasSmallElements],99, function(S) return(SmallElements(S)[Length(SmallElements(S))] - 1); end); InstallMethod(FrobeniusNumberOfNumericalSemigroup, "Returns the Frobenius Number of the numerical sgp", [IsNumericalSemigroup and HasAperyList],50, function(S) return(Maximum(AperyList(S))-Length(AperyList(S))); end); ########## ## the generic method InstallMethod(FrobeniusNumberOfNumericalSemigroup, "Returns the Frobenius Number of the numerical sgp", [IsNumericalSemigroup], function(S) local set, len, min_mult_n3_in_n1n2, gens, n, C, gg, n1, n2, n3, c1, c2, c3, delta, d, gn, og, newgens; if not (HasMinimalGenerators(S) or HasGenerators(S)) then set := SmallElementsOfNumericalSemigroup(S); len := Length(set); return(set[len] - 1); fi; ## Local Functions ############################################################## ## Rosales&Vasco min_mult_n3_in_n1n2 := function(n1,n2,n3) local u, a, b, c, ns; if n1=n3 then return 1; fi; u := n2^-1 mod n1; #requires gcd(n1,n2)=1 a := (u*n2*n3) mod (n1*n2); b := n1*n2; c := n3; ns := NumericalSemigroupByInterval(b/a,b/(a-c)); return MultiplicityOfNumericalSemigroup(ns); end; ############################################################## gens := MinimalGeneratingSystemOfNumericalSemigroup(S); n := Length(gens); C := Combinations(gens,n-1); gg := First(C,c -> Gcd(c)<>1); ## for the case of three coprime generators we use an algorithms due to Rosales & Vasco if gg = fail then ## Rosales&Vasco if n = 3 then n1 := gens[1]; n2 := gens[2]; n3 := gens[3]; c1 := min_mult_n3_in_n1n2(n2,n3,n1); c2 := min_mult_n3_in_n1n2(n1,n3,n2); c3 := min_mult_n3_in_n1n2(n1,n2,n3); delta := RootInt((c1*n1+c2*n2+c3*n3)^2-4*(c1*n1*c2*n2+c1*n1*c3*n3+c2*n2*c3*n3-n1*n2*n3)); return ((c1-2)*n1+(c2-2)*n2+(c3-2)*n3+delta)/2; else set := SmallElementsOfNumericalSemigroup(S); len := Length(set); return(set[len] - 1); fi; fi; ## next we make use of Johnson's reduction d := Gcd(gg); gn := Difference(gens,gg); og := List(gg, i -> i/d); newgens := MinimalGeneratingSystemOfNumericalSemigroup(NumericalSemigroup(Union(og,gn))); if Length(newgens) = 2 then # Sylvester return d*(newgens[1]*newgens[2]-newgens[1]-newgens[2]) + (d-1)*gn[1]; elif Length(newgens) = 1 then return -d + (d-1)*gn[1]; else return d*FrobeniusNumberOfNumericalSemigroup(NumericalSemigroup(newgens)) + (d-1)*gn[1]; fi; end); #The algorithm used here was obtained by Rosales&Vasco InstallMethod(FrobeniusNumberOfNumericalSemigroup, "Returns the Frobenius Number of the numerical sgp", [IsNumericalSemigroup and IsModularNumericalSemigroup], function(S) local a, b, r, s, ns, m; a := ModularConditionNS(S)[1]; b := ModularConditionNS(S)[2]; if (a=1) or (b=1) then return -1; fi; r := (2*b^2+1)/(2*a*b); s := (2*b^2-1)/(2*b*(a-1)); ns := NumericalSemigroupByInterval(r,s); m := MultiplicityOfNumericalSemigroup(ns); return b - m; end); #The algorithm used here was obtained by Delgado&Rosales InstallMethod(FrobeniusNumberOfNumericalSemigroup, "Returns the Frobenius Number of the numerical sgp", [IsNumericalSemigroup and IsProportionallyModularNumericalSemigroup], function(S) local a, b, c, j; a := ProportionallyModularConditionNS(S)[1]; b := ProportionallyModularConditionNS(S)[2]; c := ProportionallyModularConditionNS(S)[3]; if a <= c then return -1; fi; a := a mod b; if a = 0 then return -1; fi; if a > (b+c)/2 then a := b+c-a; fi; j := CeilingOfRational(a-a/c-a/b+(2*a)/(c*b)); while ((j*b) mod a + Int((j*b)/a)*c <= (c-1)*b+a-c) do j := j+1; od; return b-Int((j*b)/a) -1; end); ############################################################################# ## #F ConductorOfNumericalSemigroup(S) ## ## Returns the conductor of the numerical semigroup S. ## ############################################################################# InstallMethod(Conductor, "Returns the conductor of a numerical semigroup", [IsNumericalSemigroup ], function( sgp ) if not IsNumericalSemigroup(sgp) then Error("The argument must be a numerical semigroup"); fi; return FrobeniusNumber(sgp)+1; end); ############################################################################# ## #A TypeOfNumericalSemigroup(S) ## ## Returns the type of the numerical semigroup S. ## ############################################################################# InstallMethod( TypeOfNumericalSemigroup, "Returns the type of a numerical sgp", [IsNumericalSemigroup], function( sgp ) return Length(PseudoFrobeniusOfNumericalSemigroup(sgp)); end); InstallMethod(Type, "Returns the type of a numerical sgp", [IsNumericalSemigroup], function( sgp ) return TypeOfNumericalSemigroup(sgp); end); ############################################################################# ## #A Generators(S) #A GeneratorsOfNumericalSemigroup(S) ## ## Returns a set of generators of the numerical ## semigroup S. If a minimal generating system has already been computed, this ## is the set returned. ## ############################################################################# InstallMethod( GeneratorsOfNumericalSemigroup, "Returns generators of a numerical sgp", [IsNumericalSemigroup], function(S) if not IsNumericalSemigroup(S) then Error("The argument must be a numerical semigroup"); fi; if HasMinimalGenerators(S) then return(MinimalGenerators(S)); elif HasGenerators(S) then return(Generators(S)); fi; return(MinimalGeneratingSystemOfNumericalSemigroup(S)); end); ############################################################################# ## #F GeneratorsOfNumericalSemigroupNC(S) ## ## Returns a set of generators of the numerical ## semigroup S. ## ############################################################################# # InstallGlobalFunction( GeneratorsOfNumericalSemigroupNC, function(S) # if not IsNumericalSemigroup(S) then # Error("The argument must be a numerical semigroup"); # fi; # if HasGenerators(S) then # return(Generators(S)); # fi; # return(MinimalGeneratingSystemOfNumericalSemigroup(S)); # end); ############################################################################# ## #A MinimalGeneratingSystem(S) #A MinimalGeneratingSystemOfNumericalSemigroup(S) ## ## Returns the minimal generating system of the numerical ## semigroup S. ## ############################################################################# InstallMethod( MinimalGeneratingSystemOfNumericalSemigroup, "method for a numerical semigroup", true, [IsNumericalSemigroup],0, function(S) local sumNS, Elm, c, m, max, T, mingen, generators, aux, i, g, gen, ss; ##################################################### # Let A and B be *sets* (not just lists) of positive elements of the numerical semigroup S # returns the elements of A+B not greater than max sumNS := function(A,B,max) local R, a, b; R := []; for a in A do for b in B do if a+b > max then break; else AddSet(R,a+b); fi; od; od; return R; end; ## if HasMinimalGenerators(S) then return MinimalGenerators(S); fi; ## if HasGeneratorsOfNumericalSemigroup(S) then generators := Generators(S); m := Minimum(generators); # the multiplicity if m = 1 then #the semigroup is the whole N SetMinimalGenerators(S, [1]); return MinimalGenerators(S); elif m = 2 then SetMinimalGenerators(S, [2,First(generators, g -> g mod 2 = 1)]); return MinimalGenerators(S); fi; # A naive reduction that takes into account that the minimal generators are incongruent modulo the multiplicity. This reduction is slow and proves only to be useful for small multiplicities. if m < LogInt(Length(generators),2)^4 then aux := [m]; for i in [1..m-1] do g := First(generators, g -> g mod m = i); if g <> fail then Append(aux,[g]); fi; od; gen := Set(aux); else gen := ShallowCopy(generators); fi; # now remove the generators that are not irreducible (i.e. may be written as the sum of others) ss := sumNS(gen,gen,Maximum(gen)); # non irreducible elements that are the sum of two generators while ss <> [] do gen := Difference(gen,ss); ss := sumNS(ss,gen,Maximum(gen));# non irreducible elements that are the sum of three, four, etc generators od; mingen := gen; # now gen is the set of irreducible elements SetMinimalGenerators(S,mingen); return mingen; fi; ## When nor a set of generators nor the small elements are known, the small elements are computed and the function is called again (now that the system has enlarged its knowledge on S) Elm := SmallElementsOfNumericalSemigroup(S); return MinimalGeneratingSystemOfNumericalSemigroup(NumericalSemigroup(Union(Elm,[Elm[Length(Elm)]..Elm[Length(Elm)]+Elm[2]-1]))); end); ############################################################################# ## #F MinimalGeneratingSystem(S) ## If S is a numerical semigroup, then this function just passes the task of computing the minimal generating system to MinimalGeneratingSystemOfNumericalSemigroup ## If S is an ideal of numerical semigroup, then this function just passes the task of computing the minimal generating system to MinimalGeneratingSystemOfIdealOfNumericalSemigroup ## # InstallGlobalFunction(MinimalGeneratingSystem, # function(S) # if IsNumericalSemigroup(S) then # return MinimalGeneratingSystemOfNumericalSemigroup(S); # elif IsIdealOfNumericalSemigroup(S) then # return MinimalGeneratingSystemOfIdealOfNumericalSemigroup(S); # else # Error("The argument must be a numerical semigroup or an ideal of a numerical semigroup."); # fi; # end); ############################################################################# ## #F ReducedSetOfGeneratorsOfNumericalSemigroup(arg) ## ## Returns a set with possibly fewer generators than those recorded in <C>S!.generators</C>. It changes <C>S!.generators</C> to the set returned. ##The function has 1 to 3 arguments. One of them a numerical semigroup. Then an argument is a boolean (<E>true</E> means that all the elements not belonging to the Apery set with respect to the multiplicity are removed; the default is "false") and another argument is a positive integer <M>n</M> (meaning that generators that can be written as the sum of <n> or less generators are removed; the default is "2"). The boolean or the integer may not be present. If a minimal generating set for <M>S</M> is known or no generating set is known, then the minimal generating system is returned. ## # InstallGlobalFunction( ReducedSetOfGeneratorsOfNumericalSemigroup, function(arg) # local sumNS, S, apery, n, generators, m, aux, i, g, gen, ss; # ##################################################### # # Computes the sum of subsets of numerical semigroups # # WARNING: the arguments have to be non empty sets, not just lists # sumNS := function(S,T) # local mm, s, t, R; # R := []; # mm := Maximum(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; # ## # S := First(arg, s -> IsNumericalSemigroup(s)); # if S = fail then # Error("Please check the arguments of ReducedSetOfGeneratorsOfNumericalSemigroup"); # fi; # apery := First(arg, s -> IsBool(s)); # if apery = fail then # apery := false; # fi; # n := First(arg, s -> IsInt(s)); # if n = fail then # n := 2; # fi; # if not IsBound(S!.generators) then # S!.generators := MinimalGeneratingSystemOfNumericalSemigroup(S); # return S!.generators; # else # if IsBound(S!.minimalgenerators) then # #S!.generators := MinimalGeneratingSystemOfNumericalSemigroup(S); # return S!.minimalgenerators; # fi; # generators := S!.generators; # m := Minimum(generators); # the multiplicity # if m = 1 then # S!.generators := [1]; # return S!.generators; # elif m = 2 then # S!.generators := [2,First(generators, g -> g mod 2 = 1)]; # return S!.generators; # fi; # if apery then # aux := [m]; # for i in [1..m-1] do # g := First(generators, g -> g mod m = i); # if g <> fail then # Append(aux,[g]); # fi; # od; # gen := Set(aux); # else # gen := ShallowCopy(generators); # fi; # ss := sumNS(gen,gen); # i := 1; # while i < n and ss <> [] do # gen := Difference(gen,ss); # ss := sumNS(gen,ss); # i := i+1; # od; # fi; # S!.generators := gen; # return S!.generators; # end); ## ############################################################################# ############################################################################# ## #A EmbeddingDimensionOfNumericalSemigroup(S) ## ## Returns the cardinality of the minimal generating system of the numerical ## semigroup S. ## ############################################################################# InstallMethod(EmbeddingDimensionOfNumericalSemigroup, "Returns the embedding dimension of a numerical semigroup", [IsNumericalSemigroup],10, function(sgp) return Length(MinimalGeneratingSystemOfNumericalSemigroup(sgp)); end); ############################################################################# ## #A FundamentalGapsOfNumericalSemigroup(S) ## ## Returns the fundamental gaps of the numerical ## semigroup S. ## ############################################################################# InstallMethod( FundamentalGapsOfNumericalSemigroup, "returns the list of fundamental gaps", true, [IsNumericalSemigroup], function(S) local g, h, fh; h := ShallowCopy(GapsOfNumericalSemigroup(S)); if HasFundamentalGaps(S) then return FundamentalGaps(S); fi; h := GapsOfNumericalSemigroup(S); fh := []; while h <> [] do g := h[Length(h)]; Add(fh,g); h := Difference(h,DivisorsInt(g)); od; fh := Set(fh); return fh; # SetFundamentalGaps(S, fh); # return FundamentalGaps(S); end); ############################################################################# ## #A PseudoFrobeniusOfNumericalSemigroup(S) ## ## Returns the pseudo Frobenius number of the numerical ## semigroup S. ## ############################################################################# InstallMethod( PseudoFrobeniusOfNumericalSemigroup, "returns a list of the pseudo Frobenius numbers of a numerical semigroup", true, [IsNumericalSemigroup], function(S) local hs, ehs, SE, S0, x; hs := GapsOfNumericalSemigroup(S); if hs = [] then # S is N return [-1]; fi; ehs := []; SE := SmallElementsOfNumericalSemigroup(S); S0 := SE{[2..Length(SE)]}; for x in hs do if ForAll(S0, s-> BelongsToNumericalSemigroup(x+s,S)) then Add(ehs, x); fi; od; return ehs; end); ############################################################################# ## #A SpecialGapsOfNumericalSemigroup(S) ## ## Returns the special gaps of the numerical ## semigroup S. ## ############################################################################# InstallMethod( SpecialGapsOfNumericalSemigroup, "returns the list of special gaps", true, [IsNumericalSemigroup], function(S) local PF, Y, y; PF := PseudoFrobeniusOfNumericalSemigroup(S); Y := []; for y in PF do if BelongsToNumericalSemigroup(2*y,S) then Add(Y,y); fi; od; return Y; end); ############################################################################# ## #O BelongsToNumericalSemigroup(n,S) ## ## Tests if the integer n belongs to the numerical ## semigroup S. ## ############################################################################# InstallMethod( \in, "for numerical semigroups", [ IsInt, IsNumericalSemigroup ], function( x, s ) return BelongsToNumericalSemigroup(x,s); end); InstallMethod( BelongsToNumericalSemigroup, "To test whether an integer belongs to a numerical semigroup", true, [IsInt,IsNumericalSemigroup and HasSmallElements],10, function(n,S) local s; if n=0 then return true; fi; s := SmallElements(S); return (n in s) or (n >= s[Length(s)]); end); InstallMethod( BelongsToNumericalSemigroup, "To test whether an integer belongs to a numerical semigroup", true, [IsInt,IsNumericalSemigroup and HasAperyList], function(n,S) local ap, m; if n=0 then return true; fi; ap := AperyList(S); m := Length(ap); if First([1..m], i-> (n mod m = i-1) and n >= ap[i]) <> fail then return true; else return false; fi; end); InstallMethod( BelongsToNumericalSemigroup, "To test whether an integer belongs to a numerical semigroup", true, [IsInt,IsNumericalSemigroup and HasFundamentalGaps], function(n,S) local f; if n=0 then return true; fi; f := FundamentalGaps(S); return First(f, i -> i mod n =0) = fail; end); InstallMethod( BelongsToNumericalSemigroup, "To test whether an integer belongs to a numerical semigroup", true, [IsInt,IsNumericalSemigroup and HasModularConditionNS], function(n,S) local a,b; if n=0 then return true; fi; a := ModularConditionNS(S)[1]; b := ModularConditionNS(S)[2]; return a*n mod b <= n; end); InstallMethod( BelongsToNumericalSemigroup, "To test whether an integer belongs to a numerical semigroup", true, [IsInt,IsNumericalSemigroup and HasProportionallyModularConditionNS],20, function(n,S) local a,b,c; if n=0 then return true; fi; a := ProportionallyModularConditionNS(S)[1]; b := ProportionallyModularConditionNS(S)[2]; c := ProportionallyModularConditionNS(S)[3]; return a*n mod b <= c*n; end); InstallMethod( BelongsToNumericalSemigroup, "To test whether an integer belongs to a numerical semigroup", true, [IsInt,IsNumericalSemigroup and HasGenerators], function(n,S) local gen, ss, sumNS, ed, belongs, maxgen, mingen; ##################################################### # Computes the sum of subsets of numerical semigroups sumNS := function(S,T) local mm, s, t, R; R := [S[1]+T[1]]; 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; if n=0 then return true; fi; if n in Generators(S) then return true; fi; if HasMinimalGenerators(S) then gen := MinimalGenerators(S); ed:=Length(gen); # some konwn bounds for Frobenius number can be used # Selmer's, Erdos-Graham, Schur if n>Minimum([2*gen[ed]*Int(gen[1]/ed)-gen[1], 2*gen[ed-1]*Int(gen[ed]/ed)-gen[ed], (gen[1]-1)*(gen[ed]-1)-1] ) then return true; fi; else gen := Generators(S); maxgen:=Maximum(gen); mingen:=Minimum(gen); # Schur's bound if n> (mingen-1)*(maxgen-1) then return true; fi; fi; ss := sumNS(gen,gen); if n in ss then return true; fi; if n < Minimum(ss) then return false; fi; ########################## # the desperate method belongs:=function(x,gen) if gen=[] then return false; fi; if x=0 then return true; fi; if x<0 then return false; fi; return belongs(x-gen[1],gen) or belongs(x,gen{[2..Length(gen)]}); end; return belongs(n,gen); #TryNextMethod(); end); InstallMethod( BelongsToNumericalSemigroup, "To test whether an integer belongs to a numerical semigroup", true, [IsInt,IsNumericalSemigroup], function(n,S) local m, ap; if n=0 then return true; fi; m := MultiplicityOfNumericalSemigroup(S); ap := AperyListOfNumericalSemigroupWRTElement(S,m); if First([1..m], i-> (n mod m = i-1) and n >= ap[i]) <> fail then return true; else return false; fi; end); ############################################################################# ## #O AperyListOfNumericalSemigroupWRTElement(S,n) ## ## Returns the Apery list of the numerical ## semigroup S with respect to n. ## ############################################################################# InstallMethod( AperyListOfNumericalSemigroupWRTElement, "returns the Apery list of a numerical semigroup with respect to a nonzero element of the semigroup", true, [IsNumericalSemigroup,IsInt], function(S,n) local Ap, f, max, i; # if IsBound(S!.aperylist) and Length(S!.aperylist) = n then # return S!.aperylist; # elif not BelongsToNumericalSemigroup(n,S) then if not BelongsToNumericalSemigroup(n,S) then Error("The second argument must be an element of the first argument in AperyListOfNumericalSemigroupWRTElement"); else Ap := [0]; f := FrobeniusNumberOfNumericalSemigroup(S); max := f + n; #see proposition 10.4 (book) for i in [1..n-1] do Add(Ap, First(Difference([1..max],GapsOfNumericalSemigroup(S)), j -> j mod n = i)); od; if n =MultiplicityOfNumericalSemigroup(S) then SetAperyList(S, Ap); # fi; fi; return ShallowCopy(Ap); end); ############################################################################# ## #A AperyList(S) #A AperyListOfNumericalSemigroup(S) ## ## Returns the Apery list of the numerical ## semigroup S with respect to the multiplicity. ## ############################################################################# InstallMethod( AperyList, "returns the Apery list of a numerical semigroup with respect to the multiplicity", true, [IsNumericalSemigroup], function(S) return(AperyListOfNumericalSemigroupWRTElement(S, MultiplicityOfNumericalSemigroup(S))); end); # Now another method for the case an integer is specified InstallOtherMethod( AperyList, "returns the Apery list of a numerical semigroup with respect to the multiplicity", true, [IsNumericalSemigroup, IsInt], function(S,n) if n in S then return(AperyListOfNumericalSemigroupWRTElement(S,n)); fi; return(AperyListOfNumericalSemigroupWRTInteger(S,n)); end); ############################################################################# ## #F AperyListOfNumericalSemigroupWRTInteger(S,n) ## ## Returns the Apery list of the numerical ## semigroup S with respect to the positive integer n. ## ############################################################################# InstallGlobalFunction( AperyListOfNumericalSemigroupWRTInteger, function(S,n) local Ap, f, max, i; if not(IsInt(n)) then Error("The second argument must be a positive integer"); fi; #if n<=0 then # Error("The second argument must be a positive integer"); #fi; if not(IsNumericalSemigroup(S)) then Error("The first argument must be a numerical semigroup"); fi; f := FrobeniusNumberOfNumericalSemigroup(S); max := f + n+1; #from this point on x-n is in S Ap:=Filtered(Difference([0..max],GapsOfNumericalSemigroup(S)), x -> not((x-n) in S)); return Ap; end); ############################################################################# ## #F AperyListOfNumericalSemigroupAsGraph(ap) ## ## <ap> is the Apery set of a numerical semigroup. ## This function returns the adjacency list of the graph ## whose vertices are ## the elements of <ap> and the arrow u -> v exists ## iff v - u is in <ap>. ## The 0 is ignored. ## ############################################################################# InstallGlobalFunction(AperyListOfNumericalSemigroupAsGraph, function(ap) local ap2, E, i, j, G, e; if not IsAperyListOfNumericalSemigroup(ap) then Error("The argument must be the Apery set of a numerical semigroup"); fi; # Compute the set of edges of the digraph ap2 := Set(ap); E := []; for i in ap do for j in ap do if j-i in ap2 then Add(E, [i,j]); fi; od; od; # Build the adjacency list G := []; for e in E do if not (e[1] = 0 or e[2] = 0) then if not IsBound(G[e[1]]) then G[e[1]] :=[]; fi; AddSet(G[e[1]], e[2]); fi; od; return G; end); ############################################################################# ## #F FirstElementsOfNumericalSemigroup(n,s) ## ## Prints the list of the first <n> elements of <s>. ## ############################################################################# InstallGlobalFunction(FirstElementsOfNumericalSemigroup, function(n,s) local se, l, max; if not IsNumericalSemigroup(s) then Error("The second argument must be a numerical semigroup."); fi; if n=0 then return []; fi; if not IsPosInt(n) then Error("The first argument must be a nonnegative integer."); fi; se:=SmallElementsOfNumericalSemigroup(s); l:=Length(se); if l>=n then return se{[1..n]}; fi; max:=se[l]; return Concatenation( se, [max+1..(max+n-l)]); end); ############################################################################# ## #F KunzCoordinatesOfNumericalSemigroup(arg) ## ## If two argumets are given, the first is a semigroup s and the second an ## element m in s. If one argument is given, then it is the semigroup, and ## m is set to the multiplicity. ## Then the Apéry set of m in s has the form [0,k_1m+1,...,k_{m-1}m+m-1], and ## the output is the (m-1)-uple [k_1,k_2,...,k_{m-1}] ############################################################################# InstallGlobalFunction(KunzCoordinatesOfNumericalSemigroup, function(arg) local narg,s,m,ap; narg:=Length(arg); if narg>2 then Error("The number of arguments is at most two"); fi; s:=arg[1]; if not(IsNumericalSemigroup(s)) then Error("The first argument must be a numerical semigroup"); fi; if narg=2 then m:=arg[2]; if not(m in s) then Error("The second argument must be an element of the first"); fi; if m=0 then Error("The second argument cannot be zero"); fi; else m:=MultiplicityOfNumericalSemigroup(s); fi; ap:=AperyListOfNumericalSemigroupWRTElement(s,m); return List([2..m],i->(ap[i]-i+1)/m); end); ############################################################################# ## #F KunzPolytope(m) ## For a fixed multiplicity, the Kunz coordinates of the semigroups ## with that multiplicity are solutions of a system of inequalities Ax\ge b ## (see [R-GS-GG-B]). The output is the matrix (A|-b) ## ############################################################################# InstallGlobalFunction(KunzPolytope, function(m) local mat,c, eq, row, it,zero; if not(IsPosInt(m)) then Error("The argument must be a positive integer"); fi; c:=Cartesian([1..m-1],[1..m-1]); eq:=IdentityMat(m-1); eq:=TransposedMat(Concatenation(eq,[List([1..m-1],_->-1)])); zero:=List([1..m],_->0); for it in c do row:=ShallowCopy(zero); row[it[1]]:=row[it[1]]+1; row[it[2]]:=row[it[2]]+1; if (it[1]+it[2])<m then row[it[1]+it[2]]:=-1; eq:=Concatenation(eq,[row]); fi; if (it[1]+it[2])>m then row[it[1]+it[2]-m]:=-1; row[m]:=1; eq:=Concatenation(eq,[row]); fi; od; return eq; end); ############################################################################# ## #A HolesOfNumericalSemigroup(s) ## For a numerical semigroup, finds the set of gaps x such that F(S)-x is ## is also a gap ## ############################################################################# InstallMethod(HolesOfNumericalSemigroup, "Returns the embedding dimension of a numerical semigroup", [IsNumericalSemigroup],10, function(s) local gs, f; gs:=GapsOfNumericalSemigroup(s); f:=FrobeniusNumber(s); return Filtered(gs, x-> not((f-x) in s)); end); ############################################################################# ## #F CocycleOfNumericalSemigroupWRTElement(S,n) ## ## Returns the cocycle of the numerical semigroup S with respect to ## the positive integer n (an element in S) ## ############################################################################# InstallGlobalFunction(CocycleOfNumericalSemigroupWRTElement,function(S,s) local i,j,b, ap; if not(IsNumericalSemigroup(S)) then Error("The first argument must be a numerical semigroup"); fi; if not(s in S)then Error("The second argument must be in the first"); fi; b:=IdentityMat(s); ap:=AperyListOfNumericalSemigroupWRTElement(S,s); for i in [0..s-1] do for j in [0..s-1] do b[i+1][j+1]:=(ap[i+1]+ap[j+1]-ap[(i+j) mod s + 1])/s; od; od; return b; end); ############################################################################# ## #O RthElementOfNumericalSemigroup(S,n) # Given a numerical semigroup S and an integer r, returns the r-th element of S ############################################################################# InstallMethod(RthElementOfNumericalSemigroup, [IsNumericalSemigroup,IsInt], function(S,r) local selts, n; selts := SmallElementsOfNumericalSemigroup( S ); n := Length(selts); if r <= Length(selts) then return selts[r]; else return selts[n] + r - n; fi; end); ######### InstallMethod(RthElementOfNumericalSemigroup, [IsInt,IsNumericalSemigroup], function(r,S) return(RthElementOfNumericalSemigroup(S,r)); end); ############################################################################# ## #O DivisorsOfElementInNumericalSemigroup(S,n) # Given a numerical semigroup S and an integer n, returns a list L of integers such that # x in L if and only if n - x belongs to S, that is, it returns S\cap(n-S) # These elements are called divisors of n ## ############################################################################# InstallMethod(DivisorsOfElementInNumericalSemigroup, [IsNumericalSemigroup,IsInt], function(S,n) local elts; #the first n elements of S not greater than n elts := FirstElementsOfNumericalSemigroup(n, S ); return(Intersection(n - elts,elts)); end); ######## InstallMethod(DivisorsOfElementInNumericalSemigroup, [IsInt,IsNumericalSemigroup], function(n,S) return(DivisorsOfElementInNumericalSemigroup(S,n)); end);