Anymatrix is a MATLAB toolbox written by me and Mantas Mikaitis and released at version 1.0 in October 2021. The motivation for developing Anymatrix was that while MATLAB has many matrices built in (73, depending on what you count as a matrix), this set is necessarily limited in scope, yet at the same time it is hard to search within it for a matrix with a given property. Anymatrix overcomes these limitations in two ways.

First, it provides a large and growing collection of matrices organized into groups of related matrices, and it allows users to add further groups, making it extensible.

Second, it allows matrices to be annotated with properties, so that the whole collection can be searched for matrices with particular sets of properties. It includes groups `gallery`

and `matlab`

that access the matrices built into MATLAB and are annotated with properties.

Anymatrix is described in detail in a paper and a users’ guide. It is available from GitHub and MathWorks File Exchange.

## The Groups

The matrices built into Anymatrix are organized in seven groups.

`contest`

: the CONTEST toolbox of adjacency metrices from random network models (Taylor and D. J. Higham, 2009).`core`

: miscellaneous matrices.`gallery`

: matrices from the MATLAB gallery.`hadamard`

: a large collection of Hadamard matrices (mostly from a collection of Sloane) and complex Hadamard matrices.`matlab`

: other MATLAB matrices (not in gallery).`nessie`

: matrices from real-life networks (Taylor and D. J. Higham, 2009).`regtools`

: matrices from regularization problems (Hansen, 2007).

Every matrix has a unique identifier `group_name/matrix_name`

, where `matrix_name`

is the name of the function that implements the matrix.

In the rest of this post we introduce the toolbox through a few examples.

## Positive Definite Integer Matrices

We first find what symmetric positive definite matrices with integer entries are available.

>> anymatrix('properties','integer and positive definite') ans = 7×1 cell array {'core/beta' } {'core/wilson' } {'gallery/gcdmat'} {'gallery/minij' } {'gallery/moler' } {'gallery/pei' } {'matlab/pascal' }

Three of the seven groups built into Anymatrix—`core`

, `gallery`

, and `matlab`

—contain such matrices. We check the properties of the `core/beta`

matrix. Here, `'p'`

is short for `'properties'`

.

>> anymatrix('core/beta','p') ans = 12×1 cell array {'built-in' } {'infinitely divisible'} {'integer' } {'nonnegative' } {'positive' } {'positive definite' } {'real' } {'scalable' } {'square' } {'symmetric' } {'totally nonnegative' } {'totally positive' }

Infinitely divisibility of a symmetric positive semidefinite is the property that is positive semidefinite for all , where is the Hadamard power. We verify this property for and by checking that the eigenvalues are nonnegative:

>> A = anymatrix('core/beta',4) A = 1 2 3 4 2 6 12 20 3 12 30 60 4 20 60 140 > eig(A.^(1/10)) ans = 3.9036e-05 3.1806e-03 1.4173e-01 5.0955e+00

## Search Specific Groups

The search on properties returns results across all the groups. If we want to restrict to a particular group we can use the `contains`

command (one of the powerful MATLAB string-handling functions) to narrow the results. In the next example we find all the Hankel matrices built into MATLAB, that is, contained in the `gallery`

and `matlab`

groups.

>> m = anymatrix('p','hankel') m = 5×1 cell array {'core/dembo9' } {'gallery/ipjfact'} {'gallery/ris' } {'matlab/hankel' } {'regtools/ursell'} >> m = m(contains(m,{'gallery','matlab'})) m = 3×1 cell array {'gallery/ipjfact'} {'gallery/ris' } {'matlab/hankel' }

## Run a Test Over All Matrices

Anymatrix makes it possible to run tests over all or a subset of the matrices in the collection. This is not easy to do with the MATLAB gallery. The following code computes the minimum of the ratio over all the matrices, with default input arguments and size if the dimension is variable. This ratio is known to lie between and . We note several features of the code.

- By checking the
`built-in`

property, we only include matrices from the built-in groups (as opposed to any remote groups that have been downloaded). - The input arguments to some of the matrices are of a special form not respected by our general-purpose code, so the
`try`

construct handles the errors generated in these cases. - Some of the matrices are stored in the sparse format, so we make sure that the matrices are in the full format before taking the -norm.

mats = anymatrix('all'); % All matrix IDs. rng(1), k = 1; n = 64; % Size of the scalable matrices. for i = 1:length(mats) ID = mats{i}; props = anymatrix(ID,'p'); if ~contains(props, {'built-in'}), continue, end try if ismember('scalable',props); A = anymatrix(ID,n); else A = anymatrix(ID); end A = full(A); % Convert sparse matrices to full. [mm,nn] = size(A); if max(mm,nn) > 1 && max(mm,nn) <= 1e3 fprintf('%s: (%g,%g)\n', ID, size(A,1), size(A,2)) A = A/norm(A,1); % Normalize to avoid overflow. r = norm(A)/sqrt(norm(A,1)*norm(A,inf)); ratio(k) = r; k = k+1; end catch fprintf('Skipping %s\n', ID) end end fprintf('Min(ratio) = %9.2e\n', min(ratio))

The output is, with `[...]`

denoting omitted lines,

contest/erdrey: (64,64) contest/geo: (64,64) [...] regtools/ursell: (64,64) regtools/wing: (64,64) Min(ratio) = 1.25e-01

## Optimal Matrices

The core group contains some matrices with optimality properties. For example, `core/triminsval01`

is the unique matrix having the minimal smallest singular value over all nonsingular binary upper triangular matrices.

>> A = anymatrix('core/triminsval01',8) A = 1 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 0 0 1 1 0 1 0 1 0 0 0 1 1 0 1 0 0 0 0 0 1 1 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 >> min(svd(A)) ans = 4.7385e-02 >> inv(A) ans = 1 -1 1 -2 3 -5 8 -13 0 1 -1 1 -2 3 -5 8 0 0 1 -1 1 -2 3 -5 0 0 0 1 -1 1 -2 3 0 0 0 0 1 -1 1 -2 0 0 0 0 0 1 -1 1 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 1

Notice the appearance of Fibonacci numbers in the inverse.

## Remote Groups

The following groups of matrices can be added to Anymatrix. We hope that other groups will be made available by users in the future.

- https://github.com/higham/matrices-correlation-invalid: invalid correlation matrices. These are matrices that are intended to be correlation matrices but for various reasons relating to their construction have a negative eigenvalue and so are not positive semidefinite.
- https://github.com/higham/hpl-ai-matrix: a parametrized matrix designed by Fasi and Higham for use in the HPL-AI Mixed Precision Benchmark.
- https://github.com/Xiaobo-Liu/matrices-mp-cosm: a collection of MATLAB functions that generate the matrices used by Higham and Liu in testing multiprecision algorithms for computing the matrix cosine.
- https://github.com/mfasi/randsvdfast-matlab: a function
`randsvdfast`

by Fasi and Higham that provides similar functionality to`anymatrix('gallery/randsvd')`

but uses a faster algorithm.

To incorporate the matrices in the first of these repositories as a group named `corrinv`

we can use the `'groups'`

command (`'g'`

for short) as follows.

>> anymatrix('g','corrinv','higham/matrices-correlation-invalid'); Cloning into '[...]/corrinv/private'... [...] Anymatrix remote group cloned.

Now we can access matrices in the `corrinv`

group.

>> anymatrix('corrinv/tec03','h') tec03 Invalid correlation matrix from stress testing. tec03 is a 4-by-4 invalid correlation matrix from stress testing. >> C = anymatrix('corrinv/tec03') C = 1.0000e+00 -5.5000e-01 -1.5000e-01 -1.0000e-01 -5.5000e-01 1.0000e+00 9.0000e-01 9.0000e-01 -1.5000e-01 9.0000e-01 1.0000e+00 9.0000e-01 -1.0000e-01 9.0000e-01 9.0000e-01 1.0000e+00 >> eig(C) ans = -2.7759e-02 1.0000e-01 1.0137e+00 2.9140e+00