# Lattices with isometry

We call *lattice with isometry* any pair $(L, f)$ consisting of an integer lattice $L$ together with an isometry $f \in O(L)$. We refer to the section about Integer Lattices of the documentation for new users.

In Oscar, such a pair is encoded in the type called `ZZLatWithIsom`

:

`ZZLatWithIsom`

— Type`ZZLatWithIsom`

A container type for pairs $(L, f)$ consisting of an integer lattice $L$ of type `ZZLat`

and an isometry $f$ given as a `QQMatrix`

representing the action on the basis matrix of $L$.

We store the ambient space $V$ of $L$ together with an isometry $f_a$ inducing $f$ on $L$ seen as a pair $(V, f_a)$ of type `QuadSpaceWithIsom`

. We moreover store the order $n$ of $f$, which can be finite or infinite.

To construct an object of type `ZZLatWithIsom`

, see the following examples:

**Examples**

One first way to construct such object, is by entering directly the lattice with an isometry. The isometry can be a honnest isometry of the lattice, or it can be an isometry of the ambient space preserving the lattice. Depending on this choice, one should enter the appropriate boolean value `ambient_representation`

. This direct construction is done through the constructors `integer_lattice_with_isometry`

.

```
julia> L = root_lattice(:E, 6);
julia> f = matrix(QQ, 6, 6, [ 1 2 3 2 1 1;
-1 -2 -2 -2 -1 -1;
0 1 0 0 0 0;
1 0 0 0 0 0;
-1 -1 -1 0 0 -1;
0 0 1 1 0 1]);
julia> Lf = integer_lattice_with_isometry(L, f, ambient_representation = false)
Integer lattice of rank 6 and degree 6
with isometry of finite order 8
given by
[ 1 2 3 2 1 1]
[-1 -2 -2 -2 -1 -1]
[ 0 1 0 0 0 0]
[ 1 0 0 0 0 0]
[-1 -1 -1 0 0 -1]
[ 0 0 1 1 0 1]
julia> B = matrix(QQ,1,6, [1 2 3 1 -1 3]);
julia> I = lattice_in_same_ambient_space(L, B); # This is the invariant sublattice L^f
julia> If = integer_lattice_with_isometry(I, ambient_isometry(Lf))
Integer lattice of rank 1 and degree 6
with isometry of finite order 1
given by
[1]
julia> integer_lattice_with_isometry(I, neg=true)
Integer lattice of rank 1 and degree 6
with isometry of finite order 2
given by
[-1]
```

Another way to construct such objects is to see them as sub-objects of their ambient space, of type `QuadSpaceWithIsom`

. Through the constructors `lattice`

and `lattice_in_same_ambient_space`

, one can then construct lattices with isometry for free, in a given space, as long as the module they define is preserved by the fixed isometry of the ambient space.

**Examples**

```
julia> G = matrix(QQ, 6, 6 , [ 3 1 -1 1 0 0;
1 3 1 1 1 1;
-1 1 3 0 0 1;
1 1 0 4 2 2;
0 1 0 2 4 2;
0 1 1 2 2 4]);
julia> V = quadratic_space(QQ, G);
julia> f = matrix(QQ, 6, 6, [ 1 0 0 0 0 0
0 0 -1 0 0 0
-1 1 -1 0 0 0
0 0 0 1 0 -1
0 0 0 0 0 -1
0 0 0 0 1 -1]);
julia> Vf = quadratic_space_with_isometry(V, f);
julia> Lf = lattice(Vf)
Integer lattice of rank 6 and degree 6
with isometry of finite order 3
given by
[ 1 0 0 0 0 0]
[ 0 0 -1 0 0 0]
[-1 1 -1 0 0 0]
[ 0 0 0 1 0 -1]
[ 0 0 0 0 0 -1]
[ 0 0 0 0 1 -1]
julia> B = matrix(QQ, 4, 6, [1 0 3 0 0 0;
0 1 1 0 0 0;
0 0 0 0 1 0;
0 0 0 0 0 1]);
julia> Cf = lattice(Vf, B) # coinvariant sublattice L_f
Integer lattice of rank 4 and degree 6
with isometry of finite order 3
given by
[-2 3 0 0]
[-1 1 0 0]
[ 0 0 0 -1]
[ 0 0 1 -1]
julia> Cf2 = lattice_in_same_ambient_space(Lf, B)
Integer lattice of rank 4 and degree 6
with isometry of finite order 3
given by
[-2 3 0 0]
[-1 1 0 0]
[ 0 0 0 -1]
[ 0 0 1 -1]
julia> Cf == Cf2
true
```

The last equality of the last example shows why we care about *ambient context*: the two pairs of lattice with isometry `Cf`

and `Cf2`

are basically the same mathematical objects. Indeed, they lie in the same space, defines the same module and their respective isometries are induced by the same isometry of the ambient space. As for regular `ZZLat`

, as soon as the lattices are in the same ambient space, we can compare them as $\mathbb Z$-modules, endowed with an isometry.

It is seen as a quadruple $(Vf, L, f, n)$ where $Vf = (V, f_a)$ consists of the ambient rational quadratic space $V$ of $L$, and an isometry $f_a$ of $V$ preserving $L$ and inducing $f$ on $L$. The integer $n$ is the order of $f$, which is a divisor of the order of the isometry $f_a\in O(V)$.

Given a lattice with isometry $(L, f)$, we provide the following accessors to the elements of the previously described quadruple:

`ambient_isometry`

— Methodambient_isometry(Lf::ZZLatWithIsom) -> QQMatrix

Given a lattice with isometry $(L, f)$, return an isometry of the ambient space of $L$ inducing $f$ on $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L; neg=true);
julia> ambient_isometry(Lf)
[-1 0 0 0 0]
[ 0 -1 0 0 0]
[ 0 0 -1 0 0]
[ 0 0 0 -1 0]
[ 0 0 0 0 -1]
```

`ambient_space`

— Method`ambient_space(Lf::ZZLatWithIsom) -> QuadSpaceWithIsom`

Given a lattice with isometry $(L, f)$, return the pair $(V, g)$ where $V$ is the ambient quadratic space of $L$ and $g$ is an isometry of $V$ inducing $f$ on $L$.

Note that $g$ might not be unique and we fix such a global isometry together with $V$ into a container type `QuadSpaceWithIsom`

.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L; neg=true);
julia> Vf = ambient_space(Lf)
Quadratic space of dimension 5
with isometry of finite order 2
given by
[-1 0 0 0 0]
[ 0 -1 0 0 0]
[ 0 0 -1 0 0]
[ 0 0 0 -1 0]
[ 0 0 0 0 -1]
julia> typeof(Vf)
QuadSpaceWithIsom
```

`isometry`

— Method`isometry(Lf::ZZLatWithIsom) -> QQMatrix`

