Databases

Magma contains two databases of Hadamard matrices; the first database includes all inequivalent matrices of degree at most 28, and examples of matrices of all degrees up to 256. The representatives used are the canonical forms (as output by HadamardCanonicalForm), and matrices of a given degree are ordered lexicographically (with 1 considered to be less than -1 for the purposes of this ordering).

A database of skew-symmetric Hadamard matrices also exists; in this case the matrices are not stored in canonical form, since the canonical forms are not skew-symmetric. With the exception of the creation routines, the intrinsics below apply to both databases.

Contents

HadamardDatabase() : -> DB
Returns the database of Hadamard matrices.
SkewHadamardDatabase() : -> DB
Returns the database of skew-symmetric Hadamard matrices.
Matrix(D, n, k) : DB, RngIntElt, RngIntElt -> AlgMatElt
Returns the kth matrix of degree n in the database D.
Matrices(D, n) : DB, RngIntElt -> [ AlgMatElt ]
Returns the sequence of all matrices of degree n that are stored in the database D.
DegreeRange(D) : DB -> RngIntElt, RngIntElt
Returns the smallest and largest degrees of matrices in the database D.
Degrees(D) : DB -> [ RngIntElt ]
Returns the sequence of degrees for which there is at least one matrix of that degree in the database D.
NumberOfMatrices(D, n) : DB, RngIntElt -> RngIntElt
Return the number of matrices of degree n in the database D.

Example Hadamard_hadamard_db_eg (H157E3)

> D := HadamardDatabase();
> Matrix(D, 16, 3);
[ 1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1]
[ 1  1  1  1  1  1  1  1 -1 -1 -1 -1 -1 -1 -1 -1]
[ 1  1  1  1 -1 -1 -1 -1  1  1  1  1 -1 -1 -1 -1]
[ 1  1 -1 -1  1  1 -1 -1  1  1 -1 -1  1  1 -1 -1]
[ 1  1 -1 -1 -1  1  1 -1  1 -1 -1  1 -1 -1  1  1]
[ 1  1 -1 -1  1 -1 -1  1 -1  1  1 -1 -1 -1  1  1]
[ 1  1 -1 -1 -1 -1  1  1 -1 -1  1  1  1  1 -1 -1]
[ 1 -1 -1  1 -1 -1  1  1  1  1 -1 -1  1 -1 -1  1]
[ 1 -1 -1  1  1  1 -1 -1 -1 -1  1  1  1 -1 -1  1]
[ 1 -1  1 -1  1 -1  1 -1  1 -1  1 -1  1 -1  1 -1]
[ 1 -1  1 -1  1 -1 -1  1  1 -1 -1  1 -1  1 -1  1]
[ 1 -1  1 -1 -1  1  1 -1 -1  1  1 -1 -1  1 -1  1]
[ 1 -1  1 -1 -1  1 -1  1 -1  1 -1  1  1 -1  1 -1]
[ 1 -1 -1  1  1 -1  1 -1 -1  1 -1  1 -1  1  1 -1]
[ 1 -1 -1  1 -1  1 -1  1  1 -1  1 -1 -1  1  1 -1]
[ 1  1  1  1 -1 -1 -1 -1 -1 -1 -1 -1  1  1  1  1]
> NumberOfMatrices(D, 20);
3
> Degrees(D);
[ 1, 2, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72,
76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204,
208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256 ]
> [ NumberOfMatrices(D, n) : n in Degrees(D) ];
[ 1, 1, 1, 1, 1, 5, 3, 60, 487, 23, 218, 20, 500, 55, 562, 2, 3, 1, 2, 1, 2, 1,
3, 2, 1, 1, 1, 1, 2, 2, 1, 3, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]

Updating the Databases

The databases are noticeably incomplete (for example, it is known that more than 60 000 Hadamard matrices exist for degree 32 whereas only 23 are in the database; also, only matrices of degrees 36, 44, or 52 are present in the skew database). The Magma group welcomes contributions of matrices not equivalent to ones already present and will add them to future versions of the databases.

The functions in this section can be used to create new versions of the databases. This allows users to include matrices not already present without having to wait for new official versions of the databases. These functions use a record whose format is not described, as this record should only be manipulated by these functions.

HadamardDatabaseInformation(D : parameters) : DB -> Rec
    Canonical: BoolElt                  Default: true
This takes an existing Hadamard database and extracts the information in it to an internal form which will be used by the other intrinsics. This internal form is returned. The parameter Canonical indicates whether the entries in the database are known to be the canonical forms or not. It defaults to true, which is correct for the standard database; it should be set to false if working with the skew database or a user-created database where the entries are not canonical.

Note that the value of the Canonical parameter also controls whether the database created from this data should store the canonical forms or the original ones. If you want to extract the matrices from a canonical database but store them in a non-canonical one, you should create the non-canonical database first --- using either this intrinsic or HadamardDatabaseInformationEmpty --- with Canonical set to false and then add the matrices from the database with UpdateHadamardDatabase and Canonical set to true.

HadamardDatabaseInformationEmpty(: parameters) : -> Rec
    Canonical: BoolElt                  Default: true
Returns the internal data that would correspond to an empty database. The parameter Canonical is used to indicate whether the entries in the database should be written out in canonical form or not.

This allows the creation of a new database, or a slice of an existing one, without including the entirety of a previous one.

UpdateHadamardDatabase(~R, S : parameters) : Rec, SeqEnum ->
    Canonical: BoolElt                  Default: false
This augments the record R containing the database information with the matrices in the sequence S. The matrices are only added if they are inequivalent with matrices already there. Note that this requires finding the canonical forms, which can be expensive. If the matrices in S are known to be in canonical form already then the parameter Canonical should be set to true.

If the matrices of matching degree already in R are not known to be canonical then their canonical forms must also be computed. Again, this can take significant time. This is particularly troublesome for the skew database, where the canonical forms are not stored. For one way to deal with this, see the description of WriteRawHadamardData below.

WriteHadamardDatabase(S, ~R) : MonStgElt, Rec ->
This creates the database files name.dat and name.ind from the database data R, where name is taken from the string S. Since canonical forms may need to be computed during this process, the data is passed with a variable reference so that this computation is not lost. (For instance, if one writes out the database, then adds some more matrices and writes it out again.)
WriteRawHadamardData(S, R) : MonStgElt, Rec ->
This saves the data in R to the file whose name is given by the string S. When loaded, this file will define a single variable data which will behave identically to R. This is desirable for the non-canonical databases since the canonical forms will not have to be recomputed.

This routine destroys the original contents, if any, of the file.

SetVerbose("HadamardDB", v) : MonStgElt, RngIntElt ->
This procedure changes the verbose printing level for the Hadamard database update routines. The verbose value v should be an integer in the range 0 to 3. This can provide reassuring indications of progress when a long update process is underway.

Example Hadamard_hadamard_db_update (H157E4)

Here are some examples of how one might use these routines. We assume that the file matrixfile contains code that will define a sequence S of Hadamard matrices when loaded.
> D := HadamardDatabase();
> #D;
5391
> data := HadamardDatabaseInformation(D);
> SetVerbose("HadamardDB", 1);
> load "matrixfile";
> UpdateHadamardDatabase(~data, S);
3 new matrices added
> WriteHadamardDatabase("~/data/hadamard", ~data);
Sorting matrices by canonical forms
Sorting by degrees
Computing size information
Writing data file
Data file written (2007 matrices total)
Writing index file
Index file written
This has created the files hadamard.dat and hadamard.ind (in the directory ~{/data}) containing the updated data for the Hadamard database. The file stems should be hadamard for the standard database, or hadamard_skew for the database of skew-symmetric matrices; in this case we wanted the former. In order to use these files instead of the standard database, the library root must be changed. Database files are looked for in the data subdirectory of the library root, so in this example the library root should be changed to ~{} in order to get the newly created database.
> SetLibraryRoot("~");
> D := HadamardDatabase();
> #D;
2007
Of course, the library root is used by other databases, so it would be a good idea to set it back to its original value after creating the modified database. A better approach would be to encapsulate this process in a function (which could be put into the user startup file).
> function MyHadamardDatabase()
>     oldlibroot := GetLibraryRoot();
>     SetLibraryRoot("~");
>     D := HadamardDatabase();
>     SetLibraryRoot(oldlibroot);
>     return D;
> end function;
>
> D := MyHadamardDatabase();
> #D;
2007
If working with the database of skew-symmetric Hadamard matrices, it will probably be desirable to use the raw data instead, since the computation of the canonical forms takes a lot of time (about 23 minutes on a 750MHz machine). This does have to be done, but by using the raw forms it will only have to be done once, rather than each time.
> D := SkewHadamardDatabase();
> #D;
638
> data := HadamardDatabaseInformationEmpty(: Canonical := false);
> for n in Degrees(D) do
>     UpdateHadamardDatabase(~data, Matrices(D, n));
> end for;
> WriteRawHadamardData("skewraw.m", data);
Now that the raw data has been created, it can be used in other sessions to update the database (or the same session, of course).
> load "skewraw.m";
> load "matrixfile";
> UpdateHadamardDatabase(~data, S);
> WriteHadamardDatabase("~/data/hadamard_skew", ~data);
> WriteRawHadamardData("skewraw.m", data);
Note that the updated raw form is saved as well as the database. Now the new data can be accessed in the same way as the previous database was.
> SetLibraryRoot("~");
> D := SkewHadamardDatabase();
> #D;
641
As before, for maximum convenience access to the new database should also be put into a function in the startup file.
V2.28, 13 July 2023