# Database of Lattices

Magma includes a database containing most of the lattices explicitly presented in the Catalogue of Lattices maintained by Neil J.A. Sloane and Gabriele Nebe [[Nebe and Sloane, 2001](../../references.md#cite-lattice-db)].

Many standard lattices included in the Sloane & Nebe catalogue are not in the database as they may be obtained by applying Magma’s standard lattice creation functions. Also omitted from the database are a small number of catalogued lattices defined over rings other than ${\mathbb{Z}}$ or ${\mathbb{Q}}$.

The information available for any given lattice in the catalogue varies considerably. A similar variety is found in the Magma database version, although some data (generally either easily computable or rarely available in the catalogue) is omitted.

Where the Magma database does retain data, it is not altered from the data in the catalogue. Thus the caveat which comes with that catalogue remains relevant: “Warning! Not all the entries have been checked!”

A second version of the Lattice Database has been made available with Version 2.16 of Magma. It adds a few more lattices, contains more information about automorphism groups, and adds $\Theta$-series as attributes. Furthermore, it removes some duplicates. The user should be warned that the numbering of lattices (and naming in some cases) differs between the two versions. The newer version, however, does not contain information about any Hermitian structure at the current time.

The entries of the database can be accessed in three ways:

**(i)**
the $i$-th entry of the database can be requested;

**(ii)**
the $i$-th entry of a particular dimension $d$ can be specified;

**(iii)**
the desired entry can be denoted by its name $N$. This name is specified exactly as in the catalogue, including all punctuation and whitespace. In the rare event that two or more entries share a single name, particular entries may be distinguished by supplying an integer $i$ in addition to $N$, to denote the $i$-th entry with name $N$.

## Creating the Database

### `LatticeDatabase() -> DB`

This function returns a database object which contains information about the database.

## Database Information

This section gives the functions that enable the user to find out what is in the database.

### `# D: DB -> RngIntElt`

### `NumberOfLattices(D): DB -> RngIntElt`

Returns the number of lattices stored in the database.

### `LargestDimension(D): DB -> RngIntElt`

Returns the largest dimension of any lattice in the database.

### `NumberOfLattices(D, d): DB, RngIntElt -> RngIntElt`

Returns the number of lattices of dimension $d$ stored in the database.

### `NumberOfLattices(D, N): DB, MonStgElt -> RngIntElt`

Returns the number of lattices named $N$ stored in the database. (This should always be 1 now).

### `LatticeName(D, i): DB, RngIntElt -> MonStgElt, RngIntElt`

Return the name and dimension of the $i$-th entry of the database $D$.

### `LatticeName(D, d, i): DB, RngIntElt, RngIntElt -> RecMonStgElt, RngIntElt`

Return the name and dimension of the $i$-th entry of dimension $d$ of the database $D$.

### `LatticeName(D, N): DB, MonStgElt -> RecMonStgElt, RngIntElt`

Return the name and dimension of the first entry of the database with name $N$.

### `LatticeName(D, N, i): DB, MonStgElt, RngIntElt -> RecMonStgElt, RngIntElt`

Return the name and dimension of the $i$-th entry of the database with name $N$.

### `Example: Latdb Names (ex-8a7900)`

We find out the names of the database entries.

```magma
> D := LatticeDatabase();
> NumberOfLattices(D);
699

```

The database contains 699 lattices. We get the set of all names in the database.

```magma
> names := {LatticeName(D,i): i in [1..#D]};
> #names; // No duplicate names anymore
699
> Random(names);
S4(5):2
> NumberOfLattices(D, "S4(5):2");
1

```

## Accessing the Database

The following functions retrieve lattice information from the database.

### `Lattice(D, i: parameters): DB, RngIntElt -> Lattice`

### `Lattice(D, d, i: parameters): DB, RngIntElt, RngIntElt -> Lattice`

### `Lattice(D, N: parameters): DB, MonStgElt -> Lattice`

### `Lattice(D, N, i: parameters): DB, MonStgElt, RngIntElt -> Lattice`

```magma
TrustAutomorphismGroup: Bool                    Default: true
```

Returns the $i$-th entry (of dimension $d$ or name $N$) from the database $D$ as a lattice $L$.

If the `TrustAutomorphismGroup` parameter is assigned `false`, then any data which claims to be the automorphism group will not be stored in $L$.

### `LatticeData(D, i): DB, RngIntElt -> Rec`

### `LatticeData(D, d, i): DB, RngIntElt, RngIntElt -> Rec`

### `LatticeData(D, N): DB, MonStgElt -> Rec`

### `LatticeData(D, N, i): DB, MonStgElt, RngIntElt -> Rec`

Returns a record which contains all the information about the $i$-th lattice stored in the database $D$ (of dimension $d$ or name $N$). The automorphism group is returned separately from the lattice and not stored in it.

### `Example: latdb (ex-7db624)`

We look up a lattice in the database. There are 19 lattices of dimension 6 in the database. We get the 10th.

```magma
> D := LatticeDatabase();
> NumberOfLattices(D, 6);
19
> L := Lattice(D, 6, 10);
> L;
Standard Lattice of rank 6 and degree 6
Minimum: 4
Inner Product Matrix:
[4 1 2 2 2 2]
[1 4 2 2 2 2]
[2 2 4 1 2 2]
[2 2 1 4 2 2]
[2 2 2 2 4 1]
[2 2 2 2 1 4]

```

There may be more information stored than just what is returned by the `Lattice` function. We get the record containing all the stored lattice data.

```magma
> R := LatticeData(D, 6, 10);
> Format(R);
recformat<name, dim, lattice, minimum, kissing_number,
is_integral, is_even, is_unimodular, is_unimodular_hermitian,
modularity, group_names, group, group_order,
hermitian_group_names, hermitian_group, hermitian_group_order,
hermitian_structure>

```

This lists all possible fields in the record. They may or may not be assigned for any particular lattice.

```magma
> R`lattice eq L;
true
> R`name;
A6,1
> assigned R`kissing_number;
true
> R`kissing_number;
42
> assigned R`group;
false
> A := AutomorphismGroup(L);
> A : Minimal;
MatrixGroup(6, Integer Ring) of order 96 = 2^5 * 3

```

The result of the `Lattice` call is equal to the `lattice` field of the data record. The kissing number was stored, but the automorphism group wasn’t. We computed the group (as a matrix group over the integers) and found it has order 96.

## Hermitian Lattices

There are a few facilities for computing with Hermitian lattices over an imaginary quadratic field or a quaternion algebra. However, these functions apply to a Gram matrix, and not a lattice *per se*. The main application is for automorphism groups that preserve a structure.

### `HermitianTranspose(M): Mtrx -> Mtrx`

### `QuaternionicTranspose(M): Mtrx -> Mtrx`

Given a matrix over an imaginary quadratic field or a quaternion algebra, return the conjugate transpose.

### `ExpandBasis(M): Mtrx -> Mtrx`

### `QuaternionicBasis(M): Mtrx -> Mtrx`

Given a matrix over an imaginary quadratic field or a quaternion algebra, expand it to a basis over the rationals.

### `HermitianAutomorphismGroup(M): Mtrx -> GrpMat`

### `QuaternionicAutomorphismGroup(M): Mtrx -> GrpMat`

Given a conjugate symmetric Gram matrix, compute the automorphism group.

Various functions for matrix groups over associative algebras are available here, such as `CharacterTable` and `IsConjugate` which simply use a re-writing over the rationals, and `InvariantForms` which after using `GHom` needs to restrict to elements fixed by the quaterionic structure. Finally, there is `QuaternionicGModule` which will split a $G$-module over a quaternionic structure.

### `InvariantForms(G): GrpMat -> SeqEnum`

Given a matrix group over an associative algebra or an imaginary quadratic field, return a basis for the forms fixed by it.

### `QuaternionicGModule(M, I, J): ModGrp, AlgMatElt, AlgMatElt -> ModGrp`

Given a $G$-module $M$ and $I$ and $J$ in the endomorphism algebra that anti-commute and whose squares are scalars, write $G$ over the quaternionic structure given by $I$ and $J$.

### `MooreDeterminant(M): Mtrx -> Mtrx`

Given a conjugate-symmetric matrix over a quaternion algebra, compute the Moore determinant. This is the “normal” determinant, which is well-defined here because all the diagonal elements are rational, and thus there is no ambiguity between left/right division.

### `Example: Coxeter Todd (ex-a41728)`

We construct the Coxeter-Todd lattice over $Q_{3,\infty}$ starting with the group $SU(3, 3)$.

```magma
> G := SU(3, 3);
> chi := CharacterTable(G)[2];
> M := GModule(chi,Integers());
> E := EndomorphismAlgebra (M);
> while true do
>     r := &+[Random([-2..2])*E.i : i in [1..4]];
>     if r^2 eq -1 then break; end if;
> end while;
> while true do
>     s := &+[Random([-2..2])*E.i : i in [1..4]];
>     if s^2 eq -3 and r*s eq -s*r then break; end if;
> end while;
> MM := QuaternionicGModule(M, r, s);
> Discriminant(BaseRing(MM));
3
> MG := MatrixGroup(MM);
> IF := InvariantForms(MG); IF;
[
    [1 -1/2*i + 1/6*k 1/3*k]
    [1/2*i - 1/6*k 1 -1/3*j]
    [-1/3*k 1/3*j 1]
]
> assert IsIsomorphic(G, MG);

```

### `Example: Quaternionic Auto Group (ex-723012)`

We compute the quaternionic automorphism group for the Leech lattice.

```magma
> A<i,j,k> := QuaternionAlgebra<Rationals()|-1,-1>;
> v := [];
> v[1] := [2+2*i,0,0,0,0,0]; /* from Wilson's paper */
> v[2] := [2,2,0,0,0,0];
> v[3] := [0,2,2,0,0,0];
> v[4] := [i+j+k,1,1,1,1,1];
> v[5] := [0,0,1+k,1+j,1+j,1+k];
> v[6] := [0,1+j,1+j,1+k,0,1+k];
> V := [Vector(x) : x in v];
> W := [Vector([Conjugate(x) : x in Eltseq(v)]): v in V];
> M6 := Matrix(6,6,[(V[i],W[j])/2 : i,j in [1..6]]); /* 6-dim over A */
> time Q := QuaternionicAutomorphismGroup(M6);
> assert #Q eq 503193600;

```

The same can be done for the Coxeter-Todd lattice.

```magma
> A<i,j,k> := QuaternionAlgebra<Rationals()|-1,-3>;
> a := (1+i+j+k)/2;
> M3 := Matrix(3,3,[2,a,-1, Conjugate(a),2,a, -1,Conjugate(a),2]);
> time Q := QuaternionicAutomorphismGroup(M3);
> assert #Q eq 12096;

```

One can also compute the automorphism group over the Eisenstein field, using `InvariantForms` on the realisation of this group as `ShephardTodd(34)`.

```magma
> G := ShephardTodd(34);
> IF := InvariantForms(G); // scaled Coxeter-Todd over Q(sqrt(-3))
> A := HermitianAutomorphismGroup(IF[1]);
> assert IsIsomorphic(A,G);

```
