5个版本

0.2.1 2020年2月4日
0.2.0 2020年1月24日
0.1.2 2020年1月24日
0.1.1 2020年1月24日
0.1.0 2020年1月24日

#780 in 数学

BSD-3-Clause

10MB
1K SLoC

sparse21

使用稀疏矩阵方法求解大型线性方程组。

Docs

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]

稀疏方法主要适用于非零元素数量远小于矩阵整体大小的系统。这种情况在物理系统中很常见,包括电子电路仿真。除非另有说明,否则假设稀疏矩阵的所有元素都是零值。

用法

Sparse21公开了两种主要数据结构

  • Matrix 代表一个 f64 值的稀疏矩阵
  • System 代表形式为 Ax=b 的线性方程组,包括一个 Matrix (A) 和右手边 Vec (b)。

一旦创建了矩阵和系统,它们的主要公共方法是 solve,该方法返回一个 (密集) 的 Vec 解向量。

矩阵

Sparse21矩阵可以从几个数据源构建

Matrix::new 创建一个空矩阵,可以通过 add_elementadd_elements 方法添加元素。

let mut m = Matrix::new();

m.add_element(0, 0, 11.0);
m.add_element(7, 0, 22.0);
m.add_element(0, 7, 33.0);
m.add_element(7, 7, 44.0);
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)
]);

add_element 的参数是一个行 (usize),列 (usize) 和值 (f64)。通过 add_elements 添加元素(复数)需要一个代表行、列和值的 (usize, usize, f64) 元组向量。

与常见的数学符号不同,sparse21 矩阵和向量的所有位置都是零索引。在“第一个”矩阵元素中添加非零值意味着调用 add_element(0, 0, val)

使用 Matrix::from_entries 从数据条目创建 Matrix

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),
        ]);

Matrix::identity 方法返回一个大小为 (n x n) 的新单位矩阵

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]);

求解

Sparse21 矩阵用于求解方程组。Matrix 的主要公开方法是 solve(),它接受一个 Vec 右侧作为其唯一参数,并返回一个同样大小的解 Vec

矩阵可变性

你可能注意到到目前为止的所有示例都声明矩阵为 mut,可能是不必要的。这是故意的。Matrix::solve 方法(非 Rust 式地)修改矩阵 原地。对于较大的矩阵,原地修改可以节省数量级的内存,以及创建和销毁元素的时间。尽管原地自我修改与 Rust 的精神不符,但它遵循了科学计算工具的长期传统,用于此类和类似任务。

因此:为了求解,必须声明矩阵为 mut

系统

Sparse21 方程组可以直接从包括元素和 RHS 的(自定义格式)文件中加载。

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

通常更方便将 sparse21::System 分解为其组成的矩阵和 RHS。split 方法返回一个包含这两个元素的元组

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);

依赖关系