use nalgebra::DMatrix;
use nalgebra_block_triangularization::adjacency::{
build_row_adjacency, build_row_dependency_graph,
};
#[test]
fn adjacency_empty_matrix() {
let m: DMatrix<u8> = DMatrix::zeros(0, 0);
let adj = build_row_adjacency(&m);
assert_eq!(adj.len(), 0);
}
#[test]
fn adjacency_zero_rows() {
let m: DMatrix<u8> = DMatrix::zeros(0, 5);
let adj = build_row_adjacency(&m);
assert_eq!(adj.len(), 0);
}
#[test]
fn adjacency_zero_cols() {
let m: DMatrix<u8> = DMatrix::zeros(5, 0);
let adj = build_row_adjacency(&m);
assert_eq!(adj.len(), 5);
for row in adj {
assert!(row.is_empty());
}
}
#[test]
fn adjacency_single_element_zero() {
let m = DMatrix::from_element(1, 1, 0u8);
let adj = build_row_adjacency(&m);
assert_eq!(adj.len(), 1);
assert!(adj[0].is_empty());
}
#[test]
fn adjacency_single_element_nonzero() {
let m = DMatrix::from_element(1, 1, 1u8);
let adj = build_row_adjacency(&m);
assert_eq!(adj.len(), 1);
assert_eq!(adj[0], vec![0]);
}
#[test]
fn adjacency_all_zeros() {
let m: DMatrix<u8> = DMatrix::zeros(3, 4);
let adj = build_row_adjacency(&m);
assert_eq!(adj.len(), 3);
for row in adj {
assert!(row.is_empty());
}
}
#[test]
fn adjacency_all_ones() {
let m = DMatrix::from_element(3, 4, 1u8);
let adj = build_row_adjacency(&m);
assert_eq!(adj.len(), 3);
for row in &adj {
assert_eq!(row, &vec![0, 1, 2, 3]);
}
}
#[test]
fn adjacency_identity_matrix() {
let m: DMatrix<f64> = DMatrix::identity(5, 5);
let adj = build_row_adjacency(&m);
assert_eq!(adj.len(), 5);
for (i, row) in adj.iter().enumerate().take(5) {
assert_eq!(*row, vec![i]);
}
}
#[test]
fn adjacency_sparse_pattern() {
let m = DMatrix::from_row_slice(
4,
5,
&[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1],
);
let adj = build_row_adjacency(&m);
assert_eq!(adj[0], vec![0, 2, 4]);
assert_eq!(adj[1], vec![1, 3]);
assert_eq!(adj[2], vec![0, 1]);
assert_eq!(adj[3], vec![3, 4]);
}
#[test]
fn adjacency_sorted_and_deduped() {
let m = DMatrix::from_row_slice(2, 5, &[0, 0, 1, 1, 1, 1, 1, 0, 1, 0]);
let adj = build_row_adjacency(&m);
assert_eq!(adj[0], vec![2, 3, 4]);
assert_eq!(adj[1], vec![0, 1, 3]);
for row in &adj {
let mut sorted = row.clone();
sorted.sort_unstable();
assert_eq!(row, &sorted);
}
}
#[test]
fn dependency_graph_empty() {
let row_adj: Vec<Vec<usize>> = vec![];
let col_to_row: Vec<Option<usize>> = vec![];
let dep_graph = build_row_dependency_graph(&row_adj, &col_to_row);
assert_eq!(dep_graph.len(), 0);
}
#[test]
fn dependency_graph_no_matching() {
let row_adj = vec![vec![0, 1], vec![2, 3]];
let col_to_row = vec![None, None, None, None];
let dep_graph = build_row_dependency_graph(&row_adj, &col_to_row);
assert_eq!(dep_graph.len(), 2);
assert!(dep_graph[0].is_empty());
assert!(dep_graph[1].is_empty());
}
#[test]
fn dependency_graph_perfect_matching_diagonal() {
let row_adj = vec![vec![0], vec![1], vec![2]];
let col_to_row = vec![Some(0), Some(1), Some(2)];
let dep_graph = build_row_dependency_graph(&row_adj, &col_to_row);
assert_eq!(dep_graph.len(), 3);
assert!(dep_graph[0].is_empty());
assert!(dep_graph[1].is_empty());
assert!(dep_graph[2].is_empty());
}
#[test]
fn dependency_graph_with_dependencies() {
let row_adj = vec![vec![0, 1], vec![1, 2], vec![0, 2]];
let col_to_row = vec![Some(0), Some(1), Some(2)];
let dep_graph = build_row_dependency_graph(&row_adj, &col_to_row);
assert_eq!(dep_graph.len(), 3);
assert_eq!(dep_graph[0], vec![1]);
assert_eq!(dep_graph[1], vec![2]);
assert_eq!(dep_graph[2], vec![0]);
}
#[test]
fn dependency_graph_self_loop_excluded() {
let row_adj = vec![vec![0, 1]];
let col_to_row = vec![Some(0), None];
let dep_graph = build_row_dependency_graph(&row_adj, &col_to_row);
assert_eq!(dep_graph.len(), 1);
assert!(dep_graph[0].is_empty());
}
#[test]
fn dependency_graph_multiple_paths_to_same_row() {
let row_adj = vec![vec![0, 1, 2], vec![]];
let col_to_row = vec![Some(1), Some(1), Some(1)];
let dep_graph = build_row_dependency_graph(&row_adj, &col_to_row);
assert_eq!(dep_graph.len(), 2);
assert_eq!(dep_graph[0], vec![1]);
assert!(dep_graph[1].is_empty());
}
#[test]
fn dependency_graph_sorted() {
let row_adj = vec![vec![0, 1, 2, 3]];
let col_to_row = vec![Some(3), Some(1), Some(2), Some(0)];
let dep_graph = build_row_dependency_graph(&row_adj, &col_to_row);
assert_eq!(dep_graph.len(), 1);
assert_eq!(dep_graph[0], vec![1, 2, 3]);
}
#[test]
fn dependency_graph_unmatched_columns_ignored() {
let row_adj = vec![vec![0, 1, 2], vec![1, 3]];
let col_to_row = vec![Some(0), None, None, Some(1)];
let dep_graph = build_row_dependency_graph(&row_adj, &col_to_row);
assert_eq!(dep_graph.len(), 2);
assert!(dep_graph[0].is_empty());
assert!(dep_graph[1].is_empty());
}