1#############################################################################
2##
3#W  operations.gi           Manuel Delgado <mdelgado@fc.up.pt>
4#W                          Pedro A. Garcia-Sanchez <pedro@ugr.es>
5#W                          Jose Morais <josejoao@fc.up.pt>
6##
7##
8#Y  Copyright 2005 by Manuel Delgado,
9#Y  Pedro Garcia-Sanchez and Jose Joao Morais
10#Y  We adopt the copyright regulations of GAP as detailed in the
11#Y  copyright notice in the GAP manual.
12##
13#############################################################################
14
15#############################################################################
16##
17#F  QuotientOfNumericalSemigroup(S,p)
18##
19##  Computes S/p, where S is a numerical semigroup
20##  and p a positive integer.
21##
22#############################################################################
23InstallGlobalFunction(QuotientOfNumericalSemigroup, function(S,p)
24    local   f,  T,  s,  R,  g,  l;
25
26    if not (IsNumericalSemigroup(S) and IsPosInt(p)) then
27        Error("QuotientOfNumericalSemigroup takes a numerical semigroup and a positive integer as arguments.");
28    fi;
29
30    f := FrobeniusNumberOfNumericalSemigroup(S);
31    T := [0];
32    if not p in GapsOfNumericalSemigroup(S) then
33        return NumericalSemigroup(1);
34    else
35        for s in [1..f+1] do
36            if BelongsToNumericalSemigroup(p * s,S) then
37                Add(T,s);
38            fi;
39        od;
40
41        R := Difference([1..T[Length(T)]],T);
42        g := R[Length(R)];
43        l := Intersection([0..g+1],Union(T, [g+1]));
44        return(NumericalSemigroupByGaps(Difference([0..l[Length(l)]], l)));
45    fi;
46end);
47
48
49#############################################################################
50##
51#M  S / p
52##
53##  A short for QuotientOfNumericalSemigroup(S, p)
54##
55#############################################################################
56InstallOtherMethod(\/, "for a numerical semigroup and a positive integer", true,
57        [IsNumericalSemigroup,
58         IsPosInt and IsMultiplicativeElement], 999999990,
59        function( S,p )
60    return(QuotientOfNumericalSemigroup(S, p));
61end);
62
63
64############################################################
65##
66#F MultipleOfNumericalSemigroup(s,a,b)
67## s is a numerical semigroup; a and b are positive integers
68## Computes a*s \cup [b,\infty)
69##
70############################################################
71InstallGlobalFunction(MultipleOfNumericalSemigroup,function(s,a,b)
72    local l, c;
73
74    if not(IsNumericalSemigroup(s)) then
75        Error("The first argument must be a numerical semigroup");
76    fi;
77    if not(IsPosInt(a)) then
78        Error("The second argument must be a positive ingteger");
79    fi;
80    if not(IsPosInt(b)) then
81        Error("The third argument must be a positive integer");
82    fi;
83
84    c:=ConductorOfNumericalSemigroup(s);
85    if b<a*c then
86        Info(InfoNumSgps,1,"The third argument is smaller than the second times the conductor of the first");
87    fi;
88
89    l:=[0..Int(b/a)];
90    l:=Union(a*Intersection(s,l), [b]);
91    return NumericalSemigroupBySmallElementsNC(l);
92end);
93
94#################################################################
95##
96#F InductiveNumericalSemigroup(a,b)
97## a and b are lists of positive integers with b[i+1]\ge a[i]b[i]
98## Computes inductively the semigroup
99## S_0=N
100## S_i=a_iS_{i-1}\cup \{a_ib_i,a_ib_i+1,->\}
101## and outputs S_n, with n the length of a and b
102##
103##################################################################
104InstallGlobalFunction(InductiveNumericalSemigroup,function(a,b)
105	local stmp, n, i;
106
107	stmp:=NumericalSemigroup(1);
108	if not(IsListOfIntegersNS(a)) or not(IsListOfIntegersNS(b)) then
109		Error("The arguments must be lists of positive integers");
110	fi;
111
112	if not(ForAll(Union(a,b), x-> x>0)) then
113		Error("The arguments must be lists of positive integers");
114	fi;
115
116	n:=Length(a);
117
118	if not(Length(b)=n) then
119		Error("Both arguments must have the same length");
120	fi;
121
122	if not(ForAll([1..n-1], i->b[i+1]>= a[i]*b[i])) then
123		Error("The condition b[i+1]>= a[i]*b[i] does not hold");
124	fi;
125	for i in [1..n] do
126		stmp:=MultipleOfNumericalSemigroup(stmp, a[i],a[i]*b[i]);
127	od;
128
129	return stmp;
130
131end);
132