src/Pure/General/graph.scala
changeset 73359 d8a0e996614b
parent 72065 11dc8929832d
child 73360 4123fca23296
equal deleted inserted replaced
73358:78aa7846e91f 73359:d8a0e996614b
    31 
    31 
    32   def make[Key, A](entries: List[((Key, A), List[Key])],
    32   def make[Key, A](entries: List[((Key, A), List[Key])],
    33     symmetric: Boolean = false)(implicit ord: Ordering[Key]): Graph[Key, A] =
    33     symmetric: Boolean = false)(implicit ord: Ordering[Key]): Graph[Key, A] =
    34   {
    34   {
    35     val graph1 =
    35     val graph1 =
    36       (empty[Key, A](ord) /: entries) { case (graph, ((x, info), _)) => graph.new_node(x, info) }
    36       entries.foldLeft(empty[Key, A](ord)) {
       
    37         case (graph, ((x, info), _)) => graph.new_node(x, info)
       
    38       }
    37     val graph2 =
    39     val graph2 =
    38       (graph1 /: entries) { case (graph, ((x, _), ys)) =>
    40       entries.foldLeft(graph1) {
    39         (graph /: ys)({ case (g, y) => if (symmetric) g.add_edge(y, x) else g.add_edge(x, y) }) }
    41         case (graph, ((x, _), ys)) =>
       
    42           ys.foldLeft(graph) {
       
    43             case (g, y) => if (symmetric) g.add_edge(y, x) else g.add_edge(x, y)
       
    44           }
       
    45       }
    40     graph2
    46     graph2
    41   }
    47   }
    42 
    48 
    43   def string[A]: Graph[String, A] = empty(Ordering.String)
    49   def string[A]: Graph[String, A] = empty(Ordering.String)
    44   def int[A]: Graph[Int, A] = empty(Ordering.Int)
    50   def int[A]: Graph[Int, A] = empty(Ordering.Int)
   117     next: Key => Keys,
   123     next: Key => Keys,
   118     xs: List[Key]): Map[Key, Long] =
   124     xs: List[Key]): Map[Key, Long] =
   119   {
   125   {
   120     def reach(length: Long)(rs: Map[Key, Long], x: Key): Map[Key, Long] =
   126     def reach(length: Long)(rs: Map[Key, Long], x: Key): Map[Key, Long] =
   121       if (rs.get(x) match { case Some(n) => n >= length case None => false }) rs
   127       if (rs.get(x) match { case Some(n) => n >= length case None => false }) rs
   122       else ((rs + (x -> length)) /: next(x))(reach(length + count(x)))
   128       else next(x).foldLeft(rs + (x -> length))(reach(length + count(x)))
   123     (Map.empty[Key, Long] /: xs)(reach(0))
   129     xs.foldLeft(Map.empty[Key, Long])(reach(0))
   124   }
   130   }
   125   def node_height(count: Key => Long): Map[Key, Long] =
   131   def node_height(count: Key => Long): Map[Key, Long] =
   126     reachable_length(count, imm_preds, maximals)
   132     reachable_length(count, imm_preds, maximals)
   127   def node_depth(count: Key => Long): Map[Key, Long] =
   133   def node_depth(count: Key => Long): Map[Key, Long] =
   128     reachable_length(count, imm_succs, minimals)
   134     reachable_length(count, imm_succs, minimals)
   136   {
   142   {
   137     def reach(res: (Long, Keys), x: Key): (Long, Keys) =
   143     def reach(res: (Long, Keys), x: Key): (Long, Keys) =
   138     {
   144     {
   139       val (n, rs) = res
   145       val (n, rs) = res
   140       if (rs.contains(x)) res
   146       if (rs.contains(x)) res
   141       else ((n + count(x), rs + x) /: next(x))(reach)
   147       else next(x).foldLeft((n + count(x), rs + x))(reach)
   142     }
   148     }
   143 
   149 
   144     @tailrec def reachs(size: Long, rs: Keys, rest: List[Key]): Keys =
   150     @tailrec def reachs(size: Long, rs: Keys, rest: List[Key]): Keys =
   145       rest match {
   151       rest match {
   146         case Nil => rs
   152         case Nil => rs
   160     {
   166     {
   161       val (rs, r_set) = reached
   167       val (rs, r_set) = reached
   162       if (r_set(x)) reached
   168       if (r_set(x)) reached
   163       else {
   169       else {
   164         val (rs1, r_set1) =
   170         val (rs1, r_set1) =
   165           if (rev) ((rs, r_set + x) /: next(x))({ case (b, a) => reach(a, b) })
   171           if (rev) next(x).foldLeft((rs, r_set + x)) { case (b, a) => reach(a, b) }
   166           else (next(x) :\ (rs, r_set + x))(reach)
   172           else (next(x) :\ (rs, r_set + x))(reach)
   167         (x :: rs1, r_set1)
   173         (x :: rs1, r_set1)
   168       }
   174       }
   169     }
   175     }
   170     def reachs(reached: (List[List[Key]], Keys), x: Key): (List[List[Key]], Keys) =
   176     def reachs(reached: (List[List[Key]], Keys), x: Key): (List[List[Key]], Keys) =
   171     {
   177     {
   172       val (rss, r_set) = reached
   178       val (rss, r_set) = reached
   173       val (rs, r_set1) = reach(x, (Nil, r_set))
   179       val (rs, r_set1) = reach(x, (Nil, r_set))
   174       (rs :: rss, r_set1)
   180       (rs :: rss, r_set1)
   175     }
   181     }
   176     ((List.empty[List[Key]], empty_keys) /: xs)(reachs)
   182     xs.foldLeft((List.empty[List[Key]], empty_keys))(reachs)
   177   }
   183   }
   178 
   184 
   179   /*immediate*/
   185   /*immediate*/
   180   def imm_preds(x: Key): Keys = get_entry(x)._2._1
   186   def imm_preds(x: Key): Keys = get_entry(x)._2._1
   181   def imm_succs(x: Key): Keys = get_entry(x)._2._2
   187   def imm_succs(x: Key): Keys = get_entry(x)._2._2
   193 
   199 
   194 
   200 
   195   /* minimal and maximal elements */
   201   /* minimal and maximal elements */
   196 
   202 
   197   def minimals: List[Key] =
   203   def minimals: List[Key] =
   198     (List.empty[Key] /: rep) {
   204     rep.foldLeft(List.empty[Key]) {
   199       case (ms, (m, (_, (preds, _)))) => if (preds.isEmpty) m :: ms else ms }
   205       case (ms, (m, (_, (preds, _)))) => if (preds.isEmpty) m :: ms else ms
       
   206     }
   200 
   207 
   201   def maximals: List[Key] =
   208   def maximals: List[Key] =
   202     (List.empty[Key] /: rep) {
   209     rep.foldLeft(List.empty[Key]) {
   203       case (ms, (m, (_, (_, succs)))) => if (succs.isEmpty) m :: ms else ms }
   210       case (ms, (m, (_, (_, succs)))) => if (succs.isEmpty) m :: ms else ms
       
   211     }
   204 
   212 
   205   def is_minimal(x: Key): Boolean = imm_preds(x).isEmpty
   213   def is_minimal(x: Key): Boolean = imm_preds(x).isEmpty
   206   def is_maximal(x: Key): Boolean = imm_succs(x).isEmpty
   214   def is_maximal(x: Key): Boolean = imm_succs(x).isEmpty
   207 
   215 
   208   def is_isolated(x: Key): Boolean = is_minimal(x) && is_maximal(x)
   216   def is_isolated(x: Key): Boolean = is_minimal(x) && is_maximal(x)
   229 
   237 
   230   def del_node(x: Key): Graph[Key, A] =
   238   def del_node(x: Key): Graph[Key, A] =
   231   {
   239   {
   232     val (preds, succs) = get_entry(x)._2
   240     val (preds, succs) = get_entry(x)._2
   233     new Graph[Key, A](
   241     new Graph[Key, A](
   234       (((rep - x) /: preds)(del_adjacent(false, x)) /: succs)(del_adjacent(true, x)))
   242       succs.foldLeft(preds.foldLeft(rep - x)(del_adjacent(false, x)))(del_adjacent(true, x)))
   235   }
   243   }
   236 
   244 
   237   def restrict(pred: Key => Boolean): Graph[Key, A] =
   245   def restrict(pred: Key => Boolean): Graph[Key, A] =
   238     (this /: iterator){ case (graph, (x, _)) => if (!pred(x)) graph.del_node(x) else graph }
   246     iterator.foldLeft(this) { case (graph, (x, _)) => if (!pred(x)) graph.del_node(x) else graph }
   239 
   247 
   240   def exclude(pred: Key => Boolean): Graph[Key, A] = restrict(name => !pred(name))
   248   def exclude(pred: Key => Boolean): Graph[Key, A] = restrict(name => !pred(name))
   241 
   249 
   242 
   250 
   243   /* edge operations */
   251   /* edge operations */
   281   def irreducible_paths(x: Key, y: Key): List[List[Key]] =
   289   def irreducible_paths(x: Key, y: Key): List[List[Key]] =
   282   {
   290   {
   283     val (_, x_set) = reachable(imm_succs, List(x))
   291     val (_, x_set) = reachable(imm_succs, List(x))
   284     def paths(path: List[Key])(ps: List[List[Key]], z: Key): List[List[Key]] =
   292     def paths(path: List[Key])(ps: List[List[Key]], z: Key): List[List[Key]] =
   285       if (x == z) (z :: path) :: ps
   293       if (x == z) (z :: path) :: ps
   286       else (ps /: irreducible_preds(x_set, path, z))(paths(z :: path))
   294       else irreducible_preds(x_set, path, z).foldLeft(ps)(paths(z :: path))
   287     if ((x == y) && !is_edge(x, x)) List(Nil) else paths(Nil)(Nil, y)
   295     if ((x == y) && !is_edge(x, x)) List(Nil) else paths(Nil)(Nil, y)
   288   }
   296   }
   289 
   297 
   290 
   298 
   291   /* transitive closure and reduction */
   299   /* transitive closure and reduction */
   296     var graph = this
   304     var graph = this
   297     for (x <- preds; y <- succs) graph = graph.add_edge(x, y)
   305     for (x <- preds; y <- succs) graph = graph.add_edge(x, y)
   298     graph
   306     graph
   299   }
   307   }
   300 
   308 
   301   def transitive_closure: Graph[Key, A] = (this /: keys_iterator)(_.transitive_step(_))
   309   def transitive_closure: Graph[Key, A] = keys_iterator.foldLeft(this)(_.transitive_step(_))
   302 
   310 
   303   def transitive_reduction_acyclic: Graph[Key, A] =
   311   def transitive_reduction_acyclic: Graph[Key, A] =
   304   {
   312   {
   305     val trans = this.transitive_closure
   313     val trans = this.transitive_closure
   306     if (trans.iterator.exists({ case (x, (_, (_, succs))) => succs.contains(x) }))
   314     if (trans.iterator.exists({ case (x, (_, (_, succs))) => succs.contains(x) }))
   326         case cycles => throw new Graph.Cycles(cycles.map(x :: _))
   334         case cycles => throw new Graph.Cycles(cycles.map(x :: _))
   327       }
   335       }
   328     }
   336     }
   329 
   337 
   330   def add_deps_acyclic(y: Key, xs: List[Key]): Graph[Key, A] =
   338   def add_deps_acyclic(y: Key, xs: List[Key]): Graph[Key, A] =
   331     (this /: xs)(_.add_edge_acyclic(_, y))
   339     xs.foldLeft(this)(_.add_edge_acyclic(_, y))
   332 
   340 
   333   def topological_order: List[Key] = all_succs(minimals)
   341   def topological_order: List[Key] = all_succs(minimals)
   334 }
   342 }