<Chapter Label="CongruenceSubgroups">
<Heading>Construction of congruence subgroups</Heading>

<Index Key="IsCongruenceSubgroup"><C>IsCongruenceSubgroup</C></Index>
The package &Congruence; provides functions to construct several
types of canonical congruence subgroups in <M>SL_2(&ZZ;)</M>, and also 
intersections of a finite number of such subgroups. They will return 
a matrix group in the category <C>IsCongruenceSubgroup</C>,
which is defined as a subcategory of <C>IsMatrixGroup</C>, and
which will have a distinguishing property determining whether it is
a congruence subgroup of one of the canonical types, or an intersection
of such congruence subgroups (if it can not be reduced to one of the
canonical congruence subgroups).

To start to work with the package, you need first to load it as follows:

<Log>
<![CDATA[
gap> LoadPackage("congruence");
-----------------------------------------------------------------------------
Loading  Congruence 1.2.4 (Congruence subgroups of SL(2,Integers))
by Ann Dooms (http://homepages.vub.ac.be/~andooms),
   Eric Jespers (http://homepages.vub.ac.be/~efjesper),
   Olexandr Konovalov (https://alex-konovalov.github.io/), and
   Helena Verrill (http://www.math.lsu.edu/~verrill).
maintained by:
   Ann Dooms (http://homepages.vub.ac.be/~andooms),
   Olexandr Konovalov (https://alex-konovalov.github.io/), and
   Helena Verrill (http://www.math.lsu.edu/~verrill).
Homepage: https://gap-packages.github.io/congruence
Report issues at https://github.com/gap-packages/congruence/issues
-----------------------------------------------------------------------------
true
]]>
</Log>
 
<Section Label="CongConstr">
<Heading>Construction of congruence subgroups</Heading>
            
<ManSection>
  <Oper Name="PrincipalCongruenceSubgroup" 
         Arg="N"  
        Comm="" />
  <Description>
    Returns the principal congruence subgroup <M>\Gamma(N)</M> of level <A>N</A> 
    in <M>SL_2(&ZZ;)</M>.<P/>
    This subgroup consists of 
    all matrices of the form
<Alt Only="LaTeX">
  <![CDATA[
  \[
        \left( 
           \begin{array}{rr}
              1+N a & N b \\
              N c   & 1+N d
           \end{array} 
        \right)
  \]
  ]]>
</Alt>
<Alt Only="Text,HTML"><Verb><![CDATA[
                         [1+N*a    N*b]
                         [  N*c  1+N*d]
]]></Verb></Alt>   
where <M>a</M>,<M>b</M>,<M>c</M>,<M>d</M> are integers. 
       The returned group will have the property
    <Ref Prop="IsPrincipalCongruenceSubgroup" />.
  </Description>
</ManSection>       

<Example>
<![CDATA[
gap> G_8:=PrincipalCongruenceSubgroup(8);
<principal congruence subgroup of level 8 in SL_2(Z)>
gap> IsGroup(G_8);
true
gap> IsMatrixGroup(G_8);
true
gap> DimensionOfMatrixGroup(G_8);
2
gap> MultiplicativeNeutralElement(G_8);
[ [ 1, 0 ], [ 0, 1 ] ]
gap> One(G);
[ [ 1, 0 ], [ 0, 1 ] ]
gap> [[1,2],[3,4]] in G_8;
false
gap> [[1,8],[8,65]] in G_8;
true
gap> SL_2:=SL(2,Integers);
SL(2,Integers)
gap> IsSubgroup(SL_2,G_8);
true
]]>
</Example>


<ManSection>
  <Oper Name="CongruenceSubgroupGamma0" 
         Arg="N"  
        Comm="" />
  <Description>
    Returns the congruence subgroup <M>\Gamma_0(N)</M> 
    of level <A>N</A> in <M>SL_2(&ZZ;)</M>.<P/>
    This subgroup consists of 
    all matrices of the form
<Alt Only="LaTeX">
  <![CDATA[
  \[
        \left( 
           \begin{array}{rr}
              a & b \\
              N c   & d
           \end{array} 
        \right)
  \]
  ]]>
</Alt>
<Alt Only="Text,HTML"><Verb><![CDATA[
                         [a    b]
                         [N*c  d]
]]></Verb></Alt>   
where <M>a</M>,<M>b</M>,<M>c</M>,<M>d</M> are integers. 
         The returned group will have the property
    <Ref Prop="IsCongruenceSubgroupGamma0" />.   
  </Description>
</ManSection> 

<Example>
<![CDATA[
gap> G0_4:=CongruenceSubgroupGamma0(4);
<congruence subgroup CongruenceSubgroupGamma_0(4) in SL_2(Z)>
]]>
</Example>


<ManSection>
  <Oper Name="CongruenceSubgroupGammaUpper0" 
         Arg="N"  
        Comm="" />
  <Description>
    Returns the congruence subgroup <M>\Gamma^0(N)</M> 
    of level <A>N</A> in <M>SL_2(&ZZ;)</M>.<P/>
    This subgroup consists of 
    all matrices of the form
<Alt Only="LaTeX">
  <![CDATA[
  \[
        \left( 
           \begin{array}{rr}
              a & N b \\
              c   & d
           \end{array} 
        \right)
  \]
  ]]>
</Alt>
<Alt Only="Text,HTML"><Verb><![CDATA[
                         [a  N*b]
                         [c    d]
]]></Verb></Alt>   
where <M>a</M>,<M>b</M>,<M>c</M>,<M>d</M> are integers. 
             The returned group will have the property
    <Ref Prop="IsCongruenceSubgroupGammaUpper0" />. 
  </Description>
</ManSection>

<Example>
<![CDATA[
gap> GU0_2:=CongruenceSubgroupGammaUpper0(2);
<congruence subgroup CongruenceSubgroupGamma^0(2) in SL_2(Z)>
]]>
</Example>


<ManSection>
  <Oper Name="CongruenceSubgroupGamma1" 
         Arg="N"  
        Comm="" />
  <Description>
    Returns the congruence subgroup <M>\Gamma_1(N)</M> 
    of level <A>N</A> in <M>SL_2(&ZZ;)</M>.<P/>
         This subgroup consists of 
    all matrices of the form
<Alt Only="LaTeX">
  <![CDATA[
  \[
        \left( 
           \begin{array}{rr}
              1+N a & b \\
              N c   & 1+N d
           \end{array} 
        \right)
  \]
  ]]>
</Alt>
<Alt Only="Text,HTML"><Verb><![CDATA[
                         [1+N*a      b]
                         [  N*c  1+N*d]
]]></Verb></Alt>   
where <M>a</M>,<M>b</M>,<M>c</M>,<M>d</M> are integers. 
    The returned group will have the property
    <Ref Prop="IsCongruenceSubgroupGamma1" />.            
  </Description>
</ManSection> 

<Example>
<![CDATA[
gap> G1_6:=CongruenceSubgroupGamma1(6);
<congruence subgroup CongruenceSubgroupGamma_1(6) in SL_2(Z)>
]]>
</Example>


<ManSection>
  <Oper Name="CongruenceSubgroupGammaUpper1" 
         Arg="N"  
        Comm="" />
  <Description>
    Returns the congruence subgroup <M>\Gamma^1(N)</M> 
    of level <A>N</A> in <M>SL_2(&ZZ;)</M>.<P/>
         This subgroup consists of 
    all matrices of the form
<Alt Only="LaTeX">
  <![CDATA[
  \[
        \left( 
           \begin{array}{rr}
              1+N a & N b \\
               c   & 1+N d
           \end{array} 
        \right)
  \]
  ]]>
</Alt>
<Alt Only="Text,HTML"><Verb><![CDATA[
                         [1+N*a    N*b]
                         [    c  1+N*d]
]]></Verb></Alt>   
where <M>a</M>,<M>b</M>,<M>c</M>,<M>d</M> are integers. 
    The returned group will have the property
    <Ref Prop="IsCongruenceSubgroupGammaUpper1" />.               
  </Description>
</ManSection>

<Example>
<![CDATA[
gap> GU1_4:=CongruenceSubgroupGammaUpper1(4);
<congruence subgroup CongruenceSubgroupGamma^1(4) in SL_2(Z)>
]]>
</Example>


<ManSection>
  <Func Name="IntersectionOfCongruenceSubgroups" 
         Arg="G1, G2, ..., GN" />
  <Func Name="Intersection" 
         Arg="G1, G2, ..., GN" />         
  <Description>
    Returns the intersection of its arguments, which can be
    congruence subgroups or their intersections, constructed
    with the same function. It is not necessary for the user 
    to use <C>IntersectionOfCongruenceSubgroups</C>, since
    it will be called automatically from <C>Intersection</C>.<P/>
    
    The returned group will have the property
    <Ref Prop="IsIntersectionOfCongruenceSubgroups" />.<P/>
    
    The list of congruence subgroups that form the intersection
    can be obtained using <Ref Attr="DefiningCongruenceSubgroups"/>.
    
    Note, that when the intersection appears to be one of the 
    canonical congruence subgroups, the package will recognize 
    this and will return a canonical subgroup of the 
    appropriate type.
         
  </Description>
</ManSection>

<Example>
<![CDATA[
gap> I:=IntersectionOfCongruenceSubgroups(G0_4,GU1_4);
<principal congruence subgroup of level 4 in SL_2(Z)>
gap> J:=IntersectionOfCongruenceSubgroups(G0_4,G1_6);
<intersection of congruence subgroups of resulting level 12 in SL_2(Z)>
]]>
</Example>

</Section>

<!-- ********************************************************* -->

<Section Label="CongProperties">
<Heading>Properties of congruence subgroups</Heading>

A congruence subgroup constructed by one of the five above listed functions
will have certain properties determining its type. These properties will be
used for method selection by &Congruence; algorithms. Note that they do not
provide an actual test whether a certain matrix group is a congruence subgroup 
or not.

<ManSection>
  <Prop Name="IsPrincipalCongruenceSubgroup" 
         Arg="G"/>                            
  <Description>
    For a congruence subgroup <A>G</A> in the category 
    <C>IsCongruenceSubgroup</C>, returns <K>true</K> if <A>G</A> was
    constructed by <Ref Func="PrincipalCongruenceSubgroup" /> 
    (or reduced to one as a result of an intersection) and 
    returns <K>false</K> otherwise. 
  </Description>
</ManSection>

<Example>
<![CDATA[
gap> IsPrincipalCongruenceSubgroup(G_8);
true
gap> IsPrincipalCongruenceSubgroup(G0_4);
false
gap> IsPrincipalCongruenceSubgroup(I);
true
]]>
</Example>


<ManSection>
  <Prop Name="IsCongruenceSubgroupGamma0" 
         Arg="G"/>
  <Description>
    For a congruence subgroup <A>G</A> in the category 
    <C>IsCongruenceSubgroup</C>, returns <K>true</K> if 
    <A>G</A> was constructed by <Ref Func="CongruenceSubgroupGamma0" /> (or reduced to one as a result of an intersection)
    and returns <K>false</K> otherwise.  
  </Description>
</ManSection>


<ManSection>
  <Prop Name="IsCongruenceSubgroupGammaUpper0" 
         Arg="G"/>
  <Description>
    For a congruence subgroup <A>G</A> in the category 
    <C>IsCongruenceSubgroup</C>, returns <K>true</K> if 
    <A>G</A> was constructed by <Ref Func="CongruenceSubgroupGammaUpper0" /> (or reduced to one as a result of an intersection)
    and returns <K>false</K> otherwise.
  </Description>
</ManSection>


<ManSection>
  <Prop Name="IsCongruenceSubgroupGamma1" 
         Arg="G"/>
  <Description>
    For a congruence subgroup <A>G</A> in the category 
    <C>IsCongruenceSubgroup</C>, returns <K>true</K> if
    <A>G</A> was constructed by <Ref Func="CongruenceSubgroupGamma1" /> (or reduced to one as a result of an intersection)
    and returns <K>false</K> otherwise.
  </Description>
</ManSection>


<ManSection>
  <Prop Name="IsCongruenceSubgroupGammaUpper1" 
         Arg="G"/>                                    
  <Description>
    For a congruence subgroup <A>G</A> in the category 
    <C>IsCongruenceSubgroup</C>, returns <K>true</K> if 
    <A>G</A> was constructed by <Ref Func="CongruenceSubgroupGammaUpper1" /> (or reduced to one as a result of an intersection)
    and returns <K>false</K> otherwise.
  </Description>
</ManSection>


<ManSection>
  <Prop Name="IsIntersectionOfCongruenceSubgroups" 
         Arg="G"/>                                    
  <Description>
    For a congruence subgroup <A>G</A> in the category 
    <C>IsCongruenceSubgroup</C>, returns <K>true</K> if
    <A>G</A> was constructed by 
    <Ref Func="IntersectionOfCongruenceSubgroups"/> and
    without being one of the canonical congruence
    subgroups, otherwise it returns <K>false</K>.
  </Description>
</ManSection>

<Example>
<![CDATA[
gap> IsIntersectionOfCongruenceSubgroups(I);
false
gap> IsIntersectionOfCongruenceSubgroups(J);
true
]]>
</Example>

</Section>

<!-- ********************************************************* -->

<Section Label="CongAttributes">
<Heading>Attributes of congruence subgroups</Heading>

The next three attributes store key properties of congruence subgroups.

<ManSection>
  <Attr Name="LevelOfCongruenceSubgroup" 
         Arg="G"/>                                    
  <Description>
    Stores the level of the congruence subgroup <A>G</A>. The (arithmetic) level of a congruence subgroup G is the smallest positive
number N such that G contains the principal congruence subgroup of level N.
  </Description>
</ManSection>

<Example>
<![CDATA[
gap> LevelOfCongruenceSubgroup(G_8);
8
gap> LevelOfCongruenceSubgroup(G1_6);
6
gap> LevelOfCongruenceSubgroup(I);
4
gap> LevelOfCongruenceSubgroup(J);
12
]]>
</Example>


<ManSection>
  <Attr Name="IndexInSL2Z" 
         Arg="G"/>                                    
  <Description>
    Stores the index of the congruence subgroup <A>G</A> in <M>SL_2(&ZZ;)</M>.
  </Description>
</ManSection>

<Example>
<![CDATA[
gap> IndexInSL2Z(G_8);
384
gap> G_2:=PrincipalCongruenceSubgroup(2);
<principal congruence subgroup of level 2 in SL_2(Z)>
gap> IndexInSL2Z(G_2);
12
gap> IndexInSL2Z(GU1_4);
12
]]>
</Example>

<ManSection>
  <Attr Name="DefiningCongruenceSubgroups" 
         Arg="G" />
  <Returns>
    list of congruence subgroups
  </Returns>          
  <Description>
    For an intersection of congruence subgroups, returns 
    the list of congruence subgroups forming this intersection.
    For a canonical congruence subgroup returns a list of length
    one containing that subgroup.
  </Description>
</ManSection>

<Example>
<![CDATA[
gap> DefiningCongruenceSubgroups(J);
[ <congruence subgroup CongruenceSubgroupGamma_0(4) in SL_2(Z)>,
  <congruence subgroup CongruenceSubgroupGamma_1(6) in SL_2(Z)> ]
gap> P:=PrincipalCongruenceSubgroup(6);
<principal congruence subgroup of level 6 in SL_2(Z)>
gap> Q:=PrincipalCongruenceSubgroup(10); 
<principal congruence subgroup of level 10 in SL_2(Z)>
gap> G:=IntersectionOfCongruenceSubgroups(Q,P);  
<principal congruence subgroup of level 30 in SL_2(Z)>
gap> DefiningCongruenceSubgroups(G);
[ <principal congruence subgroup of level 30 in SL_2(Z)> ] 
]]>
</Example>

</Section>

<!-- ********************************************************* -->

<Section Label="CongMethods">
<Heading>Operations for congruence subgroups</Heading>

&Congruence; installs several special methods for operations already 
available in &GAP;.

<ManSection>
  <Oper Name="Random" 
       Label="one and two argument versions"
         Arg="G"/> 
  <Oper Name="Random" 
         Arg="G m"/>                                             
  <Description>
    For a congruence subgroup <A>G</A> in the category 
    <C>IsCongruenceSubgroup</C>, returns random element.
    In the two-argument form, the second parameter will
    control the absolute value of randomly selected 
    entries of the matrix.
  </Description>
</ManSection>

<Example>
<![CDATA[
gap> Random(G_2) in G_2;
true
gap> Random(G_8,2) in G_8;
true
]]>
</Example>


<ManSection>
  <Oper Name="\in" 
         Arg="m G"/> 
  <Description>
    It is easy to implement the membership test for
    congruence subgroups and their intersections.
  </Description>
</ManSection>

<Example>
<![CDATA[
gap> \in([ [ 21, 10 ], [ 2, 1 ] ],G_2);
true
gap> \in([ [ 21, 10 ], [ 2, 1 ] ],G_8);
false
]]>
</Example>


<ManSection>
  <Oper Name="CanEasilyCompareCongruenceSubgroups" 
         Arg="G H"/>                                    
  <Description>
  For congruence subgroups <A>G,H</A> in the category 
    <C>IsCongruenceSubgroup</C>, returns <K>true</K> if
    <A>G</A> and <A>H</A> are of the same type listed in
     <Ref Func="PrincipalCongruenceSubgroup" /> --> 
    <Ref Func="CongruenceSubgroupGammaUpper1" />
     and have the same
    <Ref Func="LevelOfCongruenceSubgroup"/> or if <A>G</A> and <A>H</A> 
    are of the type <Ref Func="IntersectionOfCongruenceSubgroups"/> and
    the groups from  
    <Ref Func="DefiningCongruenceSubgroups"/> are in one 
    to one correspondence, otherwise it returns <K>false</K>. 
  </Description>
</ManSection>


<Example>
<![CDATA[
gap> CanEasilyCompareCongruenceSubgroups(G_8,I);
false
]]>
</Example>

<ManSection>
  <Oper Name="IsSubset" 
         Arg="G H"/> 
  <Description>
    &Congruence; provides methods for <C>IsSubset</C>
    for congruence subgroups. <C>IsSubset</C> returns <K>true</K> 
    if <A>H</A> is a subset of <A>G</A>. These methods make it possible
    to use <C>IsSubgroup</C> operation for congruence subgroups.
  </Description>
</ManSection>


<Example>
<![CDATA[
gap> IsSubset(G_2,G_8);
true
gap> IsSubset(G_8,G_2);
false
gap> f:=[PrincipalCongruenceSubgroup,CongruenceSubgroupGamma1,CongruenceSubgroupGammaUpper1,CongruenceSubgroupGamma0,CongruenceSubgroupGammaUpper0];;
gap> g1:=List(f, t -> t(2));;
gap> g2:=List(f, t -> t(4));;
gap> for g in g2 do
> Print( List( g1, x -> IsSubgroup(x,g) ), "\n");
> od;
[ true, true, true, true, true ]
[ false, true, false, true, false ]
[ false, false, true, false, true ]
[ false, false, false, true, false ]
[ false, false, false, false, true ]
]]>
</Example>


<ManSection>
  <Oper Name="Index" 
         Arg="G H"/> 
  <Description>
    If a congruence subgroup <A>H</A> is a subgroup of a congruence 
    subgroup <A>G</A>, we can easily compute the index of <A>H</A> in
    <A>G</A>, since we know the index of both subgroups in <M>SL_2(&ZZ;)</M>.
  </Description>
</ManSection>

<Example>
<![CDATA[
gap> Index(G_2,G_8);
32
]]>
</Example>

</Section>
 
</Chapter>