Given a lattice with isometry $(L, f)$, return the underlying isometry $f$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L; neg=true);
julia> isometry(Lf)
[-1 0 0 0 0]
[ 0 -1 0 0 0]
[ 0 0 -1 0 0]
[ 0 0 0 -1 0]
[ 0 0 0 0 -1]
```

`lattice`

— Method`lattice(Lf::ZZLatWithIsom) -> ZZLat`

Given a lattice with isometry $(L, f)$, return the underlying lattice $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L; neg=true);
julia> lattice(Lf) === L
true
```

`order_of_isometry`

— Method`order_of_isometry(Lf::ZZLatWithIsom) -> IntExt`

Given a lattice with isometry $(L, f)$, return the order of the underlying isometry $f$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L; neg=true);
julia> order_of_isometry(Lf) == 2
true
```

Note that for some computations, it is more convenient to work either with the isometry of the lattice itself, or with the fixed isometry of the ambient quadratic space inducing it on the lattice.

## Constructors

We provide two ways to construct a pair $Lf = (L,f)$ consisting of an integer lattice endowed with an isometry. One way to construct an object of type `ZZLatWithIsom`

is through the methods `integer_lattice_with_isometry`

. These two methods do not require as input an ambient quadratic space with isometry.

`integer_lattice_with_isometry`

— Method```
integer_lattice_with_isometry(L::ZZLat, f::QQMatrix; check::Bool = true,
ambient_representation = true)
-> ZZLatWithIsom
```

Given a $\mathbb Z$-lattice $L$ and a matrix $f$, if $f$ defines an isometry of $L$ of order $n$, return the corresponding lattice with isometry pair $(L, f)$.

If `ambient_representation`

is set to `true`

, $f$ is consider as an isometry of the ambient space of $L$ and the induced isometry on $L$ is automatically computed as long as $f$ preserves $L$.

Otherwise, an isometry of the ambient space of $L$ is constructed, setting the identity on the complement of the rational span of $L$ if it is not of full rank.

**Examples**

The way we construct the lattice can have an influence on the isometry of the ambient space we store. Indeed, if one mentions an isometry of the lattice, this isometry will be extended by the identity on the orthogonal complement of the rational span of the lattice. In the following example, `Lf`

and `Lf2`

are the same object, but the isometry of their ambient space stored are different (one has order 2, the other one is the identity).

```
julia> B = matrix(QQ, 3, 5, [1 0 0 0 0;
0 0 1 0 1;
0 0 0 1 0]);
julia> G = matrix(QQ, 5, 5, [ 2 -1 0 0 0;
-1 2 -1 0 0;
0 -1 2 -1 0;
0 0 -1 2 -1;
0 0 0 -1 2]);
julia> L = integer_lattice(B; gram = G);
julia> f = matrix(QQ, 5, 5, [ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0]);
julia> Lf = integer_lattice_with_isometry(L, f)
Integer lattice of rank 3 and degree 5
with isometry of finite order 1
given by
[1 0 0]
[0 1 0]
[0 0 1]
julia> ambient_isometry(Lf)
[ 1 0 0 0 0]
[-1 -1 -1 -1 -1]
[ 0 0 0 0 1]
[ 0 0 0 1 0]
[ 0 0 1 0 0]
julia> Lf2 = integer_lattice_with_isometry(L, isometry(Lf); ambient_representation=false)
Integer lattice of rank 3 and degree 5
with isometry of finite order 1
given by
[1 0 0]
[0 1 0]
[0 0 1]
julia> ambient_isometry(Lf2)
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
```

`integer_lattice_with_isometry`

— Method`integer_lattice_with_isometry(L::ZZLat; neg::Bool = false) -> ZZLatWithIsom`

Given a $\mathbb Z$-lattice $L$ return the lattice with isometry pair $(L, f)$, where $f$ corresponds to the identity mapping of $L$.

If `neg`

is set to `true`

, then the isometry $f$ is negative the identity of $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L; neg=true)
Integer lattice of rank 5 and degree 5
with isometry of finite order 2
given by
[-1 0 0 0 0]
[ 0 -1 0 0 0]
[ 0 0 -1 0 0]
[ 0 0 0 -1 0]
[ 0 0 0 0 -1]
```

By default, the first constructor will always check whether the matrix defines an isometry of the lattice, or its ambient space. We recommend not to disable this parameter to avoid any further issues. Note that as in the case of quadratic spaces with isometry, both isometries of integer lattices of *finite order* and *infinite order* are supported.

Another way of constructing such lattices with isometry is by fixing an ambient quadratic space with isometry, of type `QuadSpaceWithIsom`

, and specifying a basis for an integral lattice in that space. If this lattice is preserved by the fixed isometry of the quadratic space considered, then we endow it with the induced action.

`lattice`

— Method`lattice(Vf::QuadSpaceWithIsom) -> ZZLatWithIsom`

Given a quadratic space with isometry $(V, f)$, return the full rank lattice $L$ in $V$ with basis the standard basis, together with the induced action of $f$ on $L$.

**Examples**

```
julia> V = quadratic_space(QQ, QQ[2 -1; -1 2])
Quadratic space of dimension 2
over rational field
with gram matrix
[ 2 -1]
[-1 2]
julia> f = matrix(QQ, 2, 2, [1 1; 0 -1])
[1 1]
[0 -1]
julia> Vf = quadratic_space_with_isometry(V, f)
Quadratic space of dimension 2
with isometry of finite order 2
given by
[1 1]
[0 -1]
julia> Lf = lattice(Vf)
Integer lattice of rank 2 and degree 2
with isometry of finite order 2
given by
[1 1]
[0 -1]
```

`lattice`

— Method```
lattice(Vf::QuadSpaceWithIsom, B::MatElem{<:RationalUnion};
isbasis::Bool = true, check::Bool = true)
-> ZZLatWithIsom
```

Given a quadratic space with isometry $(V, f)$ and a matrix $B$ generating a lattice $L$ in $V$, if $L$ is preserved under the action of $f$, return the lattice with isometry $(L, f_L)$ where $f_L$ is induced by the action of $f$ on $L$.

**Examples**

```
julia> V = quadratic_space(QQ, QQ[ 2 -1 0 0 0;
-1 2 -1 0 0;
0 -1 2 -1 0;
0 0 -1 2 -1;
0 0 0 -1 2]);
julia> f = matrix(QQ, 5, 5, [ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0]);
julia> Vf = quadratic_space_with_isometry(V, f);
julia> B = matrix(QQ,3,5,[1 0 0 0 0;
0 0 1 0 1;
0 0 0 1 0])
[1 0 0 0 0]
[0 0 1 0 1]
[0 0 0 1 0]
julia> lattice(Vf, B)
Integer lattice of rank 3 and degree 5
with isometry of finite order 1
given by
[1 0 0]
[0 1 0]
[0 0 1]
```

`lattice_in_same_ambient_space`

— Method```
lattice_in_same_ambient_space(L::ZZLatWithIsom, B::MatElem;
check::Bool = true)
-> ZZLatWithIsom
```

