前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【每周一库】- sprs - 用Rust实现的稀疏矩阵库

【每周一库】- sprs - 用Rust实现的稀疏矩阵库

作者头像
MikeLoveRust
发布2021-01-07 10:25:09
9270
发布2021-01-07 10:25:09
举报
文章被收录于专栏:Rust语言学习交流

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

特性

结构

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

运算

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

算法

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

示例

矩阵创建

代码语言:javascript
复制
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();

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

代码语言:javascript
复制
  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.]);

矩阵向量乘法

代码语言:javascript
复制
  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);

矩阵乘法,加法

代码语言:javascript
复制
  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());

其他示例

代码语言:javascript
复制
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);
    }
}

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust语言学习交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 特性
    • 结构
      • 运算
        • 算法
        • 示例
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档