update loading matrix market, including:

1. Several renamings
2. removed unnecessary traits
3. added support for dense matrix
4. removed unnecessary comparison when reading data line by line. (e.g.
   only read header line once)
This commit is contained in:
Hantao Hui 2021-11-17 16:32:57 +01:00
parent 7f9128c92d
commit 332fe8c0e4
4 changed files with 1031 additions and 444 deletions

View File

@ -1,9 +1,8 @@
WHITESPACE = _{ " " } WHITESPACE = _{ " "|"\t" }
// //
// dense matrix(array) not supported here Sparsity = {^"coordinate" | ^"array"}
Sparsity = {^"coordinate"}
DataType = {^"real" | ^"complex" | ^"pattern" | ^"integer" } DataType = {^"real" | ^"complex" | ^"pattern" | ^"integer" }
StorageScheme = {^"symmetric" | ^"general" | ^"skew-symmetric" | ^"hermitian"} StorageScheme = {^"symmetric" | ^"general" | ^"skew-symmetric" | ^"hermitian"}
// Only consider matrices here. // Only consider matrices here.
@ -16,7 +15,9 @@ Comments = _{ "%" ~ (!NEWLINE ~ ANY)* }
// //
Dimension = @{ ASCII_DIGIT+ } Dimension = @{ ASCII_DIGIT+ }
Shape = { Dimension ~ Dimension ~ Dimension } SparseShape = { Dimension ~ Dimension ~ Dimension}
DenseShape = { Dimension ~ Dimension}
Shape = {SparseShape | DenseShape }
// //
@ -25,14 +26,21 @@ Shape = { Dimension ~ Dimension ~ Dimension }
Sign = {("+" | "-")} Sign = {("+" | "-")}
Exp = @{ ^"e" ~ Sign? ~ ASCII_DIGIT+} Exp = @{ ^"e" ~ Sign? ~ ASCII_DIGIT+}
Number = @{ ((ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT*) | (ASCII_DIGIT* ~ "." ~ASCII_DIGIT+) | ASCII_DIGIT+ ) ~ Exp? } Number = @{ ((ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT*) | (ASCII_DIGIT* ~ "." ~ASCII_DIGIT+) | ASCII_DIGIT+ ) ~ Exp? }
Value = @{ Sign? ~ ("inf" | "NaN" | Number) } Real = @{ Sign? ~ ("inf" | "NaN" | Number) }
// zero value: pattern
// one Value: real or int number
// two values: complex number
Entry = { Dimension ~ Dimension ~ Value? ~ Value? }
// SparseReal = {Dimension~ Dimension~ Real }
SparseComplex = {Dimension ~ Dimension ~ Real ~ Real}
SparsePattern = {Dimension ~ Dimension}
DenseReal = {Real}
DenseComplex = {Real ~ Real}
Entry = { SparseComplex | SparseReal | SparsePattern | DenseComplex | DenseReal }
// end of file, a silent way, see https://github.com/pest-parser/pest/issues/304#issuecomment-427198507
eoi = _{ !ANY }
Document = { Document = {
SOI ~ SOI ~
@ -40,5 +48,6 @@ Document = {
Header ~ Header ~
(NEWLINE ~ Comments)* ~ (NEWLINE ~ Comments)* ~
(NEWLINE ~ Shape) ~ (NEWLINE ~ Shape) ~
(NEWLINE ~ Entry?)* (NEWLINE ~ Entry?)* ~
eoi
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,10 @@
//! Parsers for various matrix formats. //! Parsers for various matrix formats.
//! //!
//! Use mm(or MM) to represent matrix market. //! ## Matrix Market
//! See the [website](https://math.nist.gov/MatrixMarket/formats.html) or the [paper](https://www.researchgate.net/publication/2630533_The_Matrix_Market_Exchange_Formats_Initial_Design) for more details about matrix market.
pub use self::matrix_market::{ pub use self::matrix_market::{
load_coo_from_mm_file, load_coo_from_mm_str, MMError, MMErrorKind, MMType, load_coo_from_matrix_market_file, load_coo_from_matrix_market_str, MatrixMarketError,
MatrixMarketErrorKind, MatrixMarketScalar,
}; };
mod matrix_market; mod matrix_market;

View File

@ -1,12 +1,12 @@
use matrixcompare::assert_matrix_eq; use matrixcompare::assert_matrix_eq;
use nalgebra::dmatrix; use nalgebra::dmatrix;
use nalgebra::Complex; use nalgebra::Complex;
use nalgebra_sparse::io::load_coo_from_mm_str; use nalgebra_sparse::io::load_coo_from_matrix_market_str;
use nalgebra_sparse::CooMatrix; use nalgebra_sparse::CooMatrix;
#[test] #[test]
#[rustfmt::skip] #[rustfmt::skip]
fn test_mm_sparse_real_general() { fn test_matrixmarket_sparse_real_general() {
let file_str = r#" let file_str = r#"
%%MatrixMarket matrix CoOrdinate real general %%MatrixMarket matrix CoOrdinate real general
% This is also an example of free-format features. % This is also an example of free-format features.
@ -33,15 +33,26 @@ fn test_mm_sparse_real_general() {
%================================================================================= %=================================================================================
5 5 8 5 5 8
1 1 1 1 1 1
2 2 1.050e+01 2 2 1.050e+01
3 3 1.500e-02 3 3 1.500e-02
1 4 6.000e+00 1 4 6.000e+00
4 2 2.505e+02 4 2 2.505e+02
4 4 -2.800e+02 4 4 -2.800e+02
4 5 3.332e+01 4 5 3.332e+01
5 5 1.200e+01 5 5 1.200e+01
"#; "#;
let sparse_mat = load_coo_from_mm_str::<f32>(file_str).unwrap(); let sparse_mat = load_coo_from_matrix_market_str::<f32>(file_str).unwrap();
let expected = dmatrix![ let expected = dmatrix![
1.0, 0.0, 0.0, 6.0, 0.0; 1.0, 0.0, 0.0, 6.0, 0.0;
0.0, 10.5, 0.0, 0.0, 0.0; 0.0, 10.5, 0.0, 0.0, 0.0;
@ -54,7 +65,7 @@ fn test_mm_sparse_real_general() {
#[test] #[test]
#[rustfmt::skip] #[rustfmt::skip]
fn test_mm_sparse_int_symmetric() { fn test_matrixmarket_sparse_int_symmetric() {
let file_str = r#" let file_str = r#"
%%MatrixMarket matrix coordinate integer symmetric %%MatrixMarket matrix coordinate integer symmetric
% %
@ -69,7 +80,7 @@ fn test_mm_sparse_int_symmetric() {
5 3 35 5 3 35
5 5 55 5 5 55
"#; "#;
let sparse_mat = load_coo_from_mm_str::<i32>(file_str).unwrap(); let sparse_mat = load_coo_from_matrix_market_str::<i128>(file_str).unwrap();
let expected = dmatrix![ let expected = dmatrix![
11, 0, 0, 0, -15; 11, 0, 0, 0, -15;
0, 22, 23, 24, 0; 0, 22, 23, 24, 0;
@ -82,7 +93,7 @@ fn test_mm_sparse_int_symmetric() {
#[test] #[test]
#[rustfmt::skip] #[rustfmt::skip]
fn test_mm_sparse_complex_hermitian() { fn test_matrixmarket_sparse_complex_hermitian() {
let file_str = r#" let file_str = r#"
%%MatrixMarket matrix coordinate complex hermitian %%MatrixMarket matrix coordinate complex hermitian
% %
@ -96,7 +107,7 @@ fn test_mm_sparse_complex_hermitian() {
5 4 0.0 33.32 5 4 0.0 33.32
"#; "#;
let sparse_mat = load_coo_from_mm_str::<Complex<f64>>(file_str).unwrap(); let sparse_mat = load_coo_from_matrix_market_str::<Complex<f64>>(file_str).unwrap();
let expected = dmatrix![ let expected = dmatrix![
Complex::<f64>{re:1.0,im:0.0}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:0.0,im:0.0},Complex::<f64>{re:0.0,im:0.0}; Complex::<f64>{re:1.0,im:0.0}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:0.0,im:0.0},Complex::<f64>{re:0.0,im:0.0};
Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:10.5,im:0.0}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:250.5,im:-22.22},Complex::<f64>{re:0.0,im:0.0}; Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:10.5,im:0.0}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:250.5,im:-22.22},Complex::<f64>{re:0.0,im:0.0};
@ -109,7 +120,7 @@ fn test_mm_sparse_complex_hermitian() {
#[test] #[test]
#[rustfmt::skip] #[rustfmt::skip]
fn test_mm_sparse_real_skew() { fn test_matrixmarket_sparse_real_skew() {
let file_str = r#" let file_str = r#"
%%MatrixMarket matrix coordinate real skew-symmetric %%MatrixMarket matrix coordinate real skew-symmetric
% %
@ -119,7 +130,7 @@ fn test_mm_sparse_real_skew() {
5 1 -15.0 5 1 -15.0
5 3 -35.0 5 3 -35.0
"#; "#;
let sparse_mat = load_coo_from_mm_str::<f64>(file_str).unwrap(); let sparse_mat = load_coo_from_matrix_market_str::<f64>(file_str).unwrap();
let expected = dmatrix![ let expected = dmatrix![
0.0, 0.0, 0.0, 0.0, 15.0; 0.0, 0.0, 0.0, 0.0, 15.0;
0.0, 0.0, 23.0, 24.0, 0.0; 0.0, 0.0, 23.0, 24.0, 0.0;
@ -132,7 +143,7 @@ fn test_mm_sparse_real_skew() {
#[test] #[test]
#[rustfmt::skip] #[rustfmt::skip]
fn test_mm_sparse_pattern_general() { fn test_matrixmarket_sparse_pattern_general() {
let file_str = r#" let file_str = r#"
%%MatrixMarket matrix coordinate pattern general %%MatrixMarket matrix coordinate pattern general
% %
@ -148,7 +159,7 @@ fn test_mm_sparse_pattern_general() {
5 4 5 4
5 5 5 5
"#; "#;
let pattern_matrix = load_coo_from_mm_str::<()>(file_str).unwrap(); let pattern_matrix = load_coo_from_matrix_market_str::<()>(file_str).unwrap();
let nrows = pattern_matrix.nrows(); let nrows = pattern_matrix.nrows();
let ncols = pattern_matrix.ncols(); let ncols = pattern_matrix.ncols();
let (row_idx, col_idx, val) = pattern_matrix.disassemble(); let (row_idx, col_idx, val) = pattern_matrix.disassemble();
@ -163,3 +174,136 @@ fn test_mm_sparse_pattern_general() {
]; ];
assert_matrix_eq!(sparse_mat, expected); assert_matrix_eq!(sparse_mat, expected);
} }
#[test]
#[rustfmt::skip]
fn test_matrixmarket_dense_real_general() {
let file_str = r#"
%%MatrixMarket matrix array real general
%
4 3
1.0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0
10.0
11.0
12.0
"#;
let sparse_mat = load_coo_from_matrix_market_str::<f32>(file_str).unwrap();
let expected = dmatrix![
1.0, 5.0, 9.0;
2.0, 6.0, 10.0;
3.0, 7.0, 11.0;
4.0, 8.0, 12.0;
];
assert_matrix_eq!(sparse_mat, expected);
}
#[test]
#[rustfmt::skip]
fn test_matrixmarket_dense_real_symmetric() {
let file_str = r#"
%%MatrixMarket matrix array real symmetric
%
4 4
1.0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0
10.0
"#;
let sparse_mat = load_coo_from_matrix_market_str::<f32>(file_str).unwrap();
let expected = dmatrix![
1.0, 2.0, 3.0, 4.0;
2.0, 5.0, 6.0, 7.0;
3.0, 6.0, 8.0, 9.0;
4.0, 7.0, 9.0, 10.0;
];
assert_matrix_eq!(sparse_mat, expected);
}
#[test]
#[rustfmt::skip]
fn test_matrixmarket_dense_complex_hermitian() {
let file_str = r#"
%%MatrixMarket matrix array complex hermitian
%
4 4
1.0 0.0
2.0 2.0
3.0 3.0
4.0 4.0
5.0 0.0
6.0 6.0
7.0 7.0
8.0 0.0
9.0 9.0
10.0 0.0
"#;
let sparse_mat = load_coo_from_matrix_market_str::<Complex<f64>>(file_str).unwrap();
let expected = dmatrix![
Complex::<f64>{re:1.0,im:0.0}, Complex::<f64>{re:2.0,im:-2.0} ,Complex::<f64>{re:3.0,im:-3.0} ,Complex::<f64>{re:4.0,im:-4.0};
Complex::<f64>{re:2.0,im:2.0}, Complex::<f64>{re:5.0,im:0.0} ,Complex::<f64>{re:6.0,im:-6.0} ,Complex::<f64>{re:7.0,im:-7.0};
Complex::<f64>{re:3.0,im:3.0}, Complex::<f64>{re:6.0,im:6.0} ,Complex::<f64>{re:8.0,im:0.0} ,Complex::<f64>{re:9.0,im:-9.0};
Complex::<f64>{re:4.0,im:4.0}, Complex::<f64>{re:7.0,im:7.0} ,Complex::<f64>{re:9.0,im:9.0} ,Complex::<f64>{re:10.0,im:0.0};
];
assert_matrix_eq!(sparse_mat, expected);
}
#[test]
#[rustfmt::skip]
fn test_matrixmarket_dense_int_skew() {
let file_str = r#"
%%MatrixMarket matrix array integer skew-symmetric
%
4 4
1
2
3
4
5
6
"#;
let sparse_mat = load_coo_from_matrix_market_str::<i32>(file_str).unwrap();
let expected = dmatrix![
0,-1,-2,-3;
1, 0,-4,-5;
2, 4, 0,-6;
3, 5, 6, 0;
];
assert_matrix_eq!(sparse_mat, expected);
}
#[test]
#[rustfmt::skip]
fn test_matrixmarket_dense_complex_general() {
let file_str = r#"
%%MatrixMarket matrix array complex general
%
2 2
1 0
1 0
1 0
1 0
"#;
let sparse_mat = load_coo_from_matrix_market_str::<Complex<f32>>(file_str).unwrap();
let expected = dmatrix![
Complex::<f32>{re:1.0,im:0.0},Complex::<f32>{re:1.0,im:0.0};
Complex::<f32>{re:1.0,im:0.0},Complex::<f32>{re:1.0,im:0.0};
];
assert_matrix_eq!(sparse_mat, expected);
}