///
/// Compute the critical path for this graph.
///
/// The critical path is the longest path. For a directed acyclic graph, it is equivalent to a
/// shortest path algorithm.
///
/// Modify the graph we have to fit into the expectations of the Bellman-Ford shortest graph
/// algorithm and use that to calculate the critical path.
///
Compute the critical path for this graph.
The critical path is the longest path. For a directed acyclic graph, it is equivalent to a
shortest path algorithm.

Modify the graph we have to fit into the expectations of the Bellman-Ford shortest graph
algorithm and use that to calculate the critical path.
Compute the critical path for this graph . The critical path is the longest path . For a directed acyclic graph it is equivalent to a shortest path algorithm . Modify the graph we have to fit into the expectations of the Bellman - Ford shortest graph algorithm and use that to calculate the critical path .
fn critical_path<F>(&self, roots: &[N], duration: &F) -> (Duration, Vec<Entry<N>>)
  where
    F: Fn(&Entry<N>) -> Duration,
  {
    fn duration_into_weight(d: Duration) -> f64 {
      -(d.as_nanos() as f64)
    }
    // First, let's map nodes to edges
    let mut graph = self.pg.filter_map(
      |_node_idx, node_weight| Some(Some(node_weight)),
      |edge_idx, _edge_weight| {
        let target_node = self.pg.raw_edges()[edge_idx.index()].target();
        self
          .pg
          .node_weight(target_node)
          .map(duration)
          .map(duration_into_weight)
      },
    );
    // Add a single source that's a parent to all roots
    let srcs = roots
      .iter()
      .filter_map(|n| self.entry_id(n))
      .cloned()
      .collect::<Vec<_>>();
    let src = graph.add_node(None);
    for node in srcs {
      graph.add_edge(
        src,
        node,
        graph
          .node_weight(node)
          .map(|maybe_weight| {
            maybe_weight
              .map(duration)
              .map(duration_into_weight)
              .unwrap_or(0.)
          })
          .unwrap(),
      );
    }
    let (weights, paths) =
      petgraph::algo::bellman_ford(&graph, src).expect("The graph must be acyclic");
    if let Some((index, total_duration)) = weights
      .into_iter()
      .enumerate()
      .filter_map(|(i, weight)| {
        // INFINITY is used for missing entries.
        if weight == std::f64::INFINITY {
          None
        } else {
          Some((i, Duration::from_nanos(-weight as u64)))
        }
      })
      .max_by(|(_, left_duration), (_, right_duration)| left_duration.cmp(&right_duration))
    {
      let critical_path = {
        let mut next = paths[index];
        let mut path = vec![graph
          .node_weight(petgraph::graph::NodeIndex::new(index))
          .unwrap()
          .unwrap()];
        while next != Some(src) && next != None {
          if let Some(entry) = graph.node_weight(next.unwrap()).unwrap() {
            path.push(*entry);
          }
          next = paths[next.unwrap().index()];
        }
        path.into_iter().rev().cloned().collect()
      };
      (total_duration, critical_path)
    } else {
      (Duration::from_nanos(0), vec![])
    }
  }
fn critical_path < F > ( & self , roots : & [ N ] , duration : & F ) -> ( Duration , Vec < Entry < N > > ) where F : Fn ( & Entry < N > ) -> Duration , { fn duration_into_weight ( d : Duration ) -> f64 { - ( d . as_nanos ( ) as f64 ) } // First, let's map nodes to edges let mut graph = self . pg . filter_map ( | _node_idx , node_weight | Some ( Some ( node_weight ) ) , | edge_idx , _edge_weight | { let target_node = self . pg . raw_edges ( ) [ edge_idx . index ( ) ] . target ( ) ; self . pg . node_weight ( target_node ) . map ( duration ) . map ( duration_into_weight ) } , ) ; // Add a single source that's a parent to all roots let srcs = roots . iter ( ) . filter_map ( | n | self . entry_id ( n ) ) . cloned ( ) . collect :: < Vec < _ > > ( ) ; let src = graph . add_node ( None ) ; for node in srcs { graph . add_edge ( src , node , graph . node_weight ( node ) . map ( | maybe_weight | { maybe_weight . map ( duration ) . map ( duration_into_weight ) . unwrap_or ( 0. ) } ) . unwrap ( ) , ) ; } let ( weights , paths ) = petgraph :: algo :: bellman_ford ( & graph , src ) . expect ( " " ) ; if let Some ( ( index , total_duration ) ) = weights . into_iter ( ) . enumerate ( ) . filter_map ( | ( i , weight ) | { // INFINITY is used for missing entries. if weight == std :: f64 :: INFINITY { None } else { Some ( ( i , Duration :: from_nanos ( - weight as u64 ) ) ) } } ) . max_by ( | ( _ , left_duration ) , ( _ , right_duration ) | left_duration . cmp ( & right_duration ) ) { let critical_path = { let mut next = paths [ index ] ; let mut path = vec ! [ graph node_weight ( petgraph graph NodeIndex new ( index ) ) unwrap ( ) unwrap ( ) ] ; while next != Some ( src ) && next != None { if let Some ( entry ) = graph . node_weight ( next . unwrap ( ) ) . unwrap ( ) { path . push ( * entry ) ; } next = paths [ next . unwrap ( ) . index ( ) ] ; } path . into_iter ( ) . rev ( ) . cloned ( ) . collect ( ) } ; ( total_duration , critical_path ) } else { ( Duration :: from_nanos ( 0 ) , vec ! [ ] ) } }
Compute the critical path for this graph.
Compute the critical path for this graph .
&self
roots
&[N]
duration
&F