Given a lattice with isometry $(L, f)$ and a matrix $B$ whose rows define a free system of vectors in the ambient space $V$ of $L$, if the lattice $M$ in $V$ defined by $B$ is preserved under the fixed isometry $g$ of $V$ inducing $f$ on $L$, return the lattice with isometry pair $(M, f_M)$ where $f_M$ is induced by the action of $g$ on $M$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> B = matrix(QQ,3,5,[1 0 0 0 0;
0 0 1 0 1;
0 0 0 1 0])
[1 0 0 0 0]
[0 0 1 0 1]
[0 0 0 1 0]
julia> I = lattice_in_same_ambient_space(Lf, B)
Integer lattice of rank 3 and degree 5
with isometry of finite order 1
given by
[1 0 0]
[0 1 0]
[0 0 1]
julia> ambient_space(I) === ambient_space(Lf)
true
```

## Attributes and first operations

Given a lattice with isometry $Lf := (L, f)$, one can have access most of the attributes of $L$ and $f$ by calling the similar function for the pair. For instance, in order to know the genus of $L$, one can simply call `genus(Lf)`

. Here is a list of what are the current accessible attributes:

`basis_matrix`

— Method`basis_matrix(Lf::ZZLatWithIsom) -> QQMatrix`

Given a lattice with isometry $(L, f)$, return the basis matrix of the underlying lattice $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ,5,5,[ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0])
[ 1 0 0 0 0]
[-1 -1 -1 -1 -1]
[ 0 0 0 0 1]
[ 0 0 0 1 0]
[ 0 0 1 0 0]
julia> Lf = integer_lattice_with_isometry(L, f);
julia> I = invariant_lattice(Lf);
julia> basis_matrix(I)
[1 0 0 0 0]
[0 0 1 0 1]
[0 0 0 1 0]
```

`characteristic_polynomial`

— Method`characteristic_polynomial(Lf::ZZLatWithIsom) -> QQPolyRingElem`

Given a lattice with isometry $(L, f)$, return the characteristic polynomial of the underlying isometry $f$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L; neg=true);
julia> factor(characteristic_polynomial(Lf))
1 * (x + 1)^5
```

`degree`

— Method`degree(Lf::ZZLatWithIsom) -> Int`

Given a lattice with isometry $(L, f)$, return the degree of the underlying lattice $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> degree(Lf)
5
```

`det`

— Method`det(Lf::ZZLatWithIsom) -> QQFieldElem`

Given a lattice with isometry $(L, f)$, return the determinant of the underlying lattice $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> det(Lf)
6
```

`discriminant`

— Method`discriminant(Lf::ZZLatWithIsom) -> QQFieldElem`

Given a lattice with isometry $(L, f)$, return the discriminant of the underlying lattice $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> discriminant(Lf) == det(Lf) == 6
true
```

`genus`

— Method`genus(Lf::ZZLatWithIsom) -> ZZGenus`

Given a lattice with isometry $(L, f)$, return the genus of the underlying lattice $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L; neg=true);
julia> genus(Lf)
Genus symbol for integer lattices
Signatures: (5, 0, 0)
Local symbols:
Local genus symbol at 2: 1^-4 2^1_7
Local genus symbol at 3: 1^-4 3^1
```

`gram_matrix`

— Method`gram_matrix(Lf::ZZLatWithIsom) -> QQMatrix`

Given a lattice with isometry $(L, f)$, return the gram matrix of the underlying lattice $L$ with respect to its basis matrix.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> gram_matrix(Lf)
[ 2 -1 0 0 0]
[-1 2 -1 0 0]
[ 0 -1 2 -1 0]
[ 0 0 -1 2 -1]
[ 0 0 0 -1 2]
```

`is_definite`

— Method`is_definite(Lf::ZZLatWithIsom) -> Bool`

Given a lattice with isometry $(L, f)$, return whether the underlying lattice $L$ is definite.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> is_definite(Lf)
true
```

`is_even`

— Method`is_even(Lf::ZZLatWithIsom) -> Bool`

Given a lattice with isometry $(L, f)$, return whether the underlying lattice $L$ is even.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> is_even(Lf)
true
```

`is_elementary`

— Method`is_elementary(Lf::ZZLatWithIsom, p::IntegerUnion) -> Bool`

Given a lattice with isometry $(L, f)$ and a prime number $p$, return whether $L$ is $p$-elementary, that is whether its discriminant group is an elementary $p$-group.

**Examples**

```
julia> L = root_lattice(:E, 7);
julia> Lf = integer_lattice_with_isometry(L);
julia> is_elementary(Lf, 3)
false
julia> is_elementary(Lf, 2)
true
julia> genus(Lf)
Genus symbol for integer lattices
Signatures: (7, 0, 0)
Local symbol:
Local genus symbol at 2: 1^6 2^1_7
```

`is_elementary_with_prime`

— Method`is_elementary_with_prime(Lf::ZZLatWithIsom) -> Bool, ZZRingElem`

Given a lattice with isometry $(L, f)$, return whether $L$ is elementary, that is whether $L$ is integral and its discriminant group is an elemenentary $p$-group for some prime number $p$. In case it is, $p$ is also returned as second output.

Note that for unimodular lattices, this function returns `(true, 1)`

. If the lattice is not elementary, the second return value is `-1`

by default.

**Examples**

```
julia> L = root_lattice(:A, 7);
julia> Lf = integer_lattice_with_isometry(L);
julia> is_elementary_with_prime(Lf)
(false, -1)
julia> is_primary(Lf, 2)
true
julia> genus(Lf)
Genus symbol for integer lattices
Signatures: (7, 0, 0)
Local symbol:
Local genus symbol at 2: 1^6 8^1_7
```

`is_integral`

— Method`is_integral(Lf::ZZLatWithIsom) -> Bool`

Given a lattice with isometry $(L, f)$, return whether the underlying lattice $L$ is integral.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> is_integral(Lf)
true
```

`is_positive_definite`

— Method`is_positive_definite(Lf::ZZLatWithIsom) -> Bool`

Given a lattice with isometry $(L, f)$, return whether the underlying lattice $L$ is positive definite.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> is_positive_definite(Lf)
true
```

`is_primary`

— Method`is_primary(Lf::ZZLatWithIsom, p::IntegerUnion) -> Bool`

Given a lattice with isometry $(L, f)$ and a prime number $p$, return whether $L$ is $p$-primary, that is whether its discriminant group is a $p$-group.

**Examples**

```
julia> L = root_lattice(:A, 6);
julia> Lf = integer_lattice_with_isometry(L);
julia> is_primary(Lf, 7)
true
julia> genus(Lf)
Genus symbol for integer lattices
Signatures: (6, 0, 0)
Local symbols:
Local genus symbol at 2: 1^6
Local genus symbol at 7: 1^-5 7^-1
```

`is_primary_with_prime`

— Method`is_primary_with_prime(Lf::ZZLatWithIsom) -> Bool, ZZRingElem`

Given a lattice with isometry $(L, f)$, return whether $L$ is primary, that is whether $L$ is integral and its discriminant group is a $p$-group for some prime number $p$. In case it is, $p$ is also returned as second output.

Note that for unimodular lattices, this function returns `(true, 1)`

. If the lattice is not primary, the second return value is `-1`

by default.

**Examples**

```
julia> L = root_lattice(:A, 5);
julia> Lf = integer_lattice_with_isometry(L);
julia> is_primary_with_prime(Lf)
(false, -1)
julia> genus(Lf)
Genus symbol for integer lattices
Signatures: (5, 0, 0)
Local symbols:
Local genus symbol at 2: 1^-4 2^1_7
Local genus symbol at 3: 1^-4 3^1
```

`is_negative_definite`

— Method`is_negative_definite(Lf::ZZLatWithIsom) -> Bool`

Given a lattice with isometry $(L, f)$, return whether the underlying lattice $L$ is negative definite.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> is_negative_definite(Lf)
false
```

`is_unimodular`

— Method`is_unimodular(Lf::ZZLatWithIsom) -> Bool`

Given a lattice with isometry $(L, f)$, return whether `$L$ is unimodular, that is whether its discriminant group is trivial.

**Examples**

```
julia> L = root_lattice(:E, 8);
julia> Lf = integer_lattice_with_isometry(L);
julia> is_unimodular(Lf)
true
julia> genus(Lf)
Genus symbol for integer lattices
Signatures: (8, 0, 0)
Local symbol:
Local genus symbol at 2: 1^8
```

`minimum`

— Method`minimum(Lf::ZZLatWithIsom) -> QQFieldElem`

Given a positive definite lattice with isometry $(L, f)$, return the minimum of the underlying lattice $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> minimum(Lf)
2
```

`minimal_polynomial`

— Method`minimal_polynomial(Lf::ZZLatWithIsom) -> QQPolyRingElem`

Given a lattice with isometry $(L, f)$, return the minimal polynomial of the underlying isometry $f$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L; neg=true);
julia> minimal_polynomial(Lf)
x + 1
```

`norm`

— Method`norm(Lf::ZZLatWithIsom) -> QQFieldElem`

Given a lattice with isometry $(L, f)$, return the norm of the underlying lattice $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> norm(Lf)
2
```

`rank`

— Method`rank(Lf::ZZLatWithIsom) -> Integer`

Given a lattice with isometry $(L, f)$, return the rank of the underlying lattice $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L; neg=true);
julia> rank(Lf)
5
```

`rational_span`

— Method`rational_span(Lf::ZZLatWithIsom) -> QuadSpaceWithIsom`

Given a lattice with isometry $(L, f)$, return the rational span $L \otimes \mathbb{Q}$ of the underlying lattice $L$ together with the underlying isometry of $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> Vf = rational_span(Lf)
Quadratic space of dimension 5
with isometry of finite order 1
given by
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
julia> typeof(Vf)
QuadSpaceWithIsom
```

`scale`

— Method`scale(Lf::ZZLatWithIsom) -> QQFieldElem`

Given a lattice with isometry $(L, f)$, return the scale of the underlying lattice $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> scale(Lf)
1
```

`signature_tuple`

— Method`signature_tuple(Lf::ZZLatWithIsom) -> Tuple{Int, Int, Int}`

Given a lattice with isometry $(L, f)$, return the signature tuple of the underlying lattice $L$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> Lf = integer_lattice_with_isometry(L);
julia> signature_tuple(Lf)
(5, 0, 0)
```

Similarly, some basic operations on $\mathbb Z$-lattices and matrices are available for integer lattices with isometry.

`^`

— Method`^(Lf::ZZLatWithIsom, n::Int) -> ZZLatWithIsom`

Given a lattice with isometry $(L, f)$ and an integer $n$, return the pair $(L, f^n)$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0]);
julia> Lf = integer_lattice_with_isometry(L, f)
Integer lattice of rank 5 and degree 5
with isometry of finite order 2
given by
[ 1 0 0 0 0]
[-1 -1 -1 -1 -1]
[ 0 0 0 0 1]
[ 0 0 0 1 0]
[ 0 0 1 0 0]
julia> Lf^0
Integer lattice of rank 5 and degree 5
with isometry of finite order 1
given by
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
```

`biproduct`

— Method```
biproduct(x::Vector{ZZLatWithIsom}) -> ZZLatWithIsom,
Vector{AbstractSpaceMor},
Vector{AbstractSpaceMor}
biproduct(x::Vararg{ZZLatWithIsom}) -> ZZLatWithIsom,
Vector{AbstractSpaceMor},
Vector{AbstractSpaceMor}
```

Given a collection of lattices with isometries $(L_1, f_1), \ldots, (L_n, f_n)$, return the lattice with isometry $(L, f)$ together with the injections $L_i \to L$ and the projections $L \to L_i$, where $L$ is the biproduct $L := L_1 \oplus \ldots \oplus L_n$ and $f$ is the isometry of $L$ induced by the diagonal actions of the $f_i$'s.

For objects of type `ZZLatWithIsom`

, finite direct sums and finite direct products agree and they are therefore called biproducts. If one wants to obtain $(L, f)$ as a direct sum with the injections $L_i \to L$, one should call `direct_sum(x)`

. If one wants to obtain $(L, f)$ as a direct product with the projections $L \to L_i$, one should call `direct_product(x)`

