fleet-topology 0.1.0

Fleet network topology with constraint-aware routing and holonomy verification
Documentation
use crate::graph::FleetGraph;

/// Verify holonomy (cycle consistency) on the fleet graph.
/// For each cycle, the product of constraint maps must be identity.
/// This is the Kawasaki condition from origami, applied to fleet topology.
pub struct HolonomyVerifier<'a> {
    graph: &'a FleetGraph,
}

impl<'a> HolonomyVerifier<'a> {
    pub fn new(graph: &'a FleetGraph) -> Self {
        HolonomyVerifier { graph }
    }

    /// Verify all cycles have trivial holonomy
    pub fn verify_all(&self) -> HolonomyReport {
        let cycles = self.graph.find_cycles();
        let mut violations = Vec::new();
        for cycle in &cycles {
            if !self.verify_cycle(cycle) {
                violations.push(cycle.clone());
            }
        }
        HolonomyReport {
            total_cycles: cycles.len(),
            all_consistent: violations.is_empty(),
            violations,
            betti1: self.graph.betti1(),
        }
    }

    fn verify_cycle(&self, cycle: &[String]) -> bool {
        // XOR-fold constraint maps along cycle.
        // Count constraint-carrying edges in the cycle.
        // If odd number of constraint transformations, holonomy is non-trivial.
        let edge_count = self.count_constraint_edges_in_cycle(cycle);
        // Holonomy is trivial when constraint transformations compose to identity.
        // Simplified model: even number of constraint edges = identity composition.
        edge_count % 2 == 0
    }

    fn count_constraint_edges_in_cycle(&self, cycle: &[String]) -> usize {
        if cycle.len() < 2 {
            return 0;
        }
        let mut count = 0;
        for i in 0..cycle.len() {
            let from = &cycle[i];
            let to = &cycle[(i + 1) % cycle.len()];
            for edge in self.graph.edges() {
                if (edge.from == *from && edge.to == *to)
                    || (edge.from == *to && edge.to == *from)
                {
                    if edge.constraint_flow {
                        count += 1;
                    }
                    break;
                }
            }
        }
        count
    }
}

#[derive(Debug)]
pub struct HolonomyReport {
    pub total_cycles: usize,
    pub violations: Vec<Vec<String>>,
    pub betti1: usize,
    pub all_consistent: bool,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_empty_graph_is_consistent() {
        let graph = FleetGraph::new();
        let verifier = HolonomyVerifier::new(&graph);
        let report = verifier.verify_all();
        assert!(report.all_consistent);
        assert_eq!(report.total_cycles, 0);
    }
}