Anymatrix: An Extensible MATLAB Matrix Collection

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 $A$ is the property that $A^{\circ r}$ is positive semidefinite for all $r\ge 0$, where $A^{\circ r} = (a_{ij}^r)$ is the Hadamard power. We verify this property for $n = 4$ and $r = n/10$ 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 $\|A\|_2 / (\|A\|_1 \|A\|_{\infty} )^{1/2}$ over all the matrices, with default input arguments and size $64$ if the dimension is variable. This ratio is known to lie between $n^{-1/2}$ and $1$. 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 $2$-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.

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


Top BibTeX Tips

BibTeX is an essential tool for preparing references for a LaTeX document. It collects entries from a BibTeX .bib database and formats a reference list in a .bbl file. Here are my top BibTeX tips.

Protect Capitals

The title field should be typed in title case, with all words capitalized except for articles (the, a, an), prepositions (to, with, on, etc.), and conjunctions (and, for, or, etc.). BibTeX will convert words to lower case if the style requires it, which it typically does for the article entry type.

Capitalized words that must not be converted to lower case because they are proper nouns must be protected by putting them in braces, as in the example

title = "A {Krylov} Methods Toolbox for {MATLAB}"


Without the braces this title appears with most styles as “A krylov methods toolbox for matlab”.

Failing to protect capitals is the most common error I see in bib entries. Note that bib entries downloaded from publisher’s websites usually do not protect capitals (and often have other errors), so you should always carefully check them.

Identify Surnames

When a surname comprises two words but is not hyphenated, BibTeX will interpret the first part of the surname as a given name. This is problematic when the BibTeX style abbreviates given names to initials. For example,

author = "Charles F. Van Loan",


will produce “C. F. V. Loan” instead of “C. F. Van Loan”. The cure is to reverse the order of the given names and surname

author = "Van Loan, Charles F.",


Alternatively, you can protect the surname with braces:

author = "Charles F. {Van Loan}",


Add a DOI Field

A digital object identifier (DOI) provides a persistent link to an object on the web, and almost every published paper has one, as do many books that are available electronically. I recommend including the DOI in a doi field, such as

doi = "10.1137/1.9781611976106",


With an appropriate BibTeX style file either the DOI will be displayed and hyperlinked or the title will be hyperlinked. The doi field above generates the hyperlink

https://doi.org/10.1137/1.9781611976106


which resolves to the object in question. Here is an example of a bibliography entry from a SIAM paper that contains a DOI:

Some styles that support the doi field are listed here; see also myplain2-doi.bst (my modification of an existing style file) and the siamplain.bst style file available here.

Get a Bib Entry from a DOI

If you have a paper that has a DOI and wish to obtain a bib entry you can type the DOI into doi2bib or DOI to BibTeX converter. I use doi2bib rather than download bib entries from publisher websites, as I find the results are more reliable.

Include a URL Field

For items that do not have a DOI it is desirable to include a url field that gives the URL of the item on the web, especially for preprints, general articles, and software. Again, this is not a standard field, but some styles support it and print the URL or produce a hyperlink.

Include Date Fields

The last two fields in my bib entries are of the form

created = "2019.04.23",
updated = "2020.03.01"


These are nonstandard fields so are ignored by BibTeX. I include them because these two dates can be very useful. They give me clues about when I first came across or read a paper. The “updated” field indicates when I have added a DOI to an old entry, corrected a nontrivial error in an entry, or a preprint has been revised or become a published paper.

Use Strings for Journal Names

If you type the journal field explicitly, as in

journal = "SIAM J. Sci. Comput.",


it will be hard to keep these fields consistent across hundreds of entries. It is better to use an abbreviation

@String{j-SISC                  = "SIAM J. Sci. Comput."}


then type

journal = j-SISC,


These String lines must appear before the string is used. I collect them into a separate bib file, strings.bib, and load it before my other bib files:

\bibliography{strings,njhigham,paper}


For mathematics journals I use abbreviations used by Mathematical Reviews, which can be found in this PDF document.

Use Backref

For larger documents it is helpful for the reader to know where bibliography items are cited in the text. Including

\usepackage{backref}


in the preamble of the LaTeX document will cause each bibliography entry to be appended with a list of the pages on which it is cited. Here is an example of a bibliography entry annotated by backref: