use crate::{
Directedness, DtwPolicy, GapPolicy, Graph, GraphError, bfs, dynamic_time_warp, kruskals_mst,
layered_shortest_path, verify_alignment, verify_layered_path,
};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TinyGraphDemo {
pub node_count: usize,
pub edge_count: usize,
pub bfs_order: Vec<usize>,
pub mst_edge_ids: Vec<usize>,
pub mst_total_weight: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AlignmentCompositionDemo {
pub staged_states: Vec<i64>,
pub staged_indices: Vec<usize>,
pub staged_cost: i64,
pub staged_cells: u64,
pub staged_edges: u64,
pub alignment_score: i64,
pub alignment_steps: usize,
pub alignment_cells: u64,
pub alignment_edges: u64,
}
pub fn tiny_graph_demo() -> Result<TinyGraphDemo, GraphError> {
let mut graph = Graph::with_nodes(vec![0, 1, 2], Directedness::Undirected);
graph.add_edge(0, 1, 1_i64)?;
graph.add_edge(1, 2, 2_i64)?;
graph.add_edge(0, 2, 5_i64)?;
let traversal = bfs(&graph, 0)?;
let mst = kruskals_mst(&graph)?;
Ok(TinyGraphDemo {
node_count: graph.node_count(),
edge_count: graph.edge_count(),
bfs_order: traversal.order,
mst_edge_ids: mst.edges,
mst_total_weight: mst.total_weight,
})
}
pub fn alignment_composition_demo() -> Result<AlignmentCompositionDemo, GraphError> {
let layers = vec![vec![0_i64, 3], vec![2_i64, 5], vec![4_i64, 7]];
let staged = layered_shortest_path(&layers, |left, right| left.abs_diff(*right) as i64)?;
verify_layered_path(
&layers,
|left, right| Some(left.abs_diff(*right) as i64),
&staged,
)?;
let left = [0_i64, 2, 4];
let right = [0_i64, 1, 2, 4];
let policy = DtwPolicy::new(GapPolicy::new(2_i64, 2_i64));
let alignment = dynamic_time_warp(
&left,
&right,
|left, right| left.abs_diff(*right) as i64,
policy.clone(),
)?;
verify_alignment(
&left,
&right,
|left, right| left.abs_diff(*right) as i64,
&policy,
&alignment,
)?;
Ok(AlignmentCompositionDemo {
staged_states: staged.states,
staged_indices: staged.indices,
staged_cost: staged.total_cost,
staged_cells: staged.receipt.cells,
staged_edges: staged.receipt.edges,
alignment_score: alignment.score,
alignment_steps: alignment.steps.as_ref().map_or(0, Vec::len),
alignment_cells: alignment.receipt.cells,
alignment_edges: alignment.receipt.edges,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn graph_demo_runs_bfs_and_mst() {
let demo = tiny_graph_demo().expect("valid graph demo");
assert_eq!(demo.node_count, 3);
assert_eq!(demo.edge_count, 3);
assert_eq!(demo.bfs_order, vec![0, 1, 2]);
assert_eq!(demo.mst_edge_ids, vec![0, 1]);
assert_eq!(demo.mst_total_weight, 3);
}
#[test]
fn staged_selection_composes_with_dtw_and_verifies_both_certificates() {
let demo = alignment_composition_demo().expect("composed alignment evidence");
assert_eq!(demo.staged_states, vec![3, 2, 4]);
assert_eq!(demo.staged_indices, vec![1, 0, 0]);
assert_eq!(demo.staged_cost, 3);
assert_eq!(demo.alignment_score, 2);
assert_eq!(demo.alignment_steps, 4);
assert!(demo.staged_cells > 0 && demo.staged_edges > 0);
assert!(demo.alignment_cells > 0 && demo.alignment_edges > 0);
}
}