# Binary matrix Compressed Sparse Vector library.
[](https://crates.io/crates/csvbinmatrix)
[](https://gitlab.com/vepain/csvbinmatrix-rust/-/commits/main)
[](https://gitlab.com/vepain/csvbinmatrix-rust/-/commits/main)
[](https://docs.rs/csvbinmatrix/latest/csvbinmatrix/)
🦀 Rust package for binary matrices represented in the Compressed Sparse Vector (CSV) format.
* [Quick usage](#quick-usage)
* [Submatrices](#submatrices)
* [Easy way, but costly](#easy-way-but-costly)
* [Efficiently producing submatrices](#efficiently-producing-submatrices)
* [With boolean vectors](#with-boolean-vectors)
* [With closures](#with-closures)
* [The CSVBM file format for CSV binary matrices](#the-csvbm-file-format-for-csv-binary-matrices)
* [Recent Changes](#recent-changes)
* [License](#license)
* [References](#references)
[`BinCSV`] is the main structure and maintains the CSV format which is suitable for sparse matrices.
Learn more in the [References](#references) section.
[`BinCSV`]: crate::bincsv::BinCSV
## Quick usage
```rust
# fn quick_usage() -> Result<(), Box<dyn std::error::Error>> {
use csvbinmatrix::bincsv::BinCSV;
let matrix = BinCSV::from_u8_rows(&vec![
vec![0, 0, 0],
vec![0, 0, 1],
vec![0, 1, 1],
vec![1, 1, 1],
]);
println!("Number of rows: {}", matrix.number_of_rows());
println!("Number of columns: {}", matrix.number_of_columns());
println!("Number of ones: {}", matrix.number_of_ones());
println!("Number of zeros: {}", matrix.number_of_zeros());
matrix.write_to_file("mymatrix.csvbm")?;
// DOCU write to file but consume
assert_eq!(BinCSV::read_from_file("mymatrix.csvbm")?, matrix);
std::fs::remove_file("mymatrix.csvbm")?;
# Ok(())
# }
```
You may be interested in the [`to_file`](crate::bincsv::BinCSV::to_file) method to write the corresponding CSVBM file.
See also the [CSVBM file format](#the-csvbm-file-format-for-csv-binary-matrices) section.
## Submatrices
### Easy way, but costly
```rust
use csvbinmatrix::bincsv::{BinCSV, SubBinCSV};
use csvbinmatrix::filters::ClosureDimensionFilter;
let matrix = BinCSV::from_u8_rows(&vec![
vec![0, 0, 0],
vec![0, 0, 1],
vec![0, 1, 1],
vec![1, 1, 1],
]);
let row_filter = ClosureDimensionFilter::new(|i| i != 1);
let column_filter = ClosureDimensionFilter::new(|j| j != 0);
let expected_sub_matrix = SubBinCSV::Normal(BinCSV::from_u8_rows(&vec![
vec![0, 0],
vec![1, 1],
vec![1, 1],
]));
// Generate submatrices according to the couples of row and column filters.
// `matrix` is consumed.
assert_eq!(
matrix.submatrix(&row_filter, &column_filter),
expected_sub_matrix
);
```
### Efficiently producing submatrices
Say we would like to have a submatrix of `bin_csv` without the second row and the first column.
```txt
1 1
1 1
0 0
```
The two following subsections show how to obtain an efficient submatrix while consuming the super binary matrix with the [`to_reversed_sub_binmatrices`] method.
The memory and the time complexities are linear according to the number ones of the super binary matrix.
This efficiency is at the cost of reversing the rows and the columns of the submatrix.
You can retrieving the row and the column orders with the [`reverse`] method.
[`to_reversed_sub_binmatrices`]: crate::bincsv::BinCSV::to_reversed_sub_binmatrices
[`reverse`]: crate::bincsv::BinCSV::reverse
#### With boolean vectors
```rust
use csvbinmatrix::bincsv::{BinCSV, SubBinCSV};
use csvbinmatrix::filters::BoolVecDimensionFilter;
let matrix = BinCSV::from_u8_rows(&vec![
vec![0, 0, 0],
vec![0, 0, 1],
vec![0, 1, 1],
vec![1, 1, 1],
]);
let row_filter =
BoolVecDimensionFilter::new(vec![true, false, true, true], matrix.number_of_rows());
let column_filter =
BoolVecDimensionFilter::new(vec![false, true, true], matrix.number_of_columns());
let expected_sub_matrix = SubBinCSV::Normal(BinCSV::from_u8_rows(&vec![
vec![1, 1],
vec![1, 1],
vec![0, 0],
]));
// Generate submatrices according to the couples of row and column filters.
// `matrix` is consumed.
let mut sub_matrices = matrix.to_reversed_sub_binmatrices(vec![(&row_filter, &column_filter)]);
assert_eq!(sub_matrices.pop(), Some(expected_sub_matrix));
assert_eq!(sub_matrices.pop(), None);
// You can drop the row and column filters and take the ownership of the boolean vectors.
let boolvec_row = row_filter.to_boolean_vector();
let boolvec_column = column_filter.to_boolean_vector();
println!("Boolean vector for the rows: {boolvec_row:?}");
println!("Boolean vector for the columns: {boolvec_column:?}");
```
#### With closures
```rust
use csvbinmatrix::bincsv::{BinCSV, SubBinCSV};
use csvbinmatrix::filters::ClosureDimensionFilter;
let matrix = BinCSV::from_u8_rows(&vec![
vec![0, 0, 0],
vec![0, 0, 1],
vec![0, 1, 1],
vec![1, 1, 1],
]);
let row_filter = ClosureDimensionFilter::new(|i| i != 1);
let column_filter = ClosureDimensionFilter::new(|j| j != 0);
let expected_sub_matrix = SubBinCSV::Normal(BinCSV::from_u8_rows(&vec![
vec![1, 1],
vec![1, 1],
vec![0, 0],
]));
// Generate submatrices according to the couples of row and column filters.
// `matrix` is consumed.
let mut sub_matrices = matrix.to_reversed_sub_binmatrices(vec![(&row_filter, &column_filter)]);
assert_eq!(sub_matrices.pop(), Some(expected_sub_matrix));
assert_eq!(sub_matrices.pop(), None);
```
## The CSVBM file format for CSV binary matrices
The CSVBM format is as follows:
```text
number_of_rows number_of_columns number_of_ones
distance
distance
...
distance
```
In our example matrix, the file is:
```text
4 3 6
5
2
1
1
1
1
```
## Recent Changes
See `CHANGELOG.md`.
## License
Dual-licensed to be compatible with the Rust project.
Licensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be copied, modified, or distributed except according to those terms.
## References
This package is based on this paper, where the authors' method is adapted for binary matrices:
> Farzaneh, Aiyoub, Hossein Kheırı, et Mehdi Abbaspour Shahmersı. « AN EFFICIENT STORAGE FORMAT FOR LARGE SPARSE MATRICES ». Communications Faculty of Sciences University of Ankara Series A1 Mathematics and Statistics 58, nᵒ 2 (1 août 2009): 1‑10. <https://doi.org/10.1501/Commua1_0000000648>.