< 返回版块

0x5F3759DF 发表于 2020-12-26 19:39

sprs是用纯Rust实现的部分稀疏矩阵数据结构和线性代数算法

特性

结构

  • 矩阵
  • 三元组矩阵
  • 稀疏向量

运算

  • 稀疏矩阵 / 稀疏向量积
  • 稀疏矩阵 / 稀疏矩阵积
  • 稀疏矩阵 / 稀疏矩阵加法,减法
  • 稀疏向量 / 稀疏向量加法,减法,点积
  • 稀疏 / 稠密矩阵运算

算法

  • 压缩稀疏矩阵的外部迭代器
  • 稀疏向量迭代
  • 稀疏向量联合非零迭代
  • 简单的稀疏矩阵Cholesky分解 (需要选择接受 LGPL 许可)
  • 等式右侧为稠密矩阵或向量情况下的稀疏矩阵解三角方程组

示例

矩阵创建

use sprs::TriMat;

let mut a = TriMat::new((4, 4));
a.add_triplet(0, 0, 3.0_f64);
a.add_triplet(1, 2, 2.0);
a.add_triplet(3, 0, -2.0);

// 这个矩阵类型不允许进行计算,需要
// 转换为兼容的稀疏矩阵类型,例如
let b = a.to_csr();

用更高效直接的稀疏矩阵生成器来构建矩阵

  use sprs::{CsMat, CsMatOwned, CsVec};
  let eye : CsMatOwned<f64> = CsMat::eye(3);
  let a = CsMat::new_csc((3, 3),
                         vec![0, 2, 4, 5],
                         vec![0, 1, 0, 2, 2],
                         vec![1., 2., 3., 4., 5.]);

矩阵向量乘法

  use sprs::{CsMat, CsVec};
  let eye = CsMat::eye(5);
  let x = CsVec::new(5, vec![0, 2, 4], vec![1., 2., 3.]);
  let y = &eye * &x;
  assert_eq!(x, y);

矩阵乘法,加法

  use sprs::{CsMat, CsVec};
  let eye = CsMat::eye(3);
  let a = CsMat::new_csc((3, 3),
                         vec![0, 2, 4, 5],
                         vec![0, 1, 0, 2, 2],
                         vec![1., 2., 3., 4., 5.]);
  let b = &eye * &a;
  assert_eq!(a, b.to_csr());

其他示例

pub mod array_backend;
pub mod errors;
pub mod indexing;
pub mod io;
pub mod num_kinds;
mod sparse;
pub mod stack;

pub type Ix1 = ndarray::Ix1;
pub type Ix2 = ndarray::Ix2;

pub use crate::indexing::SpIndex;

pub use crate::sparse::{
    csmat::CsIter, csmat::OuterIterator, csmat::OuterIteratorMut,
    csmat::OuterIteratorPerm, kronecker::kronecker_product, CsMat, CsMatBase,
    CsMatI, CsMatVecView, CsMatView, CsMatViewI, CsMatViewMut, CsMatViewMutI,
    CsStructure, CsStructureI, CsStructureView, CsStructureViewI, CsVec,
    CsVecBase, CsVecI, CsVecView, CsVecViewI, CsVecViewMut, CsVecViewMutI,
    SparseMat, TriMat, TriMatBase, TriMatI, TriMatIter, TriMatView,
    TriMatViewI, TriMatViewMut, TriMatViewMutI,
};

pub use crate::sparse::symmetric::is_symmetric;

pub use crate::sparse::permutation::{
    perm_is_valid, transform_mat_papt, PermOwned, PermOwnedI, PermView,
    PermViewI, Permutation,
};

pub use crate::sparse::CompressedStorage::{self, CSC, CSR};

pub use crate::sparse::binop;
pub use crate::sparse::linalg;
pub use crate::sparse::prod;
pub use crate::sparse::smmp;
pub use crate::sparse::special_mats;
pub use crate::sparse::visu;

pub mod vec {
    pub use crate::sparse::{CsVec, CsVecBase, CsVecView, CsVecViewMut};

    pub use crate::sparse::vec::{
        IntoSparseVecIter, NnzEither, NnzIndex, NnzOrZip, SparseIterTools,
        VecDim, VectorIterator, VectorIteratorMut,
    };
}

pub use crate::sparse::construct::{bmat, hstack, vstack};

pub use crate::sparse::to_dense::assign_to_dense;

/// 矩阵的形状,第一个元素表明这是一个双元素元组
/// 行数, 第二个元素表明列数
pub type Shape = (usize, usize); // FIXME: 或许此处可以用Ix2?

pub type SpRes<T> = Result<T, errors::SprsError>;

/// 用枚举作为配置项来对算法进行对称性检查
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum SymmetryCheck {
    CheckSymmetry,
    DontCheckSymmetry,
}
pub use SymmetryCheck::*;

/// 用枚举作为配置项来对算法进行排列检查
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum PermutationCheck {
    CheckPerm,
    DontCheckPerm,
}
pub use PermutationCheck::*;

/// sprs支持的不同种类的填充归约算法
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[non_exhaustive]
pub enum FillInReduction {
    NoReduction,
    ReverseCuthillMcKee,
    CAMDSuiteSparse,
}

#[cfg(feature = "approx")]
/// 用于比较向量和矩阵的特征使用了近似特征
///
/// 使用不同的存储来比较稀疏矩阵可能会很慢
/// 为了高效,建议使用同样的存储顺序
///
/// 这些特征需要 `approx` 特性在激活状态
pub mod approx {
    pub use approx::{AbsDiffEq, RelativeEq, UlpsEq};
}

#[cfg(test)]
mod test_data;

#[cfg(test)]
mod test {
    use super::CsMat;

    #[test]
    fn iter_rbr() {
        let mat = CsMat::new(
            (3, 3),
            vec![0, 2, 3, 3],
            vec![1, 2, 0],
            vec![0.1, 0.2, 0.3],
        );
        let view = mat.view();
        let mut iter = view.iter();
        assert_eq!(iter.next(), Some((&0.1, (0, 1))));
        assert_eq!(iter.next(), Some((&0.2, (0, 2))));
        assert_eq!(iter.next(), Some((&0.3, (1, 0))));
        assert_eq!(iter.next(), None);
    }
}

评论区

写评论

还没有评论

1 共 0 条评论, 1 页