github.com/charypar/monobuild@v0.0.0-20211122220434-fd884ed50212/rs/src/graph/mod.rs (about)

     1  use std::collections::{BTreeMap, BTreeSet};
     2  
     3  mod debug;
     4  mod iter;
     5  mod partial_eq;
     6  
     7  use self::iter::{GraphIter, Vertices};
     8  
     9  pub trait Vertex: PartialEq + Clone {}
    10  impl<T> Vertex for T where T: PartialEq + Clone {}
    11  pub trait Edge: PartialEq + Ord + Copy {}
    12  impl<T> Edge for T where T: PartialEq + Ord + Copy {}
    13  
    14  pub struct Graph<V, E>
    15  where
    16      V: Vertex,
    17      E: Edge,
    18  {
    19      vertices: Vec<V>,                 // vertex index -> V
    20      edges: Vec<BTreeSet<(usize, E)>>, // vertex index -> {(vertex index, E)}
    21  }
    22  
    23  impl<V, E> Graph<V, E>
    24  where
    25      V: Vertex,
    26      E: Edge,
    27  {
    28      pub fn new() -> Self {
    29          Graph {
    30              vertices: vec![],
    31              edges: vec![],
    32          }
    33      }
    34  
    35      // Iterate over graph or vertices
    36  
    37      pub fn vertices<'g>(&'g self) -> Vertices<'g, '_, V> {
    38          Vertices {
    39              iter: self.vertices.iter().enumerate(),
    40              mask: None,
    41          }
    42      }
    43  
    44      pub fn iter<'g>(&'g self) -> GraphIter<'g, '_, V, E> {
    45          GraphIter {
    46              graph: self,
    47              iter: self.vertices.iter().enumerate(),
    48              masks: None,
    49          }
    50      }
    51  
    52      // Scope graph
    53  
    54      pub fn roots<'g>(&'g self) -> Subgraph<'g, V, E> {
    55          let mut vertex_mask: Vec<_> = std::iter::repeat(true).take(self.vertices.len()).collect();
    56  
    57          // Remove all vertices with an incoming edge
    58          for edgs in &self.edges {
    59              for (to, _) in edgs {
    60                  vertex_mask[*to] = false;
    61              }
    62          }
    63  
    64          // Remove edges using the mask we just made
    65          let edge_mask = (0..self.vertices.len())
    66              .flat_map(|from| {
    67                  self.edges
    68                      .get(from)
    69                      .expect("edges to exist")
    70                      .iter()
    71                      .map(move |(to, _)| (from, *to))
    72              })
    73              .filter(|(from, to)| vertex_mask[*from] && vertex_mask[*to])
    74              .collect();
    75  
    76          Subgraph {
    77              graph: self,
    78              vertex_mask,
    79              edge_mask,
    80          }
    81      }
    82  
    83      // Removes vertices and associated edges
    84      pub fn filter_vertices<'g, P>(&'g self, predicate: P) -> Subgraph<'g, V, E>
    85      where
    86          P: Fn(&V) -> bool,
    87      {
    88          // Remove vertices
    89          let vertex_mask: Vec<bool> = self.vertices.iter().map(|v| predicate(v)).collect();
    90  
    91          // Remove edges using the mask we just made
    92          let edge_mask = (0..self.vertices.len())
    93              .flat_map(|from| {
    94                  self.edges
    95                      .get(from)
    96                      .expect("edges to exist")
    97                      .iter()
    98                      .map(move |(to, _)| (from, *to))
    99              })
   100              .filter(|(from, to)| vertex_mask[*from] && vertex_mask[*to])
   101              .collect();
   102  
   103          Subgraph {
   104              graph: self,
   105              vertex_mask,
   106              edge_mask,
   107          }
   108      }
   109  
   110      // Removes edges but keeps vertices alone
   111      pub fn filter_edges<'g, P>(&'g self, predicate: P) -> Subgraph<'g, V, E>
   112      where
   113          P: Fn(&E) -> bool,
   114      {
   115          let vertex_mask = std::iter::repeat(true).take(self.vertices.len()).collect();
   116          let edge_mask = (0..self.vertices.len())
   117              .flat_map(|from| {
   118                  self.edges
   119                      .get(from)
   120                      .expect("edges to exist")
   121                      .iter()
   122                      .map(move |(to, label)| (from, *to, label))
   123              })
   124              .filter_map(|(from, to, label)| {
   125                  if predicate(label) {
   126                      Some((from, to))
   127                  } else {
   128                      None
   129                  }
   130              })
   131              .collect();
   132  
   133          Subgraph {
   134              graph: self,
   135              vertex_mask,
   136              edge_mask,
   137          }
   138      }
   139  
   140      // Transform graph
   141  
   142      pub fn reverse(&self) -> Self {
   143          let vertices = self.vertices.clone();
   144          let mut edges: Vec<_> = std::iter::repeat_with(|| BTreeSet::new())
   145              .take(vertices.len())
   146              .collect();
   147  
   148          for (to, edgs) in self.edges.iter().enumerate() {
   149              for (from, label) in edgs {
   150                  edges[*from].insert((to, *label));
   151              }
   152          }
   153  
   154          Graph { vertices, edges }
   155      }
   156  }
   157  
   158  // Construct a graph from adjacency list
   159  impl<Adj, Edg, V, E> From<Adj> for Graph<V, E>
   160  where
   161      Adj: IntoIterator<Item = (V, Edg)>,
   162      Edg: IntoIterator<Item = (V, E)>,
   163      V: Vertex + Ord,
   164      E: Edge,
   165  {
   166      fn from(graph: Adj) -> Self {
   167          // Make a local copy to allow multiple passes
   168          let graph: Vec<(V, BTreeSet<_>)> = graph
   169              .into_iter()
   170              .map(|(v, es)| (v, es.into_iter().collect()))
   171              .collect();
   172  
   173          // Find and insert all the vertices, sorted using Ord
   174          let mut vertices: BTreeSet<V> = BTreeSet::new();
   175          for (from, edg) in &graph {
   176              vertices.insert(from.clone());
   177  
   178              for (to, _) in edg.into_iter() {
   179                  vertices.insert(to.clone());
   180              }
   181          }
   182  
   183          // Index and reverse index them
   184          let vertices: Vec<_> = vertices.into_iter().collect();
   185          let vertex_index: BTreeMap<V, usize> = vertices
   186              .iter()
   187              .enumerate()
   188              .map(|(i, v)| (v.clone(), i))
   189              .collect();
   190  
   191          // Allocate edge mapping
   192          let mut edges: Vec<_> = std::iter::repeat_with(|| BTreeSet::new())
   193              .take(vertices.len())
   194              .collect();
   195  
   196          // Insert all the edges
   197          for (from, edg) in graph {
   198              let from_idx = *vertex_index.get(&from).expect("a vertex to exist");
   199              let edges_from = edges.get_mut(from_idx).expect("an edge set to exist");
   200  
   201              for (to, label) in edg {
   202                  let to_idx = *vertex_index.get(&to).expect("a vertex to exist");
   203  
   204                  edges_from.insert((to_idx, label));
   205              }
   206          }
   207  
   208          Graph { vertices, edges }
   209      }
   210  }
   211  
   212  pub struct Subgraph<'g, V, E>
   213  where
   214      V: Vertex + 'g,
   215      E: Edge,
   216  {
   217      graph: &'g Graph<V, E>,
   218      vertex_mask: Vec<bool>,
   219      edge_mask: BTreeSet<(usize, usize)>,
   220  }
   221  
   222  impl<'g, V, E> Subgraph<'g, V, E>
   223  where
   224      V: Vertex + 'g,
   225      E: Edge,
   226  {
   227      // Inspect graph
   228  
   229      pub fn iter<'s>(&'s self) -> GraphIter<'g, 's, V, E> {
   230          GraphIter {
   231              graph: self.graph,
   232              iter: self.graph.vertices.iter().enumerate(),
   233              masks: Some((&self.vertex_mask, &self.edge_mask)),
   234          }
   235      }
   236  
   237      pub fn vertices<'s>(&'s self) -> Vertices<'g, 's, V> {
   238          Vertices {
   239              iter: self.graph.vertices.iter().enumerate(),
   240              mask: Some(&self.vertex_mask),
   241          }
   242      }
   243  
   244      pub fn roots(&self) -> Subgraph<'g, V, E> {
   245          let mut vertex_mask: Vec<_> = self.vertex_mask.clone();
   246  
   247          // Remove all vertices with an incoming edge
   248          for (from, edgs) in self.graph.edges.iter().enumerate() {
   249              for (to, _) in edgs {
   250                  if self.edge_mask.contains(&(from, *to)) {
   251                      vertex_mask[*to] = false;
   252                  }
   253              }
   254          }
   255  
   256          // Remove edges using the mask we just made, respecting the original edge mask
   257          let edge_mask = (0..self.graph.vertices.len())
   258              .flat_map(|from| {
   259                  self.graph
   260                      .edges
   261                      .get(from)
   262                      .expect("edges to exist")
   263                      .iter()
   264                      .map(move |(to, _)| (from, *to))
   265              })
   266              .filter(|(from, to)| {
   267                  vertex_mask[*from] && vertex_mask[*to] && self.edge_mask.contains(&(*from, *to))
   268              })
   269              .collect();
   270  
   271          Subgraph {
   272              graph: self.graph,
   273              vertex_mask,
   274              edge_mask,
   275          }
   276      }
   277  
   278      // Removes vertices and associated edges
   279      pub fn filter_vertices<P>(&self, predicate: P) -> Subgraph<'g, V, E>
   280      where
   281          P: Fn(&V) -> bool,
   282      {
   283          // Remove vertices
   284          let vertex_mask: Vec<bool> = self
   285              .graph
   286              .vertices
   287              .iter()
   288              .enumerate()
   289              .map(|(i, v)| self.vertex_mask[i] && predicate(v))
   290              .collect();
   291  
   292          // Remove edges using the mask we just made
   293          let edge_mask = self
   294              .graph
   295              .vertices
   296              .iter()
   297              .enumerate()
   298              .flat_map(|(from, _)| {
   299                  self.graph
   300                      .edges
   301                      .get(from)
   302                      .expect("edges to exist")
   303                      .iter()
   304                      .map(move |(to, _)| (from, *to))
   305              })
   306              .filter(|(from, to)| {
   307                  vertex_mask[*from] && vertex_mask[*to] && self.edge_mask.contains(&(*from, *to))
   308              })
   309              .collect();
   310  
   311          Subgraph {
   312              graph: self.graph,
   313              vertex_mask,
   314              edge_mask,
   315          }
   316      }
   317  
   318      // Removes edges but keeps vertices alone
   319      pub fn filter_edges<P>(&self, predicate: P) -> Subgraph<'g, V, E>
   320      where
   321          P: Fn(&E) -> bool,
   322      {
   323          let edge_mask = (0..self.vertex_mask.len())
   324              .flat_map(|from| {
   325                  self.graph
   326                      .edges
   327                      .get(from)
   328                      .expect("edges to exist")
   329                      .iter()
   330                      .map(move |(to, label)| (from, *to, label))
   331              })
   332              .filter_map(|(from, to, label)| {
   333                  if predicate(label) && self.edge_mask.contains(&(from, to)) {
   334                      Some((from, to))
   335                  } else {
   336                      None
   337                  }
   338              })
   339              .collect();
   340  
   341          Subgraph {
   342              graph: self.graph,
   343              vertex_mask: self.vertex_mask.clone(),
   344              edge_mask,
   345          }
   346      }
   347  
   348      // Expand subgraph along original edges, applying a predicate to decide whether to follow an edge
   349      pub fn expand_via<P>(&self, predicate: P) -> Subgraph<'g, V, E>
   350      where
   351          P: Fn(&E) -> bool,
   352      {
   353          let mut vertex_mask = self.vertex_mask.clone();
   354          let mut edge_mask = self.edge_mask.clone();
   355  
   356          // front is the set of vertices we're attempting to expand the graph from
   357          // via edges that are *not* in the edge mask (because those are already included)
   358          // and that pass the predicate test
   359          let mut front: Vec<usize> = vertex_mask
   360              .iter()
   361              .enumerate()
   362              .filter_map(|(idx, inc)| if *inc { Some(idx) } else { None })
   363              .collect();
   364  
   365          while front.len() > 0 {
   366              front = front
   367                  .iter()
   368                  .flat_map(|from| {
   369                      let edges = self.graph.edges.get(*from).expect("edges to exist");
   370  
   371                      edges.iter().map(move |(to, label)| (*from, *to, label))
   372                  })
   373                  .filter_map(|(from, to, label)| {
   374                      if !self.edge_mask.contains(&(from, to)) && predicate(label) {
   375                          // expand the graph
   376                          vertex_mask[to] = true;
   377                          edge_mask.insert((from, to));
   378  
   379                          // and add the destination vertec to the next iteration front
   380                          Some(to)
   381                      } else {
   382                          None
   383                      }
   384                  })
   385                  .collect::<Vec<_>>();
   386          }
   387  
   388          Subgraph {
   389              graph: self.graph,
   390              vertex_mask,
   391              edge_mask,
   392          }
   393      }
   394  
   395      pub fn expand(&self) -> Self {
   396          self.expand_via(|_| true)
   397      }
   398  }
   399  
   400  #[cfg(test)]
   401  mod test {
   402      use super::*;
   403  
   404      #[test]
   405      fn new_normalizes_graph() {
   406          let graph = Graph::<usize, usize>::from([(1, [(2, 0), (3, 0)])]);
   407  
   408          let expected = vec![1, 2, 3];
   409          let actual = graph.vertices().cloned().collect::<Vec<_>>();
   410  
   411          assert_eq!(actual, expected);
   412      }
   413  
   414      mod filter {
   415          use super::super::*;
   416  
   417          #[test]
   418          fn filters_an_empty_graph() {
   419              let graph = Graph::<usize, usize>::new();
   420  
   421              let expected = Graph::<usize, usize>::new();
   422              let actual_v = graph.filter_vertices(|_v| true);
   423              let actual_e = graph.filter_edges(|_e| true);
   424  
   425              assert_eq!(actual_v, expected);
   426              assert_eq!(actual_e, expected);
   427          }
   428  
   429          #[test]
   430          fn filters_a_vertex_from_a_graph() {
   431              let graph = Graph::from([(1, [(2, 0), (3, 0)])]);
   432  
   433              let expected = Graph::from([(1, [(3, 0)])]);
   434              let actual = graph.filter_vertices(|v| *v != 2);
   435  
   436              assert_eq!(actual, expected);
   437          }
   438  
   439          #[test]
   440          fn filters_an_edge_from_a_graph() {
   441              let graph = Graph::from([(1, vec![(2, 0), (3, 1)]), (2, vec![(3, 0)])]);
   442  
   443              let expected = Graph::from([(1, [(2, 0)]), (2, [(3, 0)])]);
   444              let actual = graph.filter_edges(|e| *e != 1);
   445  
   446              assert_eq!(actual, expected);
   447          }
   448  
   449          #[test]
   450          fn filters_a_vertex_from_a_subgraph() {
   451              let graph = Graph::from([(1, [(2, 0), (3, 0)])]);
   452  
   453              let expected = Graph::from([(1, [])]);
   454              let actual = graph
   455                  .filter_vertices(|v| *v != 2)
   456                  .filter_vertices(|v| *v != 3);
   457  
   458              assert_eq!(actual, expected);
   459          }
   460  
   461          #[test]
   462          fn filters_an_edge_from_a_subgraph() {
   463              let graph = Graph::from([(1, vec![(2, 0), (3, 1)]), (2, vec![(3, 0), (1, 2)])]);
   464  
   465              let expected = Graph::from([(1, [(2, 0)]), (2, [(3, 0)])]);
   466              let actual = graph.filter_edges(|e| *e != 1).filter_edges(|e| *e != 2);
   467  
   468              assert_eq!(actual, expected);
   469          }
   470  
   471          #[test]
   472          fn filters_an_edge_from_a_vertex_filtered_subgraph() {
   473              let graph = Graph::from([(1, vec![(2, 0), (3, 1)]), (2, vec![(3, 0), (1, 2)])]);
   474  
   475              let expected = Graph::from([(1, vec![(2, 0)]), (2, vec![])]);
   476              let actual = graph.filter_vertices(|v| *v != 3).filter_edges(|e| *e != 2);
   477  
   478              assert_eq!(actual, expected);
   479          }
   480      }
   481  
   482      mod expand {
   483          use super::super::*;
   484  
   485          #[test]
   486          fn empty_graph() {
   487              let graph = Graph::<usize, usize>::new();
   488  
   489              let actual = graph.filter_vertices(|v| *v == 1).expand();
   490              let expected = Graph::<usize, usize>::new();
   491  
   492              assert_eq!(actual, expected);
   493          }
   494  
   495          #[test]
   496          fn single_vertex_graph() {
   497              let graph = Graph::<_, usize>::from([(1, [])]);
   498  
   499              let actual = graph.filter_vertices(|v| *v == 1).expand();
   500              let expected = Graph::<_, usize>::from([(1, [])]);
   501  
   502              assert_eq!(actual, expected);
   503          }
   504  
   505          #[test]
   506          fn single_child_of_one_vertex() {
   507              let graph = Graph::from([(1, [(2, 0)]), (3, [(2, 0)])]);
   508  
   509              let actual = graph.filter_vertices(|v| *v == 1).expand();
   510              let expected = Graph::from([(1, [(2, 0)])]);
   511  
   512              assert_eq!(actual, expected);
   513          }
   514  
   515          #[test]
   516          fn multiple_children_of_one_vertex() {
   517              let graph = Graph::from([(1, [(2, 0), (3, 0)])]);
   518  
   519              let actual = &graph.filter_vertices(|v| *v == 1).expand();
   520              let expected = &graph;
   521  
   522              assert_eq!(actual, expected);
   523          }
   524  
   525          #[test]
   526          fn all_descendants_of_one_vertex() {
   527              let graph = Graph::from([(1, [(2, 0), (3, 0)]), (2, [(3, 0), (4, 0)])]);
   528  
   529              let actual = &graph.filter_vertices(|v| *v == 1).expand();
   530              let expected = &graph;
   531  
   532              assert_eq!(actual, expected);
   533          }
   534  
   535          #[test]
   536          fn all_descendants_of_multiple_vertices() {
   537              let graph = Graph::from([
   538                  (1, vec![(4, 0), (5, 0)]),
   539                  (2, vec![(6, 0)]),
   540                  (3, vec![(8, 0), (9, 0)]),
   541                  (4, vec![(7, 0)]),
   542                  (7, vec![(8, 0)]),
   543                  (8, vec![(5, 0)]),
   544              ]);
   545  
   546              let actual = graph.filter_vertices(|v| *v == 1 || *v == 2).expand();
   547              let expected = Graph::from([
   548                  (1, vec![(4, 0), (5, 0)]),
   549                  (2, vec![(6, 0)]),
   550                  (4, vec![(7, 0)]),
   551                  (7, vec![(8, 0)]),
   552                  (8, vec![(5, 0)]),
   553              ]);
   554  
   555              assert_eq!(actual, expected);
   556          }
   557  
   558          #[test]
   559          fn all_descendants_via_edges_of_a_color() {
   560              let graph = Graph::from([
   561                  (1, vec![(4, 1), (5, 0)]),
   562                  (2, vec![(6, 1)]),
   563                  (3, vec![(8, 0), (9, 0)]),
   564                  (4, vec![(7, 1)]),
   565                  (7, vec![(8, 0)]),
   566                  (8, vec![(5, 0)]),
   567              ]);
   568  
   569              let actual = graph
   570                  .filter_vertices(|v| *v == 1 || *v == 2 || *v == 5)
   571                  .expand_via(|e| *e == 1);
   572              let expected = Graph::from([
   573                  (1, vec![(4, 1), (5, 0)]),
   574                  (2, vec![(6, 1)]),
   575                  (4, vec![(7, 1)]),
   576                  (5, vec![]),
   577                  (7, vec![]),
   578              ]);
   579  
   580              assert_eq!(actual, expected);
   581          }
   582      }
   583  
   584      mod reverse {
   585          use super::super::*;
   586  
   587          #[test]
   588          fn reverses_empty_graph() {
   589              let graph = Graph::<usize, usize>::new();
   590  
   591              let expected = Graph::<usize, usize>::new();
   592              let actual = graph.reverse();
   593  
   594              assert_eq!(actual, expected);
   595          }
   596  
   597          #[test]
   598          fn reverses_single_edge() {
   599              let graph = Graph::<usize, usize>::from([(1, [(2, 0)])]);
   600  
   601              let expected = Graph::<usize, usize>::from([(2, [(1, 0)])]);
   602              let actual = graph.reverse();
   603  
   604              assert_eq!(actual, expected);
   605          }
   606  
   607          #[test]
   608          fn reverses_a_fan() {
   609              let graph = Graph::<usize, usize>::from([(1, [(2, 0), (3, 1), (4, 0)])]);
   610  
   611              let expected =
   612                  Graph::<usize, usize>::from([(2, [(1, 0)]), (3, [(1, 1)]), (4, [(1, 0)])]);
   613              let actual = graph.reverse();
   614  
   615              assert_eq!(actual, expected);
   616          }
   617  
   618          #[test]
   619          fn reverses_a_complex_graph() {
   620              let graph = Graph::<usize, usize>::from([
   621                  (1, vec![(2, 0), (3, 1)]),
   622                  (2, vec![(3, 0)]),
   623                  (3, vec![(4, 0)]),
   624              ]);
   625  
   626              let expected = Graph::<usize, usize>::from([
   627                  (2, vec![(1, 0)]),
   628                  (3, vec![(1, 1), (2, 0)]),
   629                  (4, vec![(3, 0)]),
   630              ]);
   631              let actual = graph.reverse();
   632  
   633              assert_eq!(actual, expected);
   634          }
   635      }
   636  
   637      mod roots {
   638          use super::super::*;
   639  
   640          #[test]
   641          fn of_an_empty_graph() {
   642              let graph = Graph::<usize, usize>::new();
   643  
   644              let actual = graph.roots();
   645              let expected = Graph::<usize, usize>::new();
   646  
   647              assert_eq!(actual, expected);
   648          }
   649  
   650          #[test]
   651          fn of_a_single_edge() {
   652              let graph = Graph::from([(1, [(2, 0)])]);
   653  
   654              let actual = graph.roots();
   655              let expected = Graph::from([(1, [])]);
   656  
   657              assert_eq!(actual, expected);
   658          }
   659  
   660          #[test]
   661          fn of_a_complex_graph() {
   662              let graph = Graph::from([
   663                  (1, vec![(2, 0), (3, 0)]),
   664                  (2, vec![(3, 0)]),
   665                  (4, vec![(5, 0)]),
   666                  (5, vec![(6, 0)]),
   667                  (7, vec![(2, 0)]),
   668              ]);
   669  
   670              let actual = graph.roots();
   671              let expected = Graph::from([(1, vec![]), (4, vec![]), (7, vec![])]);
   672  
   673              assert_eq!(actual, expected);
   674          }
   675  
   676          #[test]
   677          fn of_a_subgraph() {
   678              let graph = Graph::from([
   679                  (1, vec![(2, 0), (3, 1)]),
   680                  (2, vec![(3, 1)]),
   681                  (4, vec![(5, 0)]),
   682                  (5, vec![(6, 0)]),
   683                  (7, vec![(2, 0)]),
   684              ]);
   685  
   686              let actual = graph
   687                  .filter_edges(|e| *e != 1)
   688                  .filter_vertices(|v| *v != 7)
   689                  .roots();
   690              let expected = Graph::from([(1, vec![]), (3, vec![]), (4, vec![])]);
   691  
   692              assert_eq!(actual, expected);
   693          }
   694      }
   695  }