sparse21

Solving large systems of linear equations using sparse matrix methods.

Docs

```rust let mut m = sparse21::Matrix::from_entries(vec![ (0, 0, 1.0), (0, 1, 1.0), (0, 2, 1.0), (1, 1, 2.0), (1, 2, 5.0), (2, 0, 2.0), (2, 1, 5.0), (2, 2, -1.0), ]);

    let soln = m.solve(vec![6.0, -4.0, 27.0]); 
    // => vec![5.0, 3.0, -2.0]

```

Sparse methods are primarily valuable for systems in which the number of non-zero entries is substantially less than the overall size of the matrix. Such situations are common in physical systems, including electronic circuit simulation. All elements of a sparse matrix are assumed to be zero-valued unless indicated otherwise.

Usage

Sparse21 exposes two primary data structures:

Once matrices and systems have been created, their primary public method is solve, which returns a (dense) Vec solution-vector.

Matrix

Sparse21 matrices can be constructed from a handful of data-sources

Matrix::new creates an empty matrix, to which elements can be added via the add_element and add_elements methods.

```rust let mut m = Matrix::new();

m.addelement(0, 0, 11.0); m.addelement(7, 0, 22.0); m.addelement(0, 7, 33.0); m.addelement(7, 7, 44.0); ```

```rust let mut m = Matrix::new();

m.add_elements(vec![(0, 0, 11.0), (7, 0, 22.0), (0, 7, 33.0), (7, 7, 44.0) ]); ```

The arguments to add_element are a row (usize), column (usize), and value (f64). Adding elements (plural) via add_elements takes a vector of (usize, usize, f64) tuples, representing the row, col, and val.

Unlike common mathematical notation, all locations in sparse21 matrices and vectors are zero-indexed. Adding a non-zero at the "first" matrix element therefore implies calling add_element(0, 0, val).

Creating a Matrix from data entries with Matrix::from_entries:

rust let mut m = Matrix::from_entries(vec![ (2, 2, -1.0), (2, 1, 5.0), (2, 0, 2.0), (1, 2, 5.0), (1, 1, 2.0), (0, 2, 1.0), (0, 1, 1.0), (0, 0, 1.0), ]);

The Matrix::identity method returns a new identity matrix of size (n x n):

rust let mut m = Matrix::identity(3); let soln = m.solve(vec![11.1, 30.3, 99.9]); assert_eq!(soln, vec![11.1, 30.3, 99.9]);

Solving

Sparse21 matrices are built for solving equation-systems. The primary public method of a Matrix is solve(), which accepts a Vec right-hand-side as its sole argument, and returns a solution Vec of the same size.

Matrix Mutability

You may have noticed all examples to date declare matrices as mut, perhaps unnecessarily. This is on purpose. The Matrix::solve method (un-rustily) modifies the matrix in-place. For larger matrices, the in-place modification saves orders of magnitude of memory, as well as time creating and destroying elements. While in-place self-modification falls out of line with the Rust ethos, it follows a long lineage of scientific computing tools for this and similar tasks.

So: in order to be solved, matrices must be declared mut.

System

Sparse21 equation-systems can be loaded directly from a (custom-format) file including the elements and RHS.

rust let s = sparse21::System::from_file(Path::new("my_matrix.mat"))?; let soln = s.solve();

It is often more convenient to split a sparse21::System into its constituent matrix and RHS. The split method returns a tuple of the two:

```rust let s = sparse21::System::from_file(&p)?;

// Split into parts, and solve // More or less equivalent to s.solve() let (mut mat, rhs) = s.split(); let res = mat.solve(rhs); ```