Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bind suitesparse camd #223

Merged
merged 11 commits into from
Sep 15, 2020
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,23 +105,23 @@ jobs:
override: true

- name: Build (exclude suitesparse)
run: cargo build --verbose --workspace --exclude suitesparse_ldl_sys --exclude sprs_suitesparse_ldl
run: cargo build --verbose --workspace --exclude suitesparse_ldl_sys --exclude sprs_suitesparse_ldl --exclude sprs_suitesparse_camd --exclude suitesparse_camd_sys
if: matrix.os != 'ubuntu-18.04'

- name: Build (all)
run: cargo build --verbose --workspace
if: matrix.os == 'ubuntu-18.04'

- name: Test (exclude suitesparse)
run: cargo test --verbose --workspace --exclude suitesparse_ldl_sys --exclude sprs_suitesparse_ldl
run: cargo test --verbose --workspace --exclude suitesparse_ldl_sys --exclude sprs_suitesparse_ldl --exclude sprs_suitesparse_camd --exclude suitesparse_camd_sys
if: matrix.os != 'ubuntu-18.04'

- name: Test (all)
run: cargo test --verbose --workspace
if: matrix.os == 'ubuntu-18.04'

- name: Test (suitesparse integration)
run: cargo test -p sprs-ldl --features sprs_suitesparse_ldl -Zpackage-features
run: cargo test -p sprs-ldl --features "sprs_suitesparse_ldl sprs_suitesparse_camd" -Zpackage-features
if: matrix.os == 'ubuntu-18.04' && matrix.build == 'nightly'

benches:
Expand Down
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ script:
- cargo test --release --all --verbose
- cargo run --example heat
- ./.travis_rustfmt
- ./.travis_nightly

notifications:
email:
Expand Down
13 changes: 0 additions & 13 deletions .travis_nightly

This file was deleted.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

name = "sprs"
description = "A sparse matrix library"
version = "0.8.1"
version = "0.9.0"
authors = ["Vincent Barrielle <[email protected]>"]
edition = "2018"

Expand Down Expand Up @@ -51,6 +51,8 @@ members = [
"sprs-ldl",
"suitesparse_bindings/suitesparse_ldl_sys",
"suitesparse_bindings/sprs_suitesparse_ldl",
"suitesparse_bindings/suitesparse_camd_sys",
"suitesparse_bindings/sprs_suitesparse_camd",
"sprs-rand",
"sprs-benches",
]
Expand Down
4 changes: 4 additions & 0 deletions changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
Changelog
=========

- 0.9.0
- Make FillInReduction enum non exhaustive to prevent excessive breakage
when new algorithms are implemented. **breaking change**
- Make rayon optional **breaking change**
- 0.8.1
- Expose the ``num_kinds`` module to allow generic usage of matrix market
serialization functions in client crates
Expand Down
4 changes: 2 additions & 2 deletions sprs-benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ authors = ["Vincent Barrielle <[email protected]>"]
edition = "2018"

[dependencies.sprs]
version = "0.8.0"
version = "0.9.0"
path = ".."

[dependencies.sprs-rand]
version = "0.1.0"
version = "0.2.0"
path = "../sprs-rand"

[dependencies.plotters]
Expand Down
14 changes: 11 additions & 3 deletions sprs-ldl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

name = "sprs-ldl"
description = "Sparse cholesky factorization"
version = "0.6.1"
version = "0.7.0"
authors = ["Vincent Barrielle"]
edition = "2018"

Expand All @@ -18,10 +18,18 @@ num-traits = "0.1.32"


[dependencies.sprs]
version = "0.8.0"
version = "0.9.0"
path = ".."

[dependencies.sprs_suitesparse_ldl]
version = "0.4.0"
version = "0.5.0"
path = "../suitesparse_bindings/sprs_suitesparse_ldl"
optional = true

[dependencies.sprs_suitesparse_camd]
version = "0.1.0"
path = "../suitesparse_bindings/sprs_suitesparse_camd"
optional = true

[dev-dependencies]
ndarray = ">=0.11.0,<0.14"
58 changes: 56 additions & 2 deletions sprs-ldl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,22 @@ impl Ldl {
pub fn perm<N, I>(&self, mat: CsMatViewI<N, I>) -> PermOwnedI<I>
where
I: SpIndex,
N: Copy + PartialEq,
{
match self.fill_red_method {
FillInReduction::NoReduction => PermOwnedI::identity(mat.rows()),
FillInReduction::ReverseCuthillMcKee => {
sprs::linalg::reverse_cuthill_mckee(mat).perm
sprs::linalg::reverse_cuthill_mckee(mat.structure_view()).perm
}
FillInReduction::CAMDSuiteSparse => {
#[cfg(not(feature = "sprs_suitesparse_camd"))]
panic!("Unavailable without the `sprs_suitesparse_camd` feature");
#[cfg(feature = "sprs_suitesparse_camd")]
sprs_suitesparse_camd::camd(mat.structure_view())
}
_ => {
unreachable!(
"Unhandled method, report a bug at https://github.com/vbarrielle/sprs/issues/199"
)
}
}
}
Expand Down Expand Up @@ -861,4 +871,48 @@ mod test {
let x = ldlt.solve(&b);
assert_eq!(x, x0);
}

#[cfg(feature = "sprs_suitesparse_camd")]
#[test]
fn camd_ldl_solve() {
// 0 - A - 2 - 3
// | \ | \ | / |
// 7 - 5 - 6 - 4
// | / | / | \ |
// 8 - 9 - 1 - E
#[rustfmt::skip]
let triangles = ndarray::arr2(
&[[0, 7, 5],
[0, 5, 10],
[10, 5, 6],
[10, 6, 2],
[2, 6, 3],
[3, 6, 4],
[7, 8, 5],
[5, 8, 9],
[5, 9, 6],
[6, 9, 1],
[6, 1, 11],
[6, 11, 4]],
);
let lap_mat =
sprs::special_mats::tri_mesh_graph_laplacian(12, triangles.view());
let ldlt_camd = super::Ldl::new()
.check_symmetry(super::SymmetryCheck::DontCheckSymmetry)
.fill_in_reduction(super::FillInReduction::CAMDSuiteSparse)
.numeric(lap_mat.view())
.unwrap();
let ldlt_cuthill = super::Ldl::new()
.check_symmetry(super::SymmetryCheck::DontCheckSymmetry)
.fill_in_reduction(super::FillInReduction::ReverseCuthillMcKee)
.numeric(lap_mat.view())
.unwrap();
let ldlt_raw = super::Ldl::new()
.check_symmetry(super::SymmetryCheck::DontCheckSymmetry)
.fill_in_reduction(super::FillInReduction::NoReduction)
.numeric(lap_mat.view())
.unwrap();
assert!(ldlt_camd.nnz() < ldlt_raw.nnz());
assert!(ldlt_camd.nnz() < ldlt_cuthill.nnz());
}
}
4 changes: 2 additions & 2 deletions sprs-rand/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "sprs-rand"
description = "Random sparse matrix generation"
version = "0.1.0"
version = "0.2.0"
authors = ["Vincent Barrielle <[email protected]>"]
license = "MIT OR Apache-2.0"
edition = "2018"
Expand All @@ -13,5 +13,5 @@ rand_distr = "0.2.2"
rand_pcg = "0.2.1"

[dependencies.sprs]
version = "0.8.0"
version = "0.9.0"
path = ".."
9 changes: 6 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,10 @@ pub use crate::sparse::{
csmat::CsIter, csmat::OuterIterator, csmat::OuterIteratorMut,
csmat::OuterIteratorPerm, kronecker::kronecker_product, CsMat, CsMatBase,
CsMatI, CsMatVecView, CsMatView, CsMatViewI, CsMatViewMut, CsMatViewMutI,
CsVec, CsVecBase, CsVecI, CsVecView, CsVecViewI, CsVecViewMut,
CsVecViewMutI, SparseMat, TriMat, TriMatBase, TriMatI, TriMatIter,
TriMatView, TriMatViewI, TriMatViewMut, TriMatViewMutI,
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;
Expand Down Expand Up @@ -152,9 +153,11 @@ pub use PermutationCheck::*;

/// The different kinds of fill-in-reduction algorithms supported by sprs
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[non_exhaustive]
pub enum FillInReduction {
NoReduction,
ReverseCuthillMcKee,
CAMDSuiteSparse,
}

#[cfg(feature = "approx")]
Expand Down
14 changes: 10 additions & 4 deletions src/sparse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ pub type CsMatViewMut<'a, N> = CsMatViewMutI<'a, N, usize>;
// FIXME: a fixed size array would be better, but no Deref impl
pub type CsMatVecView<'a, N> = CsMatVecView_<'a, N, usize>;

pub type CsStructureViewI<'a, I, Iptr = I> = CsMatViewI<'a, (), I, Iptr>;
pub type CsStructureView<'a> = CsStructureViewI<'a, usize>;
pub type CsStructureI<I, Iptr = I> = CsMatI<(), I, Iptr>;
pub type CsStructure = CsStructureI<usize>;

/// A sparse vector, storing the indices of its non-zero data.
///
/// A `CsVec` represents a sparse vector by storing a sorted `indices()` array
Expand Down Expand Up @@ -235,10 +240,11 @@ pub struct TriMatIter<RI, CI, DI> {
mod prelude {
pub use super::{
CsMat, CsMatBase, CsMatI, CsMatVecView, CsMatVecView_, CsMatView,
CsMatViewI, CsMatViewMut, CsMatViewMutI, CsVec, CsVecBase, CsVecI,
CsVecView, CsVecViewI, CsVecViewMut, CsVecViewMutI, SparseMat, TriMat,
TriMatBase, TriMatI, TriMatIter, TriMatView, TriMatViewI,
TriMatViewMut, TriMatViewMutI,
CsMatViewI, CsMatViewMut, CsMatViewMutI, CsStructure, CsStructureI,
CsStructureView, CsStructureViewI, CsVec, CsVecBase, CsVecI, CsVecView,
CsVecViewI, CsVecViewMut, CsVecViewMutI, SparseMat, TriMat, TriMatBase,
TriMatI, TriMatIter, TriMatView, TriMatViewI, TriMatViewMut,
TriMatViewMutI,
};
}

Expand Down
22 changes: 22 additions & 0 deletions src/sparse/csmat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,28 @@ where
}
}

pub fn structure_view(&self) -> CsStructureViewI<I, Iptr> {
// Safety: std::slice::from_raw_parts requires its passed
// pointer to be valid for the whole length of the slice. We have a
// zero-sized type, so the length is zero, and since we cast
// a non-null pointer, the pointer is valid as all pointers to zero-sized
// types are valid if they are not null.
let zst_data = unsafe {
std::slice::from_raw_parts(
self.data.as_ptr() as *const (),
self.data.len(),
)
};
CsStructureViewI {
storage: self.storage,
nrows: self.nrows,
ncols: self.ncols,
indptr: &self.indptr[..],
indices: &self.indices[..],
data: zst_data,
}
}

pub fn to_dense(&self) -> Array<N, Ix2>
where
N: Clone + Zero,
Expand Down
1 change: 1 addition & 0 deletions suitesparse_bindings/sprs_suitesparse_camd/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target/
17 changes: 17 additions & 0 deletions suitesparse_bindings/sprs_suitesparse_camd/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "sprs_suitesparse_camd"
description = "sprs bindings to the suitesparse camd fill-in reducting ordering"
version = "0.1.0"
authors = ["Vincent Barrielle <[email protected]>"]
edition = "2018"
keywords = ["sparse", "matrix", "fill-in", "permutation", "suitesparse"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies.sprs]
version = "0.9.0"
path = "../.."

[dependencies.suitesparse_camd_sys]
path = "../suitesparse_camd_sys/"
version = "0.1.0"
Loading