fleet-topology 0.1.0

Fleet network topology with constraint-aware routing and holonomy verification
Documentation
use crate::graph::FleetGraph;
use std::collections::{HashMap, HashSet, VecDeque};

/// Route messages through the fleet considering constraint propagation.
/// Messages that carry constraints must follow edges with constraint_flow=true.
pub struct ConstraintRouter<'a> {
    graph: &'a FleetGraph,
}

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

    /// Find shortest constraint-capable path between two nodes
    pub fn route(&self, from: &str, to: &str) -> Option<Route> {
        let constraint_adj: HashMap<&str, Vec<(&str, u64)>> = self
            .graph
            .edges()
            .iter()
            .filter(|e| e.constraint_flow)
            .fold(HashMap::new(), |mut acc, e| {
                acc.entry(&e.from)
                    .or_default()
                    .push((&e.to, e.latency_us));
                acc.entry(&e.to)
                    .or_default()
                    .push((&e.from, e.latency_us));
                acc
            });

        let mut queue = VecDeque::new();
        let mut parent: HashMap<String, Option<(String, u64)>> = HashMap::new();

        queue.push_back(from.to_string());
        parent.insert(from.to_string(), None);

        while let Some(current) = queue.pop_front() {
            if current == to {
                let mut path = Vec::new();
                let mut total_latency = 0u64;
                let mut node = Some(to.to_string());
                while let Some(n) = node {
                    let latency = parent
                        .get(&n)
                        .and_then(|p| p.as_ref().map(|(_, l)| *l))
                        .unwrap_or(0);
                    total_latency += latency;
                    path.push(n.clone());
                    node = parent.get(&n).and_then(|p| p.as_ref().map(|(p, _)| p.clone()));
                }
                path.reverse();
                return Some(Route {
                    hops: path.len().saturating_sub(1),
                    path,
                    total_latency_us: total_latency,
                });
            }

            if let Some(neighbors) = constraint_adj.get(current.as_str()) {
                for &(neighbor, latency) in neighbors {
                    let n = neighbor.to_string();
                    if !parent.contains_key(&n) {
                        parent.insert(
                            n.clone(),
                            Some((current.clone(), latency)),
                        );
                        queue.push_back(n);
                    }
                }
            }
        }
        None
    }

    /// Find all devices that can reach a given device via constraint edges
    pub fn constraint_neighborhood(&self, device: &str) -> Vec<String> {
        let constraint_adj: HashMap<&str, Vec<&str>> = self
            .graph
            .edges()
            .iter()
            .filter(|e| e.constraint_flow)
            .fold(HashMap::new(), |mut acc, e| {
                acc.entry(&e.from).or_default().push(&e.to);
                acc.entry(&e.to).or_default().push(&e.from);
                acc
            });

        let mut visited = HashSet::new();
        let mut queue = VecDeque::new();
        let mut result = Vec::new();

        queue.push_back(device);
        visited.insert(device);

        while let Some(current) = queue.pop_front() {
            result.push(current.to_string());
            if let Some(neighbors) = constraint_adj.get(current) {
                for &next in neighbors {
                    if !visited.contains(next) {
                        visited.insert(next);
                        queue.push_back(next);
                    }
                }
            }
        }
        result
    }
}

pub struct Route {
    pub path: Vec<String>,
    pub total_latency_us: u64,
    pub hops: usize,
}