# Equivalence Testing

## `IsHadamard(H): AlgMatElt -> BoolElt`

Returns `true` if and only if the matrix $H$ is a Hadamard matrix.

## `HadamardNormalize(H): AlgMatElt -> AlgMatElt`

Given a Hadamard matrix $H$, returns a normalized matrix equivalent to $H$. This matrix is created by negating rows and columns to ensure that the first row and column consist entirely of ones.

## `HadamardCanonicalForm(H : parameters): AlgMatElt -> AlgMatElt, AlgMatElt, AlgMatElt`

```magma
Al: MonStgElt                    Default: "Traces"
```

Given a Hadamard matrix $H$, returns a Hadamard-equivalent matrix $H'$ and transformation matrices $X$ and $Y$ such that $H' = XHY$. The parameter `Al` may be set to `"nauty"` or `"Traces"` (the default). The matrix $H'$ is canonical in the sense that all matrices that are Hadamard-equivalent to $H$ (and no others) will produce the same matrix $H'$ with the given algorithm. Note that the canonical form produced by nauty may be different from that produced by Traces.

## `HadamardInvariant(H): AlgMatElt -> [ RngIntElt ]`

Returns a sequence $S$ of integers giving the $4$-profile of the Hadamard matrix $H$. All Hadamard-equivalent matrices have the same $4$-profile, but so may some inequivalent ones. Thus this test may determine inequivalence of two matrices more cheaply than performing a full equivalence test, but cannot establish equivalence.

## `IsHadamardEquivalent(H, J : parameters): AlgMatElt, AlgMatElt -> BoolElt, AlgMatElt, AlgMatElt`

```magma
Al: MonStgElt                    Default: "Traces"
```

Returns `true` if and only if the Hadamard matrices $H$ and $J$ are Hadamard equivalent. The parameter `Al` may be set to `"Leon"`, `"nauty"`, or `"Traces"` (the default). If the `"nauty"` or `"Traces"` options are chosen and the matrices are equivalent then transformation matrices $X$ and $Y$ are also returned, such that $J = XHY$.

## `HadamardMatrixToInteger(H): AlgMatElt -> RngIntElt`

Returns an integer that encodes the entries in the given Hadamard matrix in more compact form. The intended use is to save time when testing for equality against the same set of matrices many times.

## `HadamardMatrixFromInteger(x, n): RngIntElt, RngIntElt -> AlgMatElt`

Returns a Hadamard matrix of degree $n$ whose encoded form is the integer $x$. This function is the inverse of `HadamardMatrixToInteger()`.

## `Example: Hadamard Equiv (ex-709c48)`

We demonstrate the use of some of these functions on certain degree $16$ Hadamard matrices. For convenience, we create them from the more compact integer form.

```magma
> S := [
>   47758915483058652629300889924143904114798786457834842901517979108472281628672,
>   52517743516350345514775635367035460577743730272737765852723792818755052170805,
>   69809270372633075610047556428719374057869882804054059134346034969950931648512,
>   7209801227548712796135507135820555403251560090614832684136782016680445345792
> ];
> T := [ HadamardMatrixFromInteger(x, 16) : x in S ];
> &and [ IsHadamard(m) : m in T ];
true

```

Now we can test them for equivalence; we start by checking the $4$-profiles.

```magma
> [ HadamardInvariant(m) : m in T ];
[
    [ 1680, 0, 140 ],
    [ 1680, 0, 140 ],
    [ 1344, 448, 28 ],
    [ 1344, 448, 28 ]
]

```

We see that the only possible equivalencies are between the first two and the last two, since equivalent matrices must have the same $4$-profile.

```magma
> equiv,X,Y := IsHadamardEquivalent(T[1], T[2]);
> equiv;
true
> T[2] eq X*T[1]*Y;
true
> equiv,X,Y := IsHadamardEquivalent(T[3], T[4]);
> equiv;
false

```

So we have three inequivalent matrices. An alternative way to determine the inequivalent matrices would have been to use the canonical forms.

```magma
> #{ HadamardCanonicalForm(m) : m in T };
3

```
