The function in this section computes the genus of a lattice.
Genus(L) : Lat -> [ Lat ]
Depth: RngIntElt Default:
Given an integral lattice L, enumerate the genus of L by successively constructing p-neighbours and checking on isometry. This is done using the smallest prime p not dividing the determinant of L. In the case that L is odd with odd determinant and has an even neighbour L', the genus of L is obtained from the edges of the neighbouring graph of L'.Note that neighbours with respect to two vectors v_1, v_2 whose images in L/pL lie in the same orbit of ( Aut)(L) on L/pL are isometric. Therefore only orbit representatives of the action of ( Aut)(L) on L/pL are used. The computation of these orbits restricts the range of application of this function to cases where p^(( Rank)(L)) < 10^7.
By default, the system chooses the value for the Depth parameter for the calls to AutomorphismGroup and IsIsometric (see the section on automorphism group and isometry testing) which depends on the rank of L (( Min)( Floor((( Rank)(L) - 5)/2), 4 )). This can be overruled by setting Depth := d.
We use a combination of the automorphism group, isometry and neighbouring functions. The idea is that the neighbouring graph spans the full genus which therefore can be computed by successively generating neighbours and checking them for isometry with already known ones. The automorphism group comes into play, since neighbours with respect to vectors in the same orbit under the automorphism group are isometric.
> L := CoordinateLattice(Lattice("Kappa", 12));
> G := AutomorphismGroup(L);
> G2 := ChangeRing(G, GF(2));
> O := Orbits(G2);
> [ Norm(L!Rep(o)) : o in O ];
[ 0, 4, 8, 10 ]
Hence only the second and third orbit give rise to a neighbour. To obtain an
even neighbour, the second vector has to be adjusted by an element of 2 * L
such that it has norm divisible by 8.
> v1 := L ! Rep(O[2]);
> v1 +:= 2 * Rep({ b : b in Basis(L) | (v1,b) mod 2 eq 1 });
> v2 := L ! Rep(O[3]);
> Norm(v1), Norm(v2);
16 8
> L1 := Neighbour(L, v1, 2);
> L2 := Neighbour(L, v2, 2);
> bool := IsIsometric(L, L1); bool;
true
> bool := IsIsometric(L, L2); bool;
false
So we obtain only one non-isometric even neighbour of L. To obtain the full
genus we can now proceed with L2 in the same way, and do this with the
following function EvenGenus. Note that this function is simply one
part of the intrinsic function Genus.
> function EvenGenus(L)
> // Start with the lattice L
> Lambda := [ CoordinateLattice(LLL(L)) ];
> cand := 1;
> while cand le #Lambda do
> L := Lambda[cand];
> G := ChangeRing( AutomorphismGroup(L), GF(2) );
> // Get the orbits on L/2L
> O := Orbits(G);
> for o in O do
> v := L ! Rep(o);
> if not IsZero(v) and Norm(v) mod 4 eq 0 then
> // Adjust the vector such that its norm is divisible by 8
> if not Norm(v) mod 8 eq 0 then
> v +:= 2 * Rep({ b : b in Basis(L) | (v,b) mod 2 eq 1 });
> end if;
> N := LLL(Neighbour(L, v, 2));
> new := true;
> for i in [1..#Lambda] do
> if IsIsometric(Lambda[i], N) then
> new := false;
> break i;
> end if;
> end for;
> if new then
> Append( Lambda, CoordinateLattice(N));
> end if;
> end if;
> end for;
> cand +:= 1;
> end while;
> return Lambda;
> end function;
>
> time Lambda := EvenGenus(L);
Time: 14.359
> #Lambda;
10
> [ Minimum(L) : L in Lambda ];
[ 4, 2, 2, 2, 2, 2, 2, 2, 2, 2 ]
> &+[ 1/#AutomorphismGroup(L) : L in Lambda ];
4649359/4213820620800
We see that the genus consists of 10 classes of lattices where only the
Coxeter-Todd lattice has minimum 4 and get the mass of the genus as
4649359/4213820620800.