.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0]);
julia> g = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f)
Integer lattice of rank 5 and degree 5
with isometry of finite order 2
given by
[ 1 0 0 0 0]
[-1 -1 -1 -1 -1]
[ 0 0 0 0 1]
[ 0 0 0 1 0]
[ 0 0 1 0 0]
julia> Lg = integer_lattice_with_isometry(L, g)
Integer lattice of rank 5 and degree 5
with isometry of finite order 5
given by
[1 1 1 1 1]
[0 -1 -1 -1 -1]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
julia> Lh, inj, proj = biproduct(Lf, Lg)
(Integer lattice with isometry of finite order 10, AbstractSpaceMor[Map: quadratic space -> quadratic space, Map: quadratic space -> quadratic space], AbstractSpaceMor[Map: quadratic space -> quadratic space, Map: quadratic space -> quadratic space])
julia> Lh
Integer lattice of rank 10 and degree 10
with isometry of finite order 10
given by
[ 1 0 0 0 0 0 0 0 0 0]
[-1 -1 -1 -1 -1 0 0 0 0 0]
[ 0 0 0 0 1 0 0 0 0 0]
[ 0 0 0 1 0 0 0 0 0 0]
[ 0 0 1 0 0 0 0 0 0 0]
[ 0 0 0 0 0 1 1 1 1 1]
[ 0 0 0 0 0 0 -1 -1 -1 -1]
[ 0 0 0 0 0 0 1 0 0 0]
[ 0 0 0 0 0 0 0 1 0 0]
[ 0 0 0 0 0 0 0 0 1 0]
julia> matrix(compose(inj[1], proj[1]))
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
julia> matrix(compose(inj[1], proj[2]))
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
```

`direct_product`

— Method```
direct_product(x::Vector{ZZLatWithIsom}) -> ZZLatWithIsom,
Vector{AbstractSpaceMor}
direct_product(x::Vararg{ZZLatWithIsom}) -> ZZLatWithIsom,
Vector{AbstractSpaceMor}
```

Given a collection of lattices with isometries $(L_1, f_1), \ldots, (L_n, f_n)$, return the lattice with isometry $(L, f)$ together with the projections $L \to L_i$, where $L$ is the direct product $L := L_1 \times \ldots \times L_n$ and $f$ is the isometry of $L$ induced by the diagonal actions of the $f_i$'s.

For objects of type `ZZLatWithIsom`

, finite direct sums and finite direct products agree and they are therefore called biproducts. If one wants to obtain $(L, f)$ as a direct sum with the injections $L_i \to L$, one should call `direct_sum(x)`

. If one wants to obtain $(L, f)$ as a biproduct with the injections $L_i \to L$ and the projections $L \to L_i$, one should call `biproduct(x)`

.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0]);
julia> g = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f)
Integer lattice of rank 5 and degree 5
with isometry of finite order 2
given by
[ 1 0 0 0 0]
[-1 -1 -1 -1 -1]
[ 0 0 0 0 1]
[ 0 0 0 1 0]
[ 0 0 1 0 0]
julia> Lg = integer_lattice_with_isometry(L, g)
Integer lattice of rank 5 and degree 5
with isometry of finite order 5
given by
[1 1 1 1 1]
[0 -1 -1 -1 -1]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
julia> Lh, proj = direct_product(Lf, Lg)
(Integer lattice with isometry of finite order 10, AbstractSpaceMor[Map: quadratic space -> quadratic space, Map: quadratic space -> quadratic space])
julia> Lh
Integer lattice of rank 10 and degree 10
with isometry of finite order 10
given by
[ 1 0 0 0 0 0 0 0 0 0]
[-1 -1 -1 -1 -1 0 0 0 0 0]
[ 0 0 0 0 1 0 0 0 0 0]
[ 0 0 0 1 0 0 0 0 0 0]
[ 0 0 1 0 0 0 0 0 0 0]
[ 0 0 0 0 0 1 1 1 1 1]
[ 0 0 0 0 0 0 -1 -1 -1 -1]
[ 0 0 0 0 0 0 1 0 0 0]
[ 0 0 0 0 0 0 0 1 0 0]
[ 0 0 0 0 0 0 0 0 1 0]
```

`direct_sum`

— Method```
direct_sum(x::Vector{ZZLatWithIsom}) -> ZZLatWithIsom,
Vector{AbstractSpaceMor}
direct_sum(x::Vararg{ZZLatWithIsom}) -> ZZLatWithIsom,
Vector{AbstractSpaceMor}
```

Given a collection of lattices with isometries $(L_1, f_1), \ldots, (L_n, f_n)$, return the lattice with isometry $(L, f)$ together with the injections $L_i \to L$, where $L$ is the direct sum $L := L_1 \oplus \ldots \oplus L_n$ and $f$ is the isometry of $L$ induced by the diagonal actions of the $f_i$'s.

For objects of type `ZZLatWithIsom`

, finite direct sums and finite direct products agree and they are therefore called biproducts. If one wants to obtain $(L, f)$ as a direct product with the projections $L \to L_i$, one should call `direct_product(x)`

. If one wants to obtain $(L, f)$ as a biproduct with the injections $L_i \to L$ and the projections $L \to L_i$, one should call `biproduct(x)`

.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0]);
julia> g = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f)
Integer lattice of rank 5 and degree 5
with isometry of finite order 2
given by
[ 1 0 0 0 0]
[-1 -1 -1 -1 -1]
[ 0 0 0 0 1]
[ 0 0 0 1 0]
[ 0 0 1 0 0]
julia> Lg = integer_lattice_with_isometry(L, g)
Integer lattice of rank 5 and degree 5
with isometry of finite order 5
given by
[1 1 1 1 1]
[0 -1 -1 -1 -1]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
julia> Lh, inj = direct_sum(Lf, Lg)
(Integer lattice with isometry of finite order 10, AbstractSpaceMor[Map: quadratic space -> quadratic space, Map: quadratic space -> quadratic space])
julia> Lh
Integer lattice of rank 10 and degree 10
with isometry of finite order 10
given by
[ 1 0 0 0 0 0 0 0 0 0]
[-1 -1 -1 -1 -1 0 0 0 0 0]
[ 0 0 0 0 1 0 0 0 0 0]
[ 0 0 0 1 0 0 0 0 0 0]
[ 0 0 1 0 0 0 0 0 0 0]
[ 0 0 0 0 0 1 1 1 1 1]
[ 0 0 0 0 0 0 -1 -1 -1 -1]
[ 0 0 0 0 0 0 1 0 0 0]
[ 0 0 0 0 0 0 0 1 0 0]
[ 0 0 0 0 0 0 0 0 1 0]
```

`dual`

— Method`dual(Lf::ZZLatWithIsom) -> ZZLatWithIsom`

Given a lattice with isometry $(L, f)$ inside the space $(V, \Phi)$, such that $f$ is induced by an isometry $g$ of $(V, \Phi)$, return the lattice with isometry $(L^{\vee}, h)$ where $L^{\vee}$ is the dual of $L$ in $(V, \Phi)$ and $h$ is induced by $g$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0]);
julia> Lf = integer_lattice_with_isometry(L, f)
Integer lattice of rank 5 and degree 5
with isometry of finite order 2
given by
[ 1 0 0 0 0]
[-1 -1 -1 -1 -1]
[ 0 0 0 0 1]
[ 0 0 0 1 0]
[ 0 0 1 0 0]
julia> Lfv = dual(Lf)
Integer lattice of rank 5 and degree 5
with isometry of finite order 2
given by
[1 -1 0 0 0]
[0 -1 0 0 0]
[0 -1 0 0 1]
[0 -1 0 1 0]
[0 -1 1 0 0]
julia> ambient_space(Lfv) == ambient_space(Lf)
true
```

`lll`

— Method`lll(Lf::ZZLatWithIsom) -> ZZLatWithIsom`

Given a lattice with isometry $(L, f)$, return the same lattice with isometry with a different basis matrix for $L$ obtained by performing an LLL-reduction on the associated gram matrix of $L$.

Note that matrix representing the action of $f$ on $L$ changes but the global action on the ambient space of $L$ stays the same.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0]);
julia> Lf = integer_lattice_with_isometry(L, f)
Integer lattice of rank 5 and degree 5
with isometry of finite order 2
given by
[ 1 0 0 0 0]
[-1 -1 -1 -1 -1]
[ 0 0 0 0 1]
[ 0 0 0 1 0]
[ 0 0 1 0 0]
julia> Lf2 = lll(Lf)
Integer lattice of rank 5 and degree 5
with isometry of finite order 2
given by
[ 1 0 0 0 0]
[-1 0 0 0 -1]
[-1 0 0 -1 0]
[-1 0 -1 0 0]
[-1 -1 0 0 0]
julia> ambient_space(Lf2) == ambient_space(Lf)
true
```

`orthogonal_submodule`

— Method`orthogonal_submodule(Lf::ZZLatWithIsom, B::QQMatrix) -> ZZLatWithIsom`

Given a lattice with isometry $(L, f)$ and a matrix $B$ with rational entries defining an $f$-stable sublattice of $L$, return the largest submodule of $L$ orthogonal to each row of $B$, equipped with the induced action from $f$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> B = matrix(QQ,3,5,[1 0 0 0 0;
0 0 1 0 1;
0 0 0 1 0])
[1 0 0 0 0]
[0 0 1 0 1]
[0 0 0 1 0]
julia> orthogonal_submodule(Lf, B)
Integer lattice of rank 2 and degree 5
with isometry of finite order 2
given by
[-1 0]
[ 0 -1]
```

`rescale`

— Method`rescale(Lf::ZZLatWithIsom, a::RationalUnion) -> ZZLatWithIsom`

Given a lattice with isometry $(L, f)$ and a rational number $a$, return the lattice with isometry $(L(a), f)$.

**Examples**

```
julia> L = root_lattice(:A,5)
Integer lattice of rank 5 and degree 5
with gram matrix
[ 2 -1 0 0 0]
[-1 2 -1 0 0]
[ 0 -1 2 -1 0]
[ 0 0 -1 2 -1]
[ 0 0 0 -1 2]
julia> f = matrix(QQ, 5, 5, [ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0]);
julia> Lf = integer_lattice_with_isometry(L, f)
Integer lattice of rank 5 and degree 5
with isometry of finite order 2
given by
[ 1 0 0 0 0]
[-1 -1 -1 -1 -1]
[ 0 0 0 0 1]
[ 0 0 0 1 0]
[ 0 0 1 0 0]
julia> Lf2 = rescale(Lf, 1//2)
Integer lattice of rank 5 and degree 5
with isometry of finite order 2
given by
[ 1 0 0 0 0]
[-1 -1 -1 -1 -1]
[ 0 0 0 0 1]
[ 0 0 0 1 0]
[ 0 0 1 0 0]
julia> lattice(Lf2)
Integer lattice of rank 5 and degree 5
with gram matrix
[ 1 -1//2 0 0 0]
[-1//2 1 -1//2 0 0]
[ 0 -1//2 1 -1//2 0]
[ 0 0 -1//2 1 -1//2]
[ 0 0 0 -1//2 1]
```

## Type for finite order isometries

Given a lattice with isometry $Lf := (L, f)$ where $f$ is of finite order $n$, one can compute the *type* of $Lf$.

`type`

— Method```
type(Lf::ZZLatWithIsom)
-> Dict{Int, Tuple{ <: Union{ZZGenus, HermGenus}, ZZGenus}}
```

Given a lattice with isometry $(L, f)$ with $f$ of finite order $n$, return the type of the pair $(L, f)$.

In this context, the type is defined as follows: for each divisor $k$ of $n$, the $k$-type of $(L, f)$ is the tuple $(H_k, A_K)$ consisting of the genus $H_k$ of the lattice $\ker(\Phi_k(f))$ viewed as a hermitian $\mathbb{Z}[\zeta_k]$- lattice (so a $\mathbb{Z}$-lattice for $k= 1, 2$) and of the genus $A_k$ of the $\mathbb{Z}$-lattice $\ker(f^k-1)$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> t = type(Lf);
julia> genus(invariant_lattice(Lf)) == t[1][1]
true
```

Since determining whether two pairs of lattices with isometry are isomorphic is a challenging task, one can perform a coarser comparison by looking at the type. This set of data keeps track of some local and global invariants of the pair $(L, f)$ with respect to the action of $f$ on $L$.

`is_of_type`

— Method`is_of_type(Lf::ZZLatWithIsom, t::Dict) -> Bool`

Given a lattice with isometry $(L, f)$, return whether $(L, f)$ is of type $t$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> t = type(Lf);
julia> is_of_type(Lf, t)
true
```

`is_of_same_type`

— Method`is_of_same_type(Lf::ZZLatWithIsom, Mg::ZZLatWithIsom) -> Bool`

Given two lattices with isometry $(L, f)$ and $(M, g)$, return whether they are of the same type.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> M = coinvariant_lattice(Lf);
julia> is_of_same_type(Lf, M)
false
```

Finally, if the minimal polynomial of $f$ is irreducible, then we say that the pair $(L, f)$ is of *hermitian type*. The type of a lattice with isometry of hermitian type is called *hermitian* (note that the type is only defined for finite order isometries).

These names follow from the fact that, by the trace equivalence, one can associate to the pair $(L, f)$ a hermitian lattice over the equation order of $f$, if it is maximal in the associated number field $\mathbb{Q}[f]$.

`is_of_hermitian_type`

— Method`is_of_hermitian_type(Lf::ZZLatWithIsom) -> Bool`

Given a lattice with isometry $(L, f)$, return whether the minimal polynomial of the underlying isometry $f$ is irreducible and the associated order is maximal.

Note that if $(L, f)$ is of hermitian type with $f$ of minimal polynomial $\chi$, then $L$ can be seen as a hermitian lattice over the order $\mathbb{Z}[\chi]$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f)
Integer lattice of rank 5 and degree 5
with isometry of finite order 5
given by
[1 1 1 1 1]
[0 -1 -1 -1 -1]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
julia> is_of_hermitian_type(Lf)
false
julia> is_of_hermitian_type(coinvariant_lattice(Lf))
true
```

`is_hermitian`

— Method`is_hermitian(t::Dict) -> Bool`

Given a type $t$ of lattices with isometry, return whether $t$ is hermitian, i.e. whether it defines the type of a hermitian lattice with isometry.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> M = coinvariant_lattice(Lf);
julia> is_hermitian(type(Lf))
false
julia> is_hermitian(type(M))
true
```

## Hermitian structures and trace equivalence

As mentioned in the previous section, to a lattice with isometry $Lf := (L, f)$ such that the minimal polynomial of $f$ is irreducible, one can associate a hermitian lattice $\mathfrak{L}$ over the equation order of $f$, if it is maximal, for which $Lf$ is the associated trace lattice. Hecke provides the tools to perform the trace equivalence for lattices with isometry of hermitian type.

`hermitian_structure`

— Method`hermitian_structure(Lf::ZZLatWithIsom) -> HermLat`

Given a lattice with isometry $(L, f)$ such that the minimal polynomial of the underlying isometry $f$ is irreducible, return the hermitian structure of the underlying lattice $L$ over the equation order of the minimal polynomial of $f$.

If it exists, the hermitian structure is stored. For now, we only cover the case where the equation order is maximal (which is always the case when the order is finite, for instance, since the minimal polynomial is cyclotomic).

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> M = coinvariant_lattice(Lf)
Integer lattice of rank 4 and degree 5
with isometry of finite order 5
given by
[-1 -1 -1 -1]
[ 1 0 0 0]
[ 0 1 0 0]
[ 0 0 1 0]
julia> H = hermitian_structure(M)
Hermitian lattice of rank 1 and degree 1
over relative maximal order of Relative number field of degree 2 over maximal real subfield of cyclotomic field of order 5
with pseudo-basis
(1, 1//1 * <1, 1>)
(z_5, 1//1 * <1, 1>)
julia> res = get_attribute(M, :transfer_data)
Map of change of scalars
from quadratic space of dimension 4
to hermitian space of dimension 1
julia> M2, f2 = trace_lattice_with_isometry(H, res)
(Integer lattice of rank 4 and degree 4, [-1 -1 -1 -1; 1 0 0 0; 0 1 0 0; 0 0 1 0])
julia> genus(M) == genus(M2) # One class in this genus, so they are isometric
true
julia> f2 == isometry(M)
true
```

## Discriminant groups

Given an integral lattice with isometry $Lf := (L, f)$, if one denotes by $D_L$ the discriminant group of $L$, there exists a natural map $\pi\colon O(L) \to O(D_L)$ sending any isometry to its induced action on the discriminant group of $L$. In general, this map is neither injective nor surjective. If we denote by $D_f := \pi(f)$ then $\pi$ induces a map between centralizers $O(L, f)\to O(D_L, D_f)$. Again, this induced map is in general neither injective nor surjective, and we denote its image by $G_{L,f}$.

`discriminant_group`

— Method`discriminant_group(Lf::ZZLatWithIsom) -> TorQuadModule, AutomorphismGroupElem`

Given an integral lattice with isometry $(L, f)$, return the discriminant group $D_L$ of the underlying lattice $L$ as well as the image $D_f$ of the underlying isometry $f$ inside $O(D_L)$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> qL, qf = discriminant_group(Lf)
(Finite quadratic module: Z/6 -> Q/2Z, [1])
julia> qL
Finite quadratic module
over integer ring
Abelian group: Z/6
Bilinear value module: Q/Z
Quadratic value module: Q/2Z
Gram matrix quadratic form:
[5//6]
julia> qf
Isometry of Finite quadratic module: Z/6 -> Q/2Z defined by
[1]
julia> f = matrix(QQ, 5, 5, [ 1 0 0 0 0;
-1 -1 -1 -1 -1;
0 0 0 0 1;
0 0 0 1 0;
0 0 1 0 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> discriminant_group(Lf)[2]
Isometry of Finite quadratic module: Z/6 -> Q/2Z defined by
[5]
```

For simple cases as for definite lattices, $f$ being plus-or-minus the identity or if the rank of $L$ is equal to the totient of the order of $f$ (in the finite case), $G_{L,f}$ can be easily computed. For the remaining cases, we use the hermitian version of *Miranda-Morrison theory* as presented in [BH23]. The general computation of $G_{L, f}$ has been implemented in this project and it can be indirectly used through the general following method:

`image_centralizer_in_Oq`

— Method```
image_centralizer_in_Oq(Lf::ZZLatWithIsom) -> AutomorphismGroup{TorQuadModule},
GAPGroupHomomorphism
```

Given an integral lattice with isometry $(L, f)$, return the image $G_L$ in $O(D_L, D_f)$ of the centralizer $O(L, f)$ of $f$ in $O(L)$. Here $D_L$ denotes the discriminant group of $L$ and $D_f$ is the isometry of $D_L$ induced by $f$.

**Examples**

```
julia> L = root_lattice(:A,2);
julia> f = matrix(QQ, 2, 2, [1 1; 0 -1]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> G, _ = image_centralizer_in_Oq(Lf)
(Group of isometries of Finite quadratic module: Z/3 -> Q/2Z generated by 2 elements, Hom: group of isometries of Finite quadratic module generated by 2 elements -> group of isometries of Finite quadratic module generated by 1 elements)
julia> order(G)
2
```

Note: hermitian Miranda-Morrison is only available for even lattices.

For an implementation of the regular Miranda-Morrison theory, we refer to the function `image_in_Oq`

which actually computes the image of $\pi$ in both the definite and the indefinite case.

More generally, for a finitely generated subgroup $G$ of $O(L)$, we have implemented a function which computes the representation of $G$ on $D_L$:

`discriminant_representation`

— Method```
discriminant_representation(L::ZZLat, G::MatrixGroup;
ambient_representation::Bool = true,
check::Bool = true) -> GAPGroupHomomorphism
```

Given an integer lattice $L$ and a group $G$ of isometries of $L$, return the orthogonal representation $G\to O(D_L)$ of $G$ on the discriminant group $D_L$ of $L$.

If `ambient_representation`

is set to `true`

, then the isometries in $G$ are considered as matrix representation of their action on the standard basis of the ambient space of $L$. Otherwise, they are considered as matrix representation of their action on the basis matrix of $L$.

We will see later in the section about enumeration of lattices with isometry that one can compute $G_{L,f}$ in some particular cases arising from equivariant primitive embeddings of lattices with isometries.

## Kernel sublattices

As for single integer lattices, it is possible to compute kernel sublattices of some $\mathbb{Z}$-module homomorphisms. We provide here the possibility to compute $\ker(p(f))$ as a sublattice of $L$ equipped with the induced action of $f$, where $p$ is a polynomial with rational coefficients.

`kernel_lattice`

— Method```
kernel_lattice(Lf::ZZLatWithIsom, p::Union{ZZPolyRingElem, QQPolyRingElem})
-> ZZLatWithIsom
```

Given a lattice with isometry $(L, f)$ and a polynomial $p$ with rational coefficients, return the sublattice $M := \ker(p(f))$ of the underlying lattice $L$ with isometry $f$, together with the restriction $f_{\mid M}$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> Zx,x = ZZ["x"]
(Univariate polynomial ring in x over ZZ, x)
julia> mf = minimal_polynomial(Lf)
x^5 - 1
julia> factor(mf)
1 * (x - 1) * (x^4 + x^3 + x^2 + x + 1)
julia> kernel_lattice(Lf, x-1)
Integer lattice of rank 1 and degree 5
with isometry of finite order 1
given by
[1]
julia> kernel_lattice(Lf, cyclotomic_polynomial(5))
Integer lattice of rank 4 and degree 5
with isometry of finite order 5
given by
[-1 -1 -1 -1]
[ 1 0 0 0]
[ 0 1 0 0]
[ 0 0 1 0]
```

`kernel_lattice`

— Method`kernel_lattice(Lf::ZZLatWithIsom, l::Integer) -> ZZLatWithIsom`

Given a lattice with isometry $(L, f)$ and an integer $l$, return the kernel lattice of $(L, f)$ associated to the $l-$th cyclotomic polynomial.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> kernel_lattice(Lf, 5)
Integer lattice of rank 4 and degree 5
with isometry of finite order 5
given by
[-1 -1 -1 -1]
[ 1 0 0 0]
[ 0 1 0 0]
[ 0 0 1 0]
julia> kernel_lattice(Lf, 1)
Integer lattice of rank 1 and degree 5
with isometry of finite order 1
given by
[1]
```

Note that such sublattices are by definition primitive in $L$ since $L$ is non-degenerate. As particular kernel sublattices of $L$, one can also compute the so-called *invariant* and *coinvariant* lattices of $(L, f)$:

`coinvariant_lattice`

— Method`coinvariant_lattice(Lf::ZZLatWithIsom) -> ZZLatWithIsom`

Given a lattice with isometry $(L, f)$, return the coinvariant lattice $L_f$ of $(L, f)$ together with the restriction of $f$ to $L_f$.

The coinvariant lattice $L_f$ of $(L, f)$ is the orthogonal complement in $L$ of the invariant lattice $L_f$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> coinvariant_lattice(Lf)
Integer lattice of rank 4 and degree 5
with isometry of finite order 5
given by
[-1 -1 -1 -1]
[ 1 0 0 0]
[ 0 1 0 0]
[ 0 0 1 0]
```

`invariant_lattice`

— Method`invariant_lattice(Lf::ZZLatWithIsom) -> ZZLatWithIsom`

Given a lattice with isometry $(L, f)$, return the invariant lattice $L^f$ of $(L, f)$ together with the restriction of $f$ to $L^f$ (which is the identity in this case).

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> invariant_lattice(Lf)
Integer lattice of rank 1 and degree 5
with isometry of finite order 1
given by
[1]
```

`invariant_coinvariant_pair`

— Method`invariant_coinvariant_pair(Lf::ZZLatWithIsom) -> ZZLatWithIsom, ZZLatWithIsom`

Given a lattice with isometry $(L, f)$, return the pair of lattices with isometries consisting of $(L^f, f_{\mid L^f})$ and $(L_f, f_{\mid L_f})$, the invariant and coinvariant sublattices with isometry of $(L, f)$.

Similarly, we provide the possibility to compute invariant and coinvariant sublattices given an orthogonal representation `G`

in matrix form of a finite group on a given lattice `L`

:

`coinvariant_lattice`

— Method```
coinvariant_lattice(L::ZZLat, G::MatrixGroup;
ambient_representation::Bool = true)
-> ZZLat, MatrixGroup
```

Given an integer lattice $L$ and a group $G$ of isometries of $L$, return the coinvariant sublattice $L_G$ of $L$, together with the subgroup $H$ of isometries of $L_G$ induced by the action of $G$.

If `ambient_representation`

is set to `true`

, the isometries in $G$ and $H$ are considered as matrix representation of their action on the standard basis of the ambient space of $L$. Otherwise, they are considered as matrix representation of their action on the basis matrices of $L$ and $L_G$ respectively.

**Examples**

```
julia> L = root_lattice(:A,2);
julia> G = isometry_group(L);
julia> L2, G2 = coinvariant_lattice(L, G)
(Integer lattice of rank 2 and degree 2, Matrix group of degree 2 over QQ)
julia> L == L2
true
julia> G == G2
true
```

`invariant_lattice`

— Method```
invariant_lattice(L::ZZLat, G::MatrixGroup;
ambient_representation::Bool = true) -> ZZLat
```

Given an integer lattice $L$ and a group $G$ of isometries of $L$ in matrix, return the invariant sublattice $L^G$ of $L$.

If `ambient_representation`

is set to `true`

, the isometries in $G$ are considered as matrix representation of their action on the standard basis of the ambient space of $L$. Otherwise, they are considered as matrix representation of their action on the basis matrix of $L$.

**Examples**

```
julia> L = root_lattice(:A,2);
julia> G = isometry_group(L);
julia> invariant_lattice(L, G)
Integer lattice of rank 0 and degree 2
with gram matrix
0 by 0 empty matrix
```

`invariant_coinvariant_pair`

— Method```
invariant_coinvariant_pair(L::ZZLat, G::MatrixGroup;
ambient_representation::Bool = true)
-> ZZLat, ZZLat, MatrixGroup
```

Given an integer lattice $L$ and a group $G$ of isometries of $L$, return the invariant sublattice $L^G$ of $L$ and its coinvariant sublattice $L_G$ together with the subgroup $H$ of isometries of $L_G$ induced by the action of $G$ on $L$.

If `ambient_representation`

is set to `true`

, the isometries in $G$ and $H$ are considered as matrix representation of their action on the standard basis of the ambient space of $L$. Otherwise, they are considered as matrix representation of their action on the basis matrices of $L$ and $L_G$ respectively.

**Examples**

```
julia> L = root_lattice(:A,2);
julia> G = isometry_group(L);
julia> Gsub, _ = sub(G, [gens(G)[end]]);
julia> F, C, G2 = invariant_coinvariant_pair(L, Gsub)
(Integer lattice of rank 1 and degree 2, Integer lattice of rank 1 and degree 2, Matrix group of degree 2 over QQ)
julia> F
Integer lattice of rank 1 and degree 2
with gram matrix
[2]
julia> C
Integer lattice of rank 1 and degree 2
with gram matrix
[6]
```

## Signatures

We conclude this introduction about standard functionalities for lattices with isometry by introducing a last invariant for lattices with finite isometry of hermitian type $(L, f)$, called the *signatures*. These signatures are intrinsically connected to the local archimedean invariants of the hermitian structure associated to $(L, f)$ via the trace equivalence.

`signatures`

— Method`signatures(Lf::ZZLatWithIsom) -> Dict{Int, Tuple{Int, Int}}`

Given a lattice with isometry $(L, f)$ where the minimal polynomial of $f$ is irreducible cyclotomic, return the signatures of the pair $(L, f)$.

In this context, if we denote $z$ a primitive $n$-th root of unity, where $n$ is the order of $f$, then for each $1 \leq i \leq n/2$ such that $(i, n) = 1$, the $i$-th signature of $(L, f)$ is given by the signatures of the real quadratic form $\ker(f + f^{-1} - z^i - z^{-i})$.

**Examples**

```
julia> L = root_lattice(:A,5);
julia> f = matrix(QQ, 5, 5, [1 1 1 1 1;
0 -1 -1 -1 -1;
0 1 0 0 0;
0 0 1 0 0;
0 0 0 1 0]);
julia> Lf = integer_lattice_with_isometry(L, f);
julia> M = coinvariant_lattice(Lf);
julia> signatures(M)
Dict{Integer, Tuple{Int64, Int64}} with 2 entries:
2 => (2, 0)
1 => (2, 0)
```

## Spinor norm

Given an integer lattice with isometry $(L, f)$, one often would like to know the *spinor norm* of $f$ seen as an isometry of the rational quadratic space $L\times \mathbb{Q}$. See `rational_spinor_norm(::QuadSpaceWithIsom)`

for a definition.

`rational_spinor_norm`

— Method`rational_spinor_norm(Lf::ZZLatWithIsom; b::Int = -1) -> QQFieldElem`

Given a lattice with isometry $(L, b, f)$, return the rational spinor norm of the extension of $f$ to $L\otimes \mathbb{Q}$.

If $\Phi$ is the form on $L\otimes \mathbb{Q}$, then the spinor norm is computed with respect to $b\Phi$.

## Equality

We choose as a convention that two pairs $(L, f)$ and $(L', f')$ of integer lattices with isometries are *equal* if their ambient quadratic space with isometry of type `QuadSpaceWithIsom`

are equal, and if the underlying lattices $L$ and $L'$ are equal as $\mathbb Z$-modules in the common ambient quadratic space.