pub fn toposort<Node, Key, GetKey, GetConnectedNodes>(
    nodes: Vec<Node>,
    get_key: GetKey,
    get_connected_nodes: GetConnectedNodes,
) -> Vec<Scc<Node>>
where
    Node: Clone,
    Key: Clone + Eq + Hash + std::fmt::Debug,
    GetKey: Fn(&Node) -> Key,
    GetConnectedNodes: Fn(&Node) -> HashSet<Key>,
{
    let mut graph: Graph<(Node, bool), &str> = Graph::new();
    let mut graph_nodes: HashMap<Key, (NodeIndex, HashSet<Key>)> = HashMap::new();

    // First pass: add the nodes
    for node in &nodes {
        let key = get_key(node);
        let connected_nodes = get_connected_nodes(node);
        let is_self_referencing = connected_nodes.contains(&key);
        let node_index = graph.add_node((node.clone(), is_self_referencing));
        graph_nodes.insert(key, (node_index, connected_nodes));
    }

    // Second pass: add the edges
    for node in &nodes {
        let key = get_key(node);
        let (node_index, connected_nodes) = graph_nodes
            .get(&key)
            .unwrap_or_else(|| panic!("{:?} to be in {:?}", key, graph_nodes));

        // NOTE presumably the arbitrary order of the connected_nodes iterator
        // doesn't matter here?
        connected_nodes.iter().for_each(|conn_key| {
            let (conn_index, _) = graph_nodes
                .get(conn_key)
                .cloned()
                .unwrap_or_else(|| panic!("{:?} to be in {:?}", conn_key, graph_nodes));
            graph.add_edge(*node_index, conn_index, "");
        });
    }

    // println!("{}", Dot::new(&graph));  <-- useful for debuggin'

    kosaraju_scc(&graph)
        .iter()
        .map(|component| match component.as_slice() {
            [] => panic!("unexpected empty graph component"),
            [node_index] => {
                let (node, is_self_referencing) = graph[*node_index].clone();
                if is_self_referencing {
                    Scc::Cyclic(vec![node])
                } else {
                    Scc::Acyclic(node)
                }
            }
            _ => {
                let nodes = component
                    .iter()
                    .map(|node_index| {
                        let (node, _) = graph[*node_index].clone();
                        node
                    })
                    .collect();
                Scc::Cyclic(nodes)
            }
        })
        .collect()
}
/// Extract the strongly connected components of a directed graph, reverse topologically sorted.
///
/// The order of nodes within the [Scc::Cyclic] variant is arbitrary.
/// For a deterministic version of this function see [toposort_deterministic].
Extract the strongly connected components of a directed graph, reverse topologically sorted.
The order of nodes within the [Scc::Cyclic] variant is arbitrary.
For a deterministic version of this function see [toposort_deterministic].
Extract the strongly connected components of a directed graph reverse topologically sorted . The order of nodes within the [ Scc :: Cyclic ] variant is arbitrary . For a deterministic version of this function see [ toposort_deterministic ] .
pub fn toposort<Node, Key, GetKey, GetConnectedNodes>(
    nodes: Vec<Node>,
    get_key: GetKey,
    get_connected_nodes: GetConnectedNodes,
) -> Vec<Scc<Node>>
where
    Node: Clone,
    Key: Clone + Eq + Hash + std::fmt::Debug,
    GetKey: Fn(&Node) -> Key,
    GetConnectedNodes: Fn(&Node) -> HashSet<Key>,
{
    let mut graph: Graph<(Node, bool), &str> = Graph::new();
    let mut graph_nodes: HashMap<Key, (NodeIndex, HashSet<Key>)> = HashMap::new();
    // First pass: add the nodes
    for node in &nodes {
        let key = get_key(node);
        let connected_nodes = get_connected_nodes(node);
        let is_self_referencing = connected_nodes.contains(&key);
        let node_index = graph.add_node((node.clone(), is_self_referencing));
        graph_nodes.insert(key, (node_index, connected_nodes));
    }
    // Second pass: add the edges
    for node in &nodes {
        let key = get_key(node);
        let (node_index, connected_nodes) = graph_nodes
            .get(&key)
            .unwrap_or_else(|| panic!("{:?} to be in {:?}", key, graph_nodes));
        // NOTE presumably the arbitrary order of the connected_nodes iterator
        // doesn't matter here?
        connected_nodes.iter().for_each(|conn_key| {
            let (conn_index, _) = graph_nodes
                .get(conn_key)
                .cloned()
                .unwrap_or_else(|| panic!("{:?} to be in {:?}", conn_key, graph_nodes));
            graph.add_edge(*node_index, conn_index, "");
        });
    }
    // println!("{}", Dot::new(&graph));  <-- useful for debuggin'
    kosaraju_scc(&graph)
        .iter()
        .map(|component| match component.as_slice() {
            [] => panic!("unexpected empty graph component"),
            [node_index] => {
                let (node, is_self_referencing) = graph[*node_index].clone();
                if is_self_referencing {
                    Scc::Cyclic(vec![node])
                } else {
                    Scc::Acyclic(node)
                }
            }
            _ => {
                let nodes = component
                    .iter()
                    .map(|node_index| {
                        let (node, _) = graph[*node_index].clone();
                        node
                    })
                    .collect();
                Scc::Cyclic(nodes)
            }
        })
        .collect()
}
pub fn toposort < Node , Key , GetKey , GetConnectedNodes > ( nodes : Vec < Node > , get_key : GetKey , get_connected_nodes : GetConnectedNodes , ) -> Vec < Scc < Node > > where Node : Clone , Key : Clone + Eq + Hash + std :: fmt :: Debug , GetKey : Fn ( & Node ) -> Key , GetConnectedNodes : Fn ( & Node ) -> HashSet < Key > , { let mut graph : Graph < ( Node , bool ) , & str > = Graph :: new ( ) ; let mut graph_nodes : HashMap < Key , ( NodeIndex , HashSet < Key > ) > = HashMap :: new ( ) ; // First pass: add the nodes for node in & nodes { let key = get_key ( node ) ; let connected_nodes = get_connected_nodes ( node ) ; let is_self_referencing = connected_nodes . contains ( & key ) ; let node_index = graph . add_node ( ( node . clone ( ) , is_self_referencing ) ) ; graph_nodes . insert ( key , ( node_index , connected_nodes ) ) ; } // Second pass: add the edges for node in & nodes { let key = get_key ( node ) ; let ( node_index , connected_nodes ) = graph_nodes . get ( & key ) . unwrap_or_else ( | | panic ! ( " " key graph_nodes ) ) ; // NOTE presumably the arbitrary order of the connected_nodes iterator // doesn't matter here? connected_nodes . iter ( ) . for_each ( | conn_key | { let ( conn_index , _ ) = graph_nodes . get ( conn_key ) . cloned ( ) . unwrap_or_else ( | | panic ! ( " " conn_key graph_nodes ) ) ; graph . add_edge ( * node_index , conn_index , " " ) ; } ) ; } // println!("{}", Dot::new(&graph));  <-- useful for debuggin' kosaraju_scc ( & graph ) . iter ( ) . map ( | component | match component . as_slice ( ) { [ ] => panic ! ( " " ) , [ node_index ] => { let ( node , is_self_referencing ) = graph [ * node_index ] . clone ( ) ; if is_self_referencing { Scc :: Cyclic ( vec ! [ node ] ) } else { Scc :: Acyclic ( node ) } } _ => { let nodes = component . iter ( ) . map ( | node_index | { let ( node , _ ) = graph [ * node_index ] . clone ( ) ; node } ) . collect ( ) ; Scc :: Cyclic ( nodes ) } } ) . collect ( ) }
Extract the strongly connected components of a directed graph, reverse topologically sorted.
Extract the strongly connected components of a directed graph reverse topologically sorted .
nodes
Vec<Node>
get_key
GetKey
get_connected_nodes
GetConnectedNodes
nodes
Vec<Node>
get_key
GetKey
get_connected_nodes
GetConnectedNodes