pub fn connected_components<M: Borrow<Model>>(analyser: &Analyser<M>) -> TractResult<Vec<Component>> {
    let is_edge_const: Vec<bool> = analyser
        .edges
        .iter()
        .map(|e| e.fact.value.is_concrete())
        .collect();

    let is_node_const: Vec<bool> = analyser
        .next_edges
        .iter()
        .map(|next| next.len() > 0 && next.iter().all(|i| is_edge_const[*i]))
        .collect();

    let mut components = vec![];
    let mut is_node_colored = vec![false; analyser.nodes.len()];
    let mut is_edge_colored = vec![false; analyser.edges.len()];
    let mut stack = vec![];

    macro_rules! process_edges {
        ($from:ident, $other:expr, $component:expr, $node:expr) => {{
            for &edge in &analyser.$from[$node] {
                if !is_edge_const[edge] || is_edge_colored[edge] {
                    continue;
                }

                is_edge_colored[edge] = true;
                $component.elements.push(Element::Edge(edge));

                let target = $other(edge);
                if target.is_none() {
                    continue;
                }

                if !is_node_const[target.unwrap()] {
                    $component.outputs.push(edge);
                } else {
                    stack.push(target.unwrap());
                }
            }
        }};
    };

    for (node, &is_const) in is_node_const.iter().enumerate() {
        if is_const && !is_node_colored[node] {
            let mut component = Component {
                elements: vec![],
                outputs: vec![],
            };

            stack.push(node);

            while let Some(node) = stack.pop() {
                if !is_node_const[node] || is_node_colored[node] {
                    continue;
                }

                is_node_colored[node] = true;
                component.elements.push(Element::Node(node));

                process_edges!(
                    prev_edges,
                    |e: usize| -> Option<usize> { analyser.edges[e].from.map(|n| n.node) },
                    component,
                    node
                );
                process_edges!(
                    next_edges,
                    |e: usize| analyser.edges[e].to_node,
                    component,
                    node
                );
            }

            components.push(component);
        }
    }

    Ok(components)
}
/// Computes all the connected components of the constant underlying graph.
///
/// The constant underlying graph G is constructed using these rules:
/// - If an edge has a constant value according to the analyser, it is in G.
/// - If all the outgoing edges of a node are in G, that node is also in G.
/// - If an edge in G has no target, it is called an "output".
Computes all the connected components of the constant underlying graph.
The constant underlying graph G is constructed using these rules:
If an edge has a constant value according to the analyser, it is in G.
If all the outgoing edges of a node are in G, that node is also in G.
If an edge in G has no target, it is called an "output".
Computes all the connected components of the constant underlying graph . The constant underlying graph G is constructed using these rules : If an edge has a constant value according to the analyser it is in G . If all the outgoing edges of a node are in G that node is also in G . If an edge in G has no target it is called an " output " .
pub fn connected_components<M: Borrow<Model>>(analyser: &Analyser<M>) -> TractResult<Vec<Component>> {
    let is_edge_const: Vec<bool> = analyser
        .edges
        .iter()
        .map(|e| e.fact.value.is_concrete())
        .collect();
    let is_node_const: Vec<bool> = analyser
        .next_edges
        .iter()
        .map(|next| next.len() > 0 && next.iter().all(|i| is_edge_const[*i]))
        .collect();
    let mut components = vec![];
    let mut is_node_colored = vec![false; analyser.nodes.len()];
    let mut is_edge_colored = vec![false; analyser.edges.len()];
    let mut stack = vec![];
    macro_rules! process_edges {
        ($from:ident, $other:expr, $component:expr, $node:expr) => {{
            for &edge in &analyser.$from[$node] {
                if !is_edge_const[edge] || is_edge_colored[edge] {
                    continue;
                }
                is_edge_colored[edge] = true;
                $component.elements.push(Element::Edge(edge));
                let target = $other(edge);
                if target.is_none() {
                    continue;
                }
                if !is_node_const[target.unwrap()] {
                    $component.outputs.push(edge);
                } else {
                    stack.push(target.unwrap());
                }
            }
        }};
    };
    for (node, &is_const) in is_node_const.iter().enumerate() {
        if is_const && !is_node_colored[node] {
            let mut component = Component {
                elements: vec![],
                outputs: vec![],
            };
            stack.push(node);
            while let Some(node) = stack.pop() {
                if !is_node_const[node] || is_node_colored[node] {
                    continue;
                }
                is_node_colored[node] = true;
                component.elements.push(Element::Node(node));
                process_edges!(
                    prev_edges,
                    |e: usize| -> Option<usize> { analyser.edges[e].from.map(|n| n.node) },
                    component,
                    node
                );
                process_edges!(
                    next_edges,
                    |e: usize| analyser.edges[e].to_node,
                    component,
                    node
                );
            }
            components.push(component);
        }
    }
    Ok(components)
}
pub fn connected_components < M : Borrow < Model > > ( analyser : & Analyser < M > ) -> TractResult < Vec < Component > > { let is_edge_const : Vec < bool > = analyser . edges . iter ( ) . map ( | e | e . fact . value . is_concrete ( ) ) . collect ( ) ; let is_node_const : Vec < bool > = analyser . next_edges . iter ( ) . map ( | next | next . len ( ) > 0 && next . iter ( ) . all ( | i | is_edge_const [ * i ] ) ) . collect ( ) ; let mut components = vec ! [ ] ; let mut is_node_colored = vec ! [ false analyser nodes len ( ) ] ; let mut is_edge_colored = vec ! [ false analyser edges len ( ) ] ; let mut stack = vec ! [ ] ; macro_rules! process_edges { ( $from : ident $other : expr $component : expr $node : expr ) => { { for edge in analyser $from [ $node ] { if is_edge_const [ edge ] is_edge_colored [ edge ] { continue } is_edge_colored [ edge ] true $component elements push ( Element Edge ( edge ) ) let target $other ( edge ) if target is_none ( ) { continue } if is_node_const [ target unwrap ( ) ] { $component outputs push ( edge ) } else { stack push ( target unwrap ( ) ) } } } } ; } ; for ( node , & is_const ) in is_node_const . iter ( ) . enumerate ( ) { if is_const && ! is_node_colored [ node ] { let mut component = Component { elements : vec ! [ ] , outputs : vec ! [ ] , } ; stack . push ( node ) ; while let Some ( node ) = stack . pop ( ) { if ! is_node_const [ node ] || is_node_colored [ node ] { continue ; } is_node_colored [ node ] = true ; component . elements . push ( Element :: Node ( node ) ) ; process_edges ! ( prev_edges e usize Option usize { analyser edges [ e ] from map ( n n node ) } component node ) ; process_edges ! ( next_edges e usize analyser edges [ e ] to_node component node ) ; } components . push ( component ) ; } } Ok ( components ) }
Computes all the connected components of the constant underlying graph.
Computes all the connected components of the constant underlying graph .
analyser
&Analyser<M>