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 数学
10MB
1K SLoC
sparse21
使用稀疏矩阵方法求解大型线性方程组。
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_element
和 add_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);