## Introduction

This article presents a reasonably full featured linear algebra library for .NET. It is a translation of the Java matrix package JAMA. All of the matrix operations were successfully translated, but the IO methods had too much of a Java flavor and so were replaced. The library provides the standard linear algebra features one would expect, such as multiplying and inverting matrices. The following decompositions are also provided:

- Cholesky Decomposition of symmetric, positive definite matrices
- LU Decomposition (Gaussian elimination) of rectangular matrices
- QR Decomposition of rectangular matrices
- Eigenvalue Decomposition of both symmetric and non-symmetric square matrices

This should be sufficient for many of one's matrix needs. There was also some Java testing code, but while it may have been sufficient for the original creators, it was not enough for a translator lacking intimate knowledge of why certain choices were made. The unit tests used on this project are included, and are at 97% code coverage, so you can have reasonable confidence in this software. I have purposely decided to limit the amount of code shown in this article. My goal is to allow you to use some of the power inherent in linear algebra as a black box. I want you to be able to just use the fact that you can solve systems of equations (not so hard) or perform least squares (a bit harder) or find Eigenvalues or singular values (really hard) without needing to understand the intricate mathematical details.

## Background

I strongly advise going to Stanford Engineering Everywhere and watching the first lecture on linear dynamical systems. Unlike the lectures further on, this one does not require significant mathematical understanding to appreciate. Dr. Boyd does a brilliant job of illustrating the immense power that linear algebra can bring to your applications. If you are more mathematically inclined, the entire course is certainly worth watching, and it was also one of the major motivators for my translating JAMA and writing this article.

This is certainly not the only .NET linear algebra software on the web.

- infer.net: A very interesting project from Microsoft in the UK.
- A list of numerical libraries is available on Wikipedia. This includes both free and commercial libraries.
- DotNumerics: This is a translation of LAPACK from Fortran.
- DotNetMatrix: A previous translation of JAMA that I just recently found out about and you might like.

## Roadmap

This is the second article in a series on computing with Rational numbers. This may seem a bit odd as this project does not use Rational numbers, but I felt it better to separate things. The next article will then be able to focus on Rational matrices and their performance characteristics.

As can be seen, there is a lot of work to do, enough to dominate my free time for quite a while. If anyone is inspired, I would be delighted to work with them on the advancement of rational computing on the .NET platform.

## Caveats

This code has been sitting on my computer for over a year, and only now is it finally being released. You could reasonably wonder why what appears to be such a useful library was kept under wraps for so long after completion. There are two main reasons. The first is that this is a translation and so not fully original to me. It should be noted that linear algebra packages are, in general, not created from scratch. Pretty much everything is an outgrowth of some earlier Fortran routines such as LAPACK. On account of this, I have preserved the vast majority of the original comments, so one may see references to Java here and there. I would also note that though I deserve some credit for the effort I put into the translation and unit tests, much greater credit should be awarded to the original creators: Ronald F. Boisvert, Joe Hicklin, Bruce Miller, Cleve Moler, Roldan Pozo, Karin Remington, and Peter Webb.

My second concern is more serious. Some of the code in this library is very hard to understand. In particular, I speak of the `EigenvalueDecomposition`

and `SingularValueDecomposition`

constructors. To be honest, I do not understand those two massive routines. Since I believe that one should understand the code one presents, this is a bit of a quandary. However, solving this problem is one of the main problems unit testing was meant to solve. With sufficient unit tests, you can modify code that you do not understand and still have a reasonable expectation that if the tests pass, you will have working code.

## Sample usage

Linear algebra is extremely useful. Solving systems of linear equations is a basic task that a linear algebra library ought to perform. Here is an example from the unit tests:

String strMat = @"2 1 1
4 -6 0
-2 7 2";
String strVals = @"5
-2
9";
String strExpectedSoln = @"1
1
2";
Matrix mat = Matrix.Parse(strMat);
Matrix vals = Matrix.Parse(strVals);
Matrix expectedSoln = Matrix.Parse(strExpectedSoln);
Matrix soln = mat.Solve(vals);
Assert.That(mat.Times(soln), Is.EqualTo(vals));
Assert.That (soln ,Is.EqualTo(expectedSoln));

This is pretty easy to do. You might notice that almost the entirety of the work involved is in setting up the input in a human readable format. This type of situation where we have the same number of unknowns and equations does come up; however, a much more interesting situation occurs when the number of equations exceeds the number of variables. In these types of problems, you try to find the best approximation to a solution given your equations. This can easily occur when the equations are based on error prone measurements. These problems are referred to as "least squares" problems, and you can do a remarkable amount of mathematical modeling with this technique.

String strMat = @"1 1
1 2
1 3
1 4";
String strVals = @"6
5
7
10";
String strExpectedSoln = @"3.5
1.4";
Matrix mat = Matrix.Parse(strMat);
Matrix vals = Matrix.Parse(strVals);
Matrix expectedSoln = Matrix.Parse(strExpectedSoln);
Matrix soln = mat.Solve(vals);
Assert.That(soln, Is.EqualTo(expectedSoln).Within(.001));

It is no harder from a programming standpoint to solve a least squares problem than it is to solve a more matched set of linear equations. Though there are many potential uses for this library, I will assume that you want to either solve linear systems of equations or calculate least squares approximate solutions. If we have two matrices A and B such that Ax=B, they can be solved or least square solved by the following:

Matrix solution = A.Solve(B);

The majority of the work is involved in creating the matrices. Note that numerous IO samples can be found in the `Matrix_IOTests`

unit test file.

### Making matrices

There are three main methods for the creation of matrices. You can create a matrix of zeros and then set the values.

Matrix A = new Matrix(3,2); A.Set(0,1,7); A.Array[0,1] = 7;

A matrix can also be created directly from a one or two dimensional array.

double[] valArray = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 };
Matrix A = new Matrix(valArray,4);
double[][] valTwoD= new double[3][] { new double[4] { 1.0, 0.0, 0.0, 0.0 },
new double[4] { 0.0, 1.0, 0.0, 0.0 },
new double[4] { 0.0, 0.0, 1.0, 0.0 } };
Matrix B = new Matrix(valTwoD);

There are also several ways of parsing text to create a matrix. It is assumed that there are three likely formats that matrices are likely to come in. These are strings where rows are delimited by lines, and columns by spaces, the format used by MATLAB or the format used by Mathematica.

Matrix A = Matrix.Parse("1 2\n3 4"); A = Matrix.Parse("[1 2;3 4]"); A = Matrix.Parse("{{1, 2}, {3, 4}}");
A = Matrix.ParseMatLab("[1 2;3 4]");
A = Matrix.ParseMathematica("{{1, 2}, {3, 4}}]");

If your string is in another format, there is also a version with many parameters.

public static Matrix Parse(string str, string matrixFrontCap, string rowFrontCap,
string rowDelimiter, string columnDelimiter,
string rowEndCap, string matrixEndCap){..}

There is also a `FromDataTable`

and a `Load`

that takes a file path. There is also a `Generators`

assembly that has more specialized methods to produce `Toeplitz`

and some other matrices.

## Unit tests

This project includes a large number of unit tests. In fact, the vast majority of time spent on this project was on writing and devising unit tests. Getting high levels of code coverage on preexisting code can be astonishingly difficult. Some of the unit tests use random numbers, and will on occasionally fail. This is due to the degree of numerical precision expected of the answers. All of these tests have *random* in their names.

## Conclusion

My hope is that this library will make it significantly easier to write software that takes advantage of the power of linear algebra. It is also another step in my exploration of computing with Rational numbers. The third article in this series, where Rational matrices appear, is coming soon. Stay tuned.