use crate::{
containers::maps::MapTrait,
conversions::FromGraph,
graph::{Graph, GraphError, GraphWithMutableEdges, GraphWithMutableNodes, NodeIndex},
};
pub struct BitMapMatrix<const N: usize, const R: usize, NI, M>
where
NI: NodeIndex,
M: MapTrait<NI, usize>,
{
bitmap: super::bit_matrix::BitMatrix<N, R>,
index_map: M,
phantom: core::marker::PhantomData<NI>,
}
impl<const N: usize, const R: usize, NI, M> BitMapMatrix<N, R, NI, M>
where
NI: NodeIndex,
M: MapTrait<NI, usize>,
{
pub fn new(
bitmap: super::bit_matrix::BitMatrix<N, R>,
index_map: M,
) -> Result<Self, GraphError<NI>> {
let max_valid_index = 8 * N;
for (node, idx) in index_map.iter() {
if *idx >= max_valid_index {
return Err(GraphError::IndexOutOfBounds(*idx, *node));
}
}
Ok(Self::new_unchecked(bitmap, index_map))
}
pub fn new_unchecked(bitmap: super::bit_matrix::BitMatrix<N, R>, index_map: M) -> Self {
Self {
bitmap,
index_map,
phantom: core::marker::PhantomData,
}
}
}
impl<const N: usize, const R: usize, NI, M> FromGraph<NI, GraphError<NI>>
for BitMapMatrix<N, R, NI, M>
where
NI: NodeIndex + Copy,
M: MapTrait<NI, usize> + Default,
{
fn from_graph<G>(source_graph: &G) -> Result<Self, GraphError<NI>>
where
G: Graph<NI>,
GraphError<NI>: From<G::Error>,
{
let mut index_map = M::default();
let max_index = 8 * N;
match source_graph.iter_nodes() {
Ok(nodes_iter) => {
for (matrix_index, node) in nodes_iter.enumerate() {
if matrix_index >= max_index {
return Err(GraphError::OutOfCapacity);
}
index_map
.insert(node, matrix_index)
.map_err(|_| GraphError::OutOfCapacity)?;
}
}
Err(err) => {
let graph_error = GraphError::from(err);
match graph_error {
GraphError::OutOfCapacity => {
}
other_error => {
return Err(other_error);
}
}
}
}
let mut bitmap = super::bit_matrix::BitMatrix::<N, R>::new([[0u8; N]; R])
.map_err(|_| GraphError::InvalidMatrixSize)?;
if let Ok(edges_iter) = source_graph.iter_edges() {
for (src, dst) in edges_iter {
if let (Some(&src_idx), Some(&dst_idx)) = (index_map.get(&src), index_map.get(&dst))
{
bitmap
.add_edge(src_idx, dst_idx)
.map_err(|_| GraphError::OutOfCapacity)?;
}
}
}
Ok(Self::new_unchecked(bitmap, index_map))
}
}
impl<const N: usize, const R: usize, NI, M> Graph<NI> for BitMapMatrix<N, R, NI, M>
where
NI: NodeIndex,
M: MapTrait<NI, usize>,
{
type Error = GraphError<NI>;
fn iter_nodes(&self) -> Result<impl Iterator<Item = NI>, Self::Error> {
Ok(self.index_map.iter().map(|(&k, _)| k))
}
fn contains_node(&self, node: NI) -> Result<bool, Self::Error> {
Ok(self.index_map.contains_key(&node))
}
fn iter_edges(&self) -> Result<impl Iterator<Item = (NI, NI)>, Self::Error> {
Ok(self
.index_map
.iter()
.flat_map(move |(&from_node, &from_idx)| {
self.index_map
.iter()
.filter_map(move |(&to_node, &to_idx)| {
if self.bitmap.get(from_idx, to_idx) {
Some((from_node, to_node))
} else {
None
}
})
}))
}
fn outgoing_edges(&self, node: NI) -> Result<impl Iterator<Item = NI>, Self::Error> {
let matrix_idx = self.index_map.get(&node).copied();
let outgoing = self
.bitmap
.outgoing_edges(matrix_idx.unwrap_or(usize::MAX))
.map_err(|_| GraphError::NodeNotFound(node))?;
Ok(outgoing
.filter(move |_| matrix_idx.is_some()) .filter_map(move |target_idx| {
self.index_map
.iter()
.find(|(_, &idx)| idx == target_idx)
.map(|(&node, _)| node)
}))
}
fn incoming_edges(&self, node: NI) -> Result<impl Iterator<Item = NI>, Self::Error> {
let matrix_idx = self.index_map.get(&node).copied();
let incoming = self
.bitmap
.incoming_edges(matrix_idx.unwrap_or(usize::MAX))
.map_err(|_| GraphError::NodeNotFound(node))?;
Ok(incoming
.filter(move |_| matrix_idx.is_some()) .filter_map(move |source_idx| {
self.index_map
.iter()
.find(|(_, &idx)| idx == source_idx)
.map(|(&node, _)| node)
}))
}
}
impl<const N: usize, const R: usize, NI, M> GraphWithMutableNodes<NI> for BitMapMatrix<N, R, NI, M>
where
NI: NodeIndex,
M: MapTrait<NI, usize>,
{
fn add_node(&mut self, node: NI) -> Result<(), Self::Error> {
if self.index_map.contains_key(&node) {
return Err(GraphError::DuplicateNode(node));
}
let max_index = 8 * N;
let unused_index = (0..max_index)
.find(|&idx| !self.index_map.iter().any(|(_, &used_idx)| used_idx == idx))
.ok_or(GraphError::OutOfCapacity)?;
self.index_map
.insert(node, unused_index)
.map_err(|_| GraphError::OutOfCapacity)?;
Ok(())
}
fn remove_node(&mut self, node: NI) -> Result<(), Self::Error> {
if !self.index_map.contains_key(&node) {
return Err(GraphError::NodeNotFound(node));
}
if self.incoming_edges(node)?.next().is_some() {
return Err(GraphError::NodeHasIncomingEdges(node));
}
if self.outgoing_edges(node)?.next().is_some() {
return Err(GraphError::NodeHasOutgoingEdges(node));
}
self.index_map.remove(&node);
Ok(())
}
}
impl<const N: usize, const R: usize, NI, M> GraphWithMutableEdges<NI> for BitMapMatrix<N, R, NI, M>
where
NI: NodeIndex,
M: MapTrait<NI, usize>,
{
fn add_edge(&mut self, source: NI, destination: NI) -> Result<(), Self::Error> {
let source_idx = self
.index_map
.get(&source)
.copied()
.ok_or(GraphError::EdgeHasInvalidNode(source))?;
let destination_idx = self
.index_map
.get(&destination)
.copied()
.ok_or(GraphError::EdgeHasInvalidNode(destination))?;
self.bitmap
.add_edge(source_idx, destination_idx)
.map_err(|err| match err {
GraphError::EdgeHasInvalidNode(_) => {
GraphError::EdgeHasInvalidNode(source)
}
GraphError::OutOfCapacity => GraphError::OutOfCapacity,
_ => GraphError::EdgeHasInvalidNode(source), })
}
fn remove_edge(&mut self, source: NI, destination: NI) -> Result<(), Self::Error> {
let source_idx = self
.index_map
.get(&source)
.copied()
.ok_or(GraphError::EdgeNotFound(source, destination))?;
let destination_idx = self
.index_map
.get(&destination)
.copied()
.ok_or(GraphError::EdgeNotFound(source, destination))?;
self.bitmap
.remove_edge(source_idx, destination_idx)
.map_err(|err| match err {
GraphError::EdgeNotFound(_, _) => {
GraphError::EdgeNotFound(source, destination)
}
_ => GraphError::EdgeNotFound(source, destination), })
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::containers::maps::staticdict::Dictionary;
use crate::edgelist::edge_list::EdgeList;
use crate::edges::EdgeStructOption;
use crate::graph::GraphWithMutableEdges;
use crate::tests::{collect, collect_sorted};
#[test]
fn test_bit_map_matrix_basic() {
let bits = [
[0b00000011u8], [0b00000001u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], ];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<char, usize, 8>::new();
index_map.insert('A', 0).unwrap();
index_map.insert('B', 1).unwrap();
let bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
let mut nodes = ['\0'; 8];
let nodes_slice = collect_sorted(bit_map_matrix.iter_nodes().unwrap(), &mut nodes);
assert_eq!(nodes_slice, &['A', 'B']);
assert!(bit_map_matrix.contains_node('A').unwrap());
assert!(bit_map_matrix.contains_node('B').unwrap());
assert!(!bit_map_matrix.contains_node('C').unwrap());
let mut outgoing_a = ['\0'; 8];
let outgoing_slice = collect(bit_map_matrix.outgoing_edges('A').unwrap(), &mut outgoing_a);
assert_eq!(outgoing_slice.len(), 2);
let mut outgoing_b = ['\0'; 8];
let outgoing_slice = collect(bit_map_matrix.outgoing_edges('B').unwrap(), &mut outgoing_b);
assert_eq!(outgoing_slice, &['A']); }
#[test]
fn test_bit_map_matrix_empty() {
let bits = [[0u8], [0u8], [0u8], [0u8], [0u8], [0u8], [0u8], [0u8]];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let index_map = Dictionary::<u32, usize, 8>::new();
let bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
assert_eq!(bit_map_matrix.iter_nodes().unwrap().count(), 0);
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 0);
assert!(!bit_map_matrix.contains_node(42).unwrap());
}
#[test]
fn test_bit_map_matrix_nonexistent_node() {
let bits = [
[0b00000001u8], [0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<u32, usize, 8>::new();
index_map.insert(100, 0).unwrap();
let bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
assert_eq!(bit_map_matrix.outgoing_edges(999).unwrap().count(), 0);
assert_eq!(bit_map_matrix.incoming_edges(999).unwrap().count(), 0);
}
#[test]
fn test_bit_map_matrix_incoming_edges() {
let bits = [
[0b00000011u8], [0b00000001u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], ];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<char, usize, 8>::new();
index_map.insert('A', 0).unwrap();
index_map.insert('B', 1).unwrap();
let bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
let mut incoming_a = ['\0'; 8];
let incoming_slice =
collect_sorted(bit_map_matrix.incoming_edges('A').unwrap(), &mut incoming_a);
assert_eq!(incoming_slice, &['A', 'B']);
let mut incoming_b = ['\0'; 8];
let incoming_slice = collect(bit_map_matrix.incoming_edges('B').unwrap(), &mut incoming_b);
assert_eq!(incoming_slice, &['A']); }
#[test]
fn test_bit_map_matrix_outgoing_edges_bounds() {
let bits = [
[0b00000011u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], [0b00000000u8], ];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<char, usize, 8>::new();
index_map.insert('A', 0).unwrap();
index_map.insert('B', 1).unwrap();
let bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
let mut outgoing = ['\0'; 8];
let outgoing_slice = collect(bit_map_matrix.outgoing_edges('C').unwrap(), &mut outgoing);
assert_eq!(outgoing_slice.len(), 0);
let mut outgoing = ['\0'; 8];
let outgoing_slice = collect(bit_map_matrix.outgoing_edges('D').unwrap(), &mut outgoing);
assert_eq!(outgoing_slice.len(), 0);
}
#[test]
fn test_add_node_to_empty_bit_matrix() {
let bits = [[0u8], [0u8], [0u8], [0u8], [0u8], [0u8], [0u8], [0u8]];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let index_map = Dictionary::<u32, usize, 10>::new();
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
bit_map_matrix.add_node(42).unwrap();
let mut nodes = [0u32; 2];
let nodes_slice = collect(bit_map_matrix.iter_nodes().unwrap(), &mut nodes);
assert_eq!(nodes_slice, &[42]);
assert_eq!(bit_map_matrix.outgoing_edges(42).unwrap().count(), 0);
}
#[test]
fn test_add_node_to_existing_bit_matrix() {
let bits = [
[0b00000001u8], [0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<char, usize, 10>::new();
index_map.insert('A', 0).unwrap();
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
bit_map_matrix.add_node('B').unwrap();
let mut nodes = ['\0'; 4];
let nodes_slice = collect_sorted(bit_map_matrix.iter_nodes().unwrap(), &mut nodes);
assert_eq!(nodes_slice, &['A', 'B']);
assert_eq!(bit_map_matrix.outgoing_edges('B').unwrap().count(), 0);
assert_eq!(bit_map_matrix.outgoing_edges('A').unwrap().count(), 1);
}
#[test]
fn test_add_duplicate_node_bit_matrix() {
let bits = [[0u8], [0u8], [0u8], [0u8], [0u8], [0u8], [0u8], [0u8]];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<u32, usize, 8>::new();
index_map.insert(100, 0).unwrap();
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
let result = bit_map_matrix.add_node(100);
assert!(matches!(result, Err(GraphError::DuplicateNode(100))));
let mut nodes = [0u32; 2];
let nodes_slice = collect(bit_map_matrix.iter_nodes().unwrap(), &mut nodes);
assert_eq!(nodes_slice, &[100]);
}
#[test]
fn test_add_node_capacity_exceeded_bit_matrix() {
let bits = [[0u8], [0u8], [0u8], [0u8], [0u8], [0u8], [0u8], [0u8]];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<u32, usize, 8>::new();
for i in 0..8 {
index_map.insert(i as u32, i).unwrap();
}
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
let result = bit_map_matrix.add_node(999);
assert!(matches!(result, Err(GraphError::OutOfCapacity)));
let mut nodes = [0u32; 10];
let nodes_slice = collect_sorted(bit_map_matrix.iter_nodes().unwrap(), &mut nodes);
assert_eq!(nodes_slice, &[0, 1, 2, 3, 4, 5, 6, 7]);
}
#[test]
fn test_add_multiple_nodes_bit_matrix() {
let bits = [[0u8], [0u8], [0u8], [0u8], [0u8], [0u8], [0u8], [0u8]];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let index_map = Dictionary::<char, usize, 10>::new();
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
bit_map_matrix.add_node('X').unwrap();
bit_map_matrix.add_node('Y').unwrap();
bit_map_matrix.add_node('Z').unwrap();
let mut nodes = ['\0'; 4];
let nodes_slice = collect_sorted(bit_map_matrix.iter_nodes().unwrap(), &mut nodes);
assert_eq!(nodes_slice, &['X', 'Y', 'Z']);
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 0);
}
#[test]
fn test_add_node_fills_gaps_bit_matrix() {
let bits = [[0u8], [0u8], [0u8], [0u8], [0u8], [0u8], [0u8], [0u8]];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<u32, usize, 10>::new();
index_map.insert(10, 0).unwrap();
index_map.insert(30, 2).unwrap();
index_map.insert(50, 4).unwrap();
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
bit_map_matrix.add_node(20).unwrap();
let mut nodes = [0u32; 6];
let nodes_slice = collect_sorted(bit_map_matrix.iter_nodes().unwrap(), &mut nodes);
assert_eq!(nodes_slice, &[10, 20, 30, 50]);
}
#[test]
fn test_add_edge_success() {
let bits = [[0u8]; 8];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<char, usize, 10>::new();
index_map.insert('A', 0).unwrap();
index_map.insert('B', 1).unwrap();
index_map.insert('C', 2).unwrap();
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
assert!(bit_map_matrix.add_edge('A', 'B').is_ok());
assert!(bit_map_matrix.add_edge('B', 'C').is_ok());
assert!(bit_map_matrix.add_edge('A', 'C').is_ok());
let edge_count = bit_map_matrix.iter_edges().unwrap().count();
assert_eq!(edge_count, 3);
let mut edges = [('\0', '\0'); 8];
let edges_slice = collect_sorted(bit_map_matrix.iter_edges().unwrap(), &mut edges);
assert_eq!(edges_slice, &[('A', 'B'), ('A', 'C'), ('B', 'C')]);
}
#[test]
fn test_add_edge_invalid_nodes() {
let bits = [[0u8]; 8];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<char, usize, 10>::new();
index_map.insert('A', 0).unwrap();
index_map.insert('B', 1).unwrap();
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
let result = bit_map_matrix.add_edge('X', 'B');
assert!(matches!(result, Err(GraphError::EdgeHasInvalidNode('X'))));
let result = bit_map_matrix.add_edge('A', 'Y');
assert!(matches!(result, Err(GraphError::EdgeHasInvalidNode('Y'))));
let result = bit_map_matrix.add_edge('X', 'Y');
assert!(matches!(result, Err(GraphError::EdgeHasInvalidNode('X'))));
}
#[test]
fn test_remove_edge_success() {
let bits = [
[0b00000110u8], [0b00000100u8], [0b00000000u8], [0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<char, usize, 10>::new();
index_map.insert('A', 0).unwrap();
index_map.insert('B', 1).unwrap();
index_map.insert('C', 2).unwrap();
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 3);
assert!(bit_map_matrix.remove_edge('A', 'B').is_ok());
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 2);
let mut edges = [('\0', '\0'); 8];
let edges_slice = collect_sorted(bit_map_matrix.iter_edges().unwrap(), &mut edges);
assert_eq!(edges_slice, &[('A', 'C'), ('B', 'C')]);
}
#[test]
fn test_remove_edge_not_found() {
let bits = [
[0b00000010u8], [0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
[0b00000000u8],
];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<char, usize, 10>::new();
index_map.insert('A', 0).unwrap();
index_map.insert('B', 1).unwrap();
index_map.insert('C', 2).unwrap();
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
let result = bit_map_matrix.remove_edge('A', 'C');
assert!(matches!(result, Err(GraphError::EdgeNotFound('A', 'C'))));
let result = bit_map_matrix.remove_edge('X', 'Y');
assert!(matches!(result, Err(GraphError::EdgeNotFound('X', 'Y'))));
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 1);
}
#[test]
fn test_add_remove_edge_comprehensive() {
let bits = [[0u8]; 8];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<u32, usize, 10>::new();
index_map.insert(10, 0).unwrap();
index_map.insert(20, 1).unwrap();
index_map.insert(30, 2).unwrap();
index_map.insert(40, 3).unwrap();
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 0);
assert!(bit_map_matrix.add_edge(10, 20).is_ok());
assert!(bit_map_matrix.add_edge(20, 30).is_ok());
assert!(bit_map_matrix.add_edge(30, 40).is_ok());
assert!(bit_map_matrix.add_edge(10, 40).is_ok());
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 4);
assert!(bit_map_matrix.remove_edge(20, 30).is_ok());
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 3);
let result = bit_map_matrix.remove_edge(20, 30);
assert!(matches!(result, Err(GraphError::EdgeNotFound(20, 30))));
assert!(bit_map_matrix.add_edge(20, 30).is_ok());
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 4);
let mut edges = [(0u32, 0u32); 8];
let edges_slice = collect_sorted(bit_map_matrix.iter_edges().unwrap(), &mut edges);
assert_eq!(edges_slice, &[(10, 20), (10, 40), (20, 30), (30, 40)]);
}
#[test]
fn test_self_loops() {
let bits = [[0u8]; 8];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<char, usize, 10>::new();
index_map.insert('A', 0).unwrap();
index_map.insert('B', 1).unwrap();
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
assert!(bit_map_matrix.add_edge('A', 'A').is_ok()); assert!(bit_map_matrix.add_edge('A', 'B').is_ok());
assert!(bit_map_matrix.add_edge('B', 'B').is_ok());
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 3);
assert!(bit_map_matrix.remove_edge('A', 'A').is_ok());
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 2);
let mut edges = [('\0', '\0'); 8];
let edges_slice = collect_sorted(bit_map_matrix.iter_edges().unwrap(), &mut edges);
assert_eq!(edges_slice, &[('A', 'B'), ('B', 'B')]);
}
#[test]
fn test_edge_idempotency() {
let bits = [[0u8]; 8];
let bitmap = super::super::bit_matrix::BitMatrix::new_unchecked(bits);
let mut index_map = Dictionary::<u32, usize, 10>::new();
index_map.insert(1, 0).unwrap();
index_map.insert(2, 1).unwrap();
let mut bit_map_matrix = BitMapMatrix::new(bitmap, index_map).unwrap();
assert!(bit_map_matrix.add_edge(1, 2).is_ok());
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 1);
assert!(bit_map_matrix.add_edge(1, 2).is_ok());
assert_eq!(bit_map_matrix.iter_edges().unwrap().count(), 1);
}
#[test]
fn test_bit_map_matrix_from_graph() {
let edges = EdgeStructOption([Some((10, 20)), Some((20, 30)), Some((10, 30)), None]);
let source = EdgeList::<4, usize, _>::new(edges);
type TestMatrix = BitMapMatrix<1, 8, usize, Dictionary<usize, usize, 8>>;
let bit_map_matrix: TestMatrix = BitMapMatrix::from_graph(&source).unwrap();
let mut nodes = [0usize; 8];
let nodes_slice = collect_sorted(bit_map_matrix.iter_nodes().unwrap(), &mut nodes);
assert_eq!(nodes_slice, &[10, 20, 30]);
let mut edges = [(0usize, 0usize); 16];
let edges_slice = collect_sorted(bit_map_matrix.iter_edges().unwrap(), &mut edges);
assert_eq!(edges_slice, &[(10, 20), (10, 30), (20, 30)]);
assert!(bit_map_matrix.contains_node(10).unwrap());
assert!(bit_map_matrix.contains_node(20).unwrap());
assert!(bit_map_matrix.contains_node(30).unwrap());
assert!(!bit_map_matrix.contains_node(40).unwrap());
}
#[test]
fn test_bit_map_matrix_from_graph_capacity_exceeded() {
let edges = EdgeStructOption([
Some((0, 1)),
Some((1, 2)),
Some((2, 3)),
Some((3, 4)),
Some((4, 5)),
Some((5, 6)),
Some((6, 7)),
Some((7, 8)),
]);
let source = EdgeList::<8, usize, _>::new(edges);
type TestMatrix = BitMapMatrix<1, 8, usize, Dictionary<usize, usize, 10>>;
let result: Result<TestMatrix, _> = BitMapMatrix::from_graph(&source);
assert!(matches!(result, Err(GraphError::OutOfCapacity)));
}
#[test]
fn test_bit_map_matrix_from_graph_with_arbitrary_indices() {
let edges = EdgeStructOption([Some((100, 200)), Some((200, 500)), Some((500, 100)), None]);
let source = EdgeList::<4, usize, _>::new(edges);
type TestMatrix = BitMapMatrix<1, 8, usize, Dictionary<usize, usize, 8>>;
let bit_map_matrix: TestMatrix = BitMapMatrix::from_graph(&source).unwrap();
let mut nodes = [0usize; 8];
let nodes_slice = collect_sorted(bit_map_matrix.iter_nodes().unwrap(), &mut nodes);
assert_eq!(nodes_slice, &[100, 200, 500]);
let mut edges = [(0usize, 0usize); 16];
let edges_slice = collect_sorted(bit_map_matrix.iter_edges().unwrap(), &mut edges);
assert_eq!(edges_slice, &[(100, 200), (200, 500), (500, 100)]);
let mut outgoing = [0usize; 8];
let outgoing_slice = collect(bit_map_matrix.outgoing_edges(100).unwrap(), &mut outgoing);
assert_eq!(outgoing_slice, &[200]);
let outgoing_slice = collect(bit_map_matrix.outgoing_edges(200).unwrap(), &mut outgoing);
assert_eq!(outgoing_slice, &[500]);
let outgoing_slice = collect(bit_map_matrix.outgoing_edges(500).unwrap(), &mut outgoing);
assert_eq!(outgoing_slice, &[100]);
}
#[test]
fn test_bit_map_matrix_from_graph_invalid_dimensions() {
let edges = EdgeStructOption([Some((0, 1)), Some((1, 2)), None]);
let source = EdgeList::<3, usize, _>::new(edges);
type InvalidMatrix = BitMapMatrix<1, 4, usize, Dictionary<usize, usize, 8>>;
let result: Result<InvalidMatrix, _> = BitMapMatrix::from_graph(&source);
assert!(matches!(result, Err(GraphError::InvalidMatrixSize)));
}
}