Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 6 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,6 @@ include multivariate polynomials, functions such as sin or cos, constants such a
pi, fractional exponents, negative exponents, and optimistically also polynomial
expansion.

### Arr2D

The Arr2D struct provides a convenient way to use a two-dimensional matrix that is
a one-dimensional vector under the hood.
This allows for efficient memory usage while enabling standard matrix operations.

Arr2D implements a wide range of methods and traits, including:

- Linear Algebra: dot product, inverse, transpose.
- Arithmetic: Implementations of multiplication by matrices, vectors, and scalars and division by scalars
- Manipulation: shape, size, full, reshape, map
- Conversion: from_flat, From, TryFrom
- Utility: new, max, min, is_empty

## Project layout

This repository is split into three crates. The tests for spindalis_core and
Expand All @@ -112,13 +98,12 @@ Within these crates, the following modules `spindalis::<module name>` are provid

| Module | Description |
| --------------- | ------------------------------------------------------------------------------------------------------ |
| `utils` | Utility functions such as `Arr2D`, `Arr2DError`, forward substitution, and back substitution |
| `utils` | Utility functions such as different types of mean and standard deviation |
| `polynomials` | Parsing and evaluating simple and intermediate polynomials |
| `derivatives` | Differentiating simple and intermediate polynomials |
| `integrals` | Integrating simple and intermediate polynomials |
| `solvers` | Solving equations and differential equations, including root-finding, extrema-finding, and ODE solvers |
| `eigen` | Algorithms to solve eigenvalue and eigenvector problems |
| `decomposition` | Decomposition algorithms including LU decomposition and LU decomposition with partial pivoting |
| `regressors` | Linear and non-linear regression, including least-squares, Gaussian, and polynomial regression |
| `reduction` | Linear and non-linear dimensionality reduction algorithms, including PCA |

Expand Down Expand Up @@ -149,7 +134,11 @@ Stay connected via our **[Discord Server](https://discord.gg/PdVZCtcgaH)**

## Stability

This project is in the alpha stage. APIs may change without warning until version
> [!CAUTION]
> Arr2D functionality and decomposition functions moved to [jedvek](https://github.com/lignum-vitae/jedvek)!
> Arr2D is now Matrix2D.

This project is in the beta stage. APIs may change without warning until version
1.0.0.

## License
Expand Down
1 change: 1 addition & 0 deletions spindalis/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ name = "spindalis"
path = "src/lib.rs"

[dependencies]
jedvek = "0.1.0"
spindalis_core = { path = "../spindalis_core", version = ">=0.2.0" }
spindalis_macros = { path = "../spindalis_macros", version = "0.1.0" }
4 changes: 2 additions & 2 deletions spindalis/examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ parsing to parse polynomials into an abstract syntax tree.
## Math

Where applicable, functions accept any coefficient matrix that can be coerced
into a `Arr2D<f64>` type. That includes nested vecs of ints or floats,
nested arrays of ints or floats, and Arr2D vectors of types other than
into a `Matrix2D<f64>` type. That includes nested vecs of ints or floats,
nested arrays of ints or floats, and Matrix2D vectors of types other than
`f64`. The matrix must be borrowed for conversion to work.
The right hand side vector also accepts a vector containing
any numerical values that can be converted into `f64`.
Expand Down
6 changes: 3 additions & 3 deletions spindalis/examples/eigen.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use jedvek::{Matrix2D, Rounding};
use spindalis::eigen::power_method;
use spindalis::utils::{Arr2D, Rounding};

fn main() {
let matrix = Arr2D::from(&[[2.0, 8.0, 10.0], [8.0, 4.0, 5.0], [10.0, 5.0, 7.0]]);
let matrix = Matrix2D::from(&[[2.0, 8.0, 10.0], [8.0, 4.0, 5.0], [10.0, 5.0, 7.0]]);
println!("Original Matrix:\n{matrix}\n");
let result = power_method(&matrix, 1e-10);
match result {
Expand All @@ -16,7 +16,7 @@ fn main() {
Ok(inverted) => inverted,
Err(e) => {
eprintln!("Unable to invert matrix: {e:?}");
Arr2D::from(&[[]])
Matrix2D::from(&[[]])
}
};
if !inverse_matrix.is_empty() {
Expand Down
17 changes: 0 additions & 17 deletions spindalis/examples/lu_decomposition.rs

This file was deleted.

5 changes: 0 additions & 5 deletions spindalis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ pub mod integrals {
pub use spindalis_core::integrals::univariate_definite::romberg_definite;
}

pub mod decomposition {
pub use crate::solvers::decomposition::lu::lu_decomposition;
pub use crate::solvers::decomposition::plu::lu_pivot_decomposition;
}

pub mod eigen {
pub use crate::solvers::eigen::power_method::power_method;
}
15 changes: 8 additions & 7 deletions spindalis/src/reduction/dimension/linear/pca.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::reduction::dimension::{DimensionError, ReductionError};
use crate::utils::{StdDevType, arith_mean, arr2D::Arr2D, std_dev};
use crate::utils::{StdDevType, arith_mean, std_dev};
use jedvek::Matrix2D;

// ┌─────────────┬────────┬────────┬────────┬────────┬──────────┐
// │ │ USA │ France │ Belgium│ UK │ Czechia │
Expand All @@ -16,9 +17,9 @@ use crate::utils::{StdDevType, arith_mean, arr2D::Arr2D, std_dev};
pub fn pca() {}

fn _center_data(
data: &Arr2D<f64>,
data: &Matrix2D<f64>,
std_type: Option<StdDevType>,
) -> Result<Arr2D<f64>, ReductionError> {
) -> Result<Matrix2D<f64>, ReductionError> {
let mut result = data.clone();
let mut std = 1_f64;
for row in &mut result {
Expand Down Expand Up @@ -76,10 +77,10 @@ fn _covariance(x_data: &[f64], y_data: &[f64]) -> Result<f64, DimensionError> {
Ok(cov_sum / (n - 1.0))
}

fn _cov_mat(data: &Arr2D<f64>) -> Result<Arr2D<f64>, ReductionError> {
fn _cov_mat(data: &Matrix2D<f64>) -> Result<Matrix2D<f64>, ReductionError> {
let height = data.height;

let mut covariance_matrix = Arr2D::full(0.0, height, height);
let mut covariance_matrix = Matrix2D::full(0.0, height, height);

for (i, x) in data.into_iter().enumerate() {
for (j, y) in data.into_iter().enumerate() {
Expand All @@ -99,10 +100,10 @@ mod tests {

#[test]
fn test_center_data() {
let data = Arr2D::from(&[[1., 2., 3.], [4., 5., 6.]]);
let data = Matrix2D::from(&[[1., 2., 3.], [4., 5., 6.]]);

let centered = _center_data(&data, None).unwrap();
let expected = Arr2D::from(&[[-1., 0., 1.], [-1., 0., 1.]]);
let expected = Matrix2D::from(&[[-1., 0., 1.], [-1., 0., 1.]]);

assert_eq!(centered, expected);
}
Expand Down
8 changes: 4 additions & 4 deletions spindalis/src/reduction/dimension/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
pub mod linear;
pub mod non_linear;

use crate::utils::Arr2DError;
use jedvek::Matrix2DError;
pub use linear::pca::pca;

#[derive(Debug)]
pub enum ReductionError {
ShapeError(DimensionError),
InvalidFlatVector(Arr2DError),
InvalidFlatVector(Matrix2DError),
ZeroMean,
}

impl From<Arr2DError> for ReductionError {
fn from(err: Arr2DError) -> Self {
impl From<Matrix2DError> for ReductionError {
fn from(err: Matrix2DError) -> Self {
ReductionError::InvalidFlatVector(err)
}
}
Expand Down
24 changes: 13 additions & 11 deletions spindalis/src/reduction/matrix/hessenberg.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
use crate::solvers::SolverError;
use crate::utils::Arr2D;
use jedvek::Matrix2D;

/// Computes the Hessenberg reduction of a square matrix A.
/// Returns (H, Q) such that H = Q^T * A * Q, where H is upper Hessenberg and Q is orthogonal.
pub fn hessenberg_reduction(matrix: &Arr2D<f64>) -> Result<(Arr2D<f64>, Arr2D<f64>), SolverError> {
pub fn hessenberg_reduction(
matrix: &Matrix2D<f64>,
) -> Result<(Matrix2D<f64>, Matrix2D<f64>), SolverError> {
if matrix.height != matrix.width {
return Err(SolverError::NonSquareMatrix);
}
let n = matrix.height;
if n <= 2 {
return Ok((matrix.clone(), Arr2D::identity(n)));
return Ok((matrix.clone(), Matrix2D::identity(n)));
}

let mut h = matrix.clone();
let mut q = Arr2D::identity(n);
let mut q = Matrix2D::identity(n);

for k in 0..n - 2 {
// x = h[k+1..n, k]
Expand Down Expand Up @@ -83,23 +85,23 @@ pub fn hessenberg_reduction(matrix: &Arr2D<f64>) -> Result<(Arr2D<f64>, Arr2D<f6
#[cfg(test)]
mod tests {
use super::*;
use crate::utils::Rounding;
use jedvek::Rounding;

#[test]
fn test_hessenberg_2x2() {
let mat = Arr2D::from(&[[1.0, 2.0], [3.0, 4.0]]);
let mat = Matrix2D::from(&[[1.0, 2.0], [3.0, 4.0]]);
let (h, q) = hessenberg_reduction(&mat).unwrap();
assert_eq!(h.round_to_decimal(10), mat.round_to_decimal(10));
assert_eq!(
q.round_to_decimal(10),
Arr2D::identity(2).round_to_decimal(10)
Matrix2D::identity(2).round_to_decimal(10)
);
}

#[test]
fn test_hessenberg_3x3() {
// Simple 3x3 matrix
let mat = Arr2D::from(&[[1.0, 5.0, 7.0], [3.0, 0.0, 6.0], [4.0, 3.0, 1.0]]);
let mat = Matrix2D::from(&[[1.0, 5.0, 7.0], [3.0, 0.0, 6.0], [4.0, 3.0, 1.0]]);
let (h, q) = hessenberg_reduction(&mat).unwrap();

// Check if H is upper Hessenberg
Expand All @@ -110,7 +112,7 @@ mod tests {
let i = q.dot(&qt).unwrap();
assert_eq!(
i.round_to_decimal(10),
Arr2D::identity(3).round_to_decimal(10)
Matrix2D::identity(3).round_to_decimal(10)
);

// Check if A = Q * H * Q^T
Expand All @@ -120,7 +122,7 @@ mod tests {

#[test]
fn test_hessenberg_4x4() {
let mat = Arr2D::from(&[
let mat = Matrix2D::from(&[
[1.0, 2.0, 3.0, 4.0],
[2.0, 1.0, 2.0, 3.0],
[3.0, 2.0, 1.0, 2.0],
Expand All @@ -138,7 +140,7 @@ mod tests {
let i = q.dot(&qt).unwrap();
assert_eq!(
i.round_to_decimal(10),
Arr2D::identity(4).round_to_decimal(10)
Matrix2D::identity(4).round_to_decimal(10)
);

// Check A = Q H Q^T
Expand Down
91 changes: 0 additions & 91 deletions spindalis/src/solvers/decomposition/lu.rs

This file was deleted.

2 changes: 0 additions & 2 deletions spindalis/src/solvers/decomposition/mod.rs

This file was deleted.

Loading