1pub mod dominators;
8
9use std::collections::BinaryHeap;
10use std::cmp::min;
11
12use prelude::*;
13
14use super::{
15 EdgeType,
16};
17use scored::MinScored;
18use super::visit::{
19 GraphRef,
20 GraphBase,
21 Visitable,
22 VisitMap,
23 IntoNeighbors,
24 IntoNeighborsDirected,
25 IntoNodeIdentifiers,
26 NodeCount,
27 NodeIndexable,
28 NodeCompactIndexable,
29 IntoEdgeReferences,
30 IntoEdges,
31 Reversed,
32};
33use super::unionfind::UnionFind;
34use super::graph::{
35 IndexType,
36};
37use visit::{Data, NodeRef, IntoNodeReferences};
38use data::{
39 Element,
40};
41
42pub use super::isomorphism::{
43 is_isomorphic,
44 is_isomorphic_matching,
45};
46pub use super::dijkstra::dijkstra;
47pub use super::astar::astar;
48
49pub fn connected_components<G>(g: G) -> usize
53 where G: NodeCompactIndexable + IntoEdgeReferences,
54{
55 let mut vertex_sets = UnionFind::new(g.node_bound());
56 for edge in g.edge_references() {
57 let (a, b) = (edge.source(), edge.target());
58
59 vertex_sets.union(g.to_index(a), g.to_index(b));
61 }
62 let mut labels = vertex_sets.into_labeling();
63 labels.sort();
64 labels.dedup();
65 labels.len()
66}
67
68
69pub fn is_cyclic_undirected<G>(g: G) -> bool
73 where G: NodeIndexable + IntoEdgeReferences
74{
75 let mut edge_sets = UnionFind::new(g.node_bound());
76 for edge in g.edge_references() {
77 let (a, b) = (edge.source(), edge.target());
78
79 if !edge_sets.union(g.to_index(a), g.to_index(b)) {
82 return true
83 }
84 }
85 false
86}
87
88
89pub fn toposort<G>(g: G, space: Option<&mut DfsSpace<G::NodeId, G::Map>>)
101 -> Result<Vec<G::NodeId>, Cycle<G::NodeId>>
102 where G: IntoNeighborsDirected + IntoNodeIdentifiers + Visitable,
103{
104 with_dfs(g, space, |dfs| {
106 dfs.reset(g);
107 let mut finished = g.visit_map();
108
109 let mut finish_stack = Vec::new();
110 for i in g.node_identifiers() {
111 if dfs.discovered.is_visited(&i) {
112 continue;
113 }
114 dfs.stack.push(i);
115 while let Some(&nx) = dfs.stack.last() {
116 if dfs.discovered.visit(nx) {
117 for succ in g.neighbors(nx) {
119 if succ == nx {
120 return Err(Cycle(nx));
122 }
123 if !dfs.discovered.is_visited(&succ) {
124 dfs.stack.push(succ);
125 }
126 }
127 } else {
128 dfs.stack.pop();
129 if finished.visit(nx) {
130 finish_stack.push(nx);
132 }
133 }
134 }
135 }
136 finish_stack.reverse();
137
138 dfs.reset(g);
139 for &i in &finish_stack {
140 dfs.move_to(i);
141 let mut cycle = false;
142 while let Some(j) = dfs.next(Reversed(g)) {
143 if cycle {
144 return Err(Cycle(j));
145 }
146 cycle = true;
147 }
148 }
149
150 Ok(finish_stack)
151 })
152}
153
154pub fn is_cyclic_directed<G>(g: G) -> bool
159 where G: IntoNodeIdentifiers + IntoNeighbors + Visitable,
160{
161 use visit::{depth_first_search, DfsEvent};
162
163 depth_first_search(g, g.node_identifiers(), |event| {
164 match event {
165 DfsEvent::BackEdge(_, _) => Err(()),
166 _ => Ok(()),
167 }
168 }).is_err()
169}
170
171type DfsSpaceType<G> = DfsSpace<<G as GraphBase>::NodeId, <G as Visitable>::Map>;
172
173#[derive(Clone, Debug)]
175pub struct DfsSpace<N, VM> {
176 dfs: Dfs<N, VM>,
177}
178
179impl<N, VM> DfsSpace<N, VM>
180 where N: Copy + PartialEq,
181 VM: VisitMap<N>,
182{
183 pub fn new<G>(g: G) -> Self
184 where G: GraphRef + Visitable<NodeId=N, Map=VM>,
185 {
186 DfsSpace {
187 dfs: Dfs::empty(g)
188 }
189 }
190}
191
192impl<N, VM> Default for DfsSpace<N, VM>
193 where VM: VisitMap<N> + Default,
194{
195 fn default() -> Self {
196 DfsSpace {
197 dfs: Dfs {
198 stack: <_>::default(),
199 discovered: <_>::default(),
200 }
201 }
202 }
203}
204
205fn with_dfs<G, F, R>(g: G, space: Option<&mut DfsSpaceType<G>>, f: F) -> R
207 where G: GraphRef + Visitable,
208 F: FnOnce(&mut Dfs<G::NodeId, G::Map>) -> R
209{
210 let mut local_visitor;
211 let dfs = if let Some(v) = space { &mut v.dfs } else {
212 local_visitor = Dfs::empty(g);
213 &mut local_visitor
214 };
215 f(dfs)
216}
217
218pub fn has_path_connecting<G>(g: G, from: G::NodeId, to: G::NodeId,
225 space: Option<&mut DfsSpace<G::NodeId, G::Map>>)
226 -> bool
227 where G: IntoNeighbors + Visitable,
228{
229 with_dfs(g, space, |dfs| {
230 dfs.reset(g);
231 dfs.move_to(from);
232 while let Some(x) = dfs.next(g) {
233 if x == to {
234 return true;
235 }
236 }
237 false
238 })
239}
240
241#[deprecated(note = "renamed to kosaraju_scc")]
243pub fn scc<G>(g: G) -> Vec<Vec<G::NodeId>>
244 where G: IntoNeighborsDirected + Visitable + IntoNodeIdentifiers,
245{
246 kosaraju_scc(g)
247}
248
249pub fn kosaraju_scc<G>(g: G) -> Vec<Vec<G::NodeId>>
261 where G: IntoNeighborsDirected + Visitable + IntoNodeIdentifiers,
262{
263 let mut dfs = DfsPostOrder::empty(g);
264
265 let mut finish_order = Vec::with_capacity(0);
268 for i in g.node_identifiers() {
269 if dfs.discovered.is_visited(&i) {
270 continue
271 }
272
273 dfs.move_to(i);
274 while let Some(nx) = dfs.next(Reversed(g)) {
275 finish_order.push(nx);
276 }
277 }
278
279 let mut dfs = Dfs::from_parts(dfs.stack, dfs.discovered);
280 dfs.reset(g);
281 let mut sccs = Vec::new();
282
283 for i in finish_order.into_iter().rev() {
286 if dfs.discovered.is_visited(&i) {
287 continue;
288 }
289 dfs.move_to(i);
291 let mut scc = Vec::new();
292 while let Some(nx) = dfs.next(g) {
293 scc.push(nx);
294 }
295 sccs.push(scc);
296 }
297 sccs
298}
299
300pub fn tarjan_scc<G>(g: G) -> Vec<Vec<G::NodeId>>
312 where G: IntoNodeIdentifiers + IntoNeighbors + NodeIndexable
313{
314 #[derive(Copy, Clone)]
315 #[derive(Debug)]
316 struct NodeData {
317 index: Option<usize>,
318 lowlink: usize,
319 on_stack: bool,
320 }
321
322 #[derive(Debug)]
323 struct Data<'a, G>
324 where G: NodeIndexable,
325 G::NodeId: 'a
326 {
327 index: usize,
328 nodes: Vec<NodeData>,
329 stack: Vec<G::NodeId>,
330 sccs: &'a mut Vec<Vec<G::NodeId>>,
331 }
332
333 fn scc_visit<G>(v: G::NodeId, g: G, data: &mut Data<G>)
334 where G: IntoNeighbors + NodeIndexable
335 {
336 macro_rules! node {
337 ($node:expr) => (data.nodes[g.to_index($node)])
338 }
339
340 if node![v].index.is_some() {
341 return;
343 }
344
345 let v_index = data.index;
346 node![v].index = Some(v_index);
347 node![v].lowlink = v_index;
348 node![v].on_stack = true;
349 data.stack.push(v);
350 data.index += 1;
351
352 for w in g.neighbors(v) {
353 match node![w].index {
354 None => {
355 scc_visit(w, g, data);
356 node![v].lowlink = min(node![v].lowlink, node![w].lowlink);
357 }
358 Some(w_index) => {
359 if node![w].on_stack {
360 let v_lowlink = &mut node![v].lowlink;
362 *v_lowlink = min(*v_lowlink, w_index);
363 }
364 }
365 }
366 }
367
368 if let Some(v_index) = node![v].index {
370 if node![v].lowlink == v_index {
371 let mut cur_scc = Vec::new();
372 loop {
373 let w = data.stack.pop().unwrap();
374 node![w].on_stack = false;
375 cur_scc.push(w);
376 if g.to_index(w) == g.to_index(v) { break; }
377 }
378 data.sccs.push(cur_scc);
379 }
380 }
381 }
382
383 let mut sccs = Vec::new();
384 {
385 let map = vec![NodeData { index: None, lowlink: !0, on_stack: false }; g.node_bound()];
386
387 let mut data = Data {
388 index: 0,
389 nodes: map,
390 stack: Vec::new(),
391 sccs: &mut sccs,
392 };
393
394 for n in g.node_identifiers() {
395 scc_visit(n, g, &mut data);
396 }
397 }
398 sccs
399}
400
401pub fn condensation<N, E, Ty, Ix>(g: Graph<N, E, Ty, Ix>, make_acyclic: bool) -> Graph<Vec<N>, E, Ty, Ix>
406 where Ty: EdgeType,
407 Ix: IndexType,
408{
409 let sccs = kosaraju_scc(&g);
410 let mut condensed: Graph<Vec<N>, E, Ty, Ix> = Graph::with_capacity(sccs.len(), g.edge_count());
411
412 let mut node_map = vec![NodeIndex::end(); g.node_count()];
414 for comp in sccs {
415 let new_nix = condensed.add_node(Vec::new());
416 for nix in comp {
417 node_map[nix.index()] = new_nix;
418 }
419 }
420
421 let (nodes, edges) = g.into_nodes_edges();
423 for (nix, node) in nodes.into_iter().enumerate() {
424 condensed[node_map[nix]].push(node.weight);
425 }
426 for edge in edges {
427 let source = node_map[edge.source().index()];
428 let target = node_map[edge.target().index()];
429 if make_acyclic {
430 if source != target {
431 condensed.update_edge(source, target, edge.weight);
432 }
433 } else {
434 condensed.add_edge(source, target, edge.weight);
435 }
436 }
437 condensed
438}
439
440pub fn min_spanning_tree<G>(g: G) -> MinSpanningTree<G>
453 where G::NodeWeight: Clone,
454 G::EdgeWeight: Clone + PartialOrd,
455 G: IntoNodeReferences + IntoEdgeReferences + NodeIndexable,
456{
457
458 let subgraphs = UnionFind::new(g.node_bound());
461
462 let edges = g.edge_references();
463 let mut sort_edges = BinaryHeap::with_capacity(edges.size_hint().0);
464 for edge in edges {
465 sort_edges.push(MinScored(edge.weight().clone(), (edge.source(), edge.target())));
466 }
467
468 MinSpanningTree {
469 graph: g,
470 node_ids: Some(g.node_references()),
471 subgraphs: subgraphs,
472 sort_edges: sort_edges,
473 }
474
475}
476
477pub struct MinSpanningTree<G>
479 where G: Data + IntoNodeReferences,
480{
481 graph: G,
482 node_ids: Option<G::NodeReferences>,
483 subgraphs: UnionFind<usize>,
484 sort_edges: BinaryHeap<MinScored<G::EdgeWeight, (G::NodeId, G::NodeId)>>,
485}
486
487
488impl<G> Iterator for MinSpanningTree<G>
489 where G: IntoNodeReferences + NodeIndexable,
490 G::NodeWeight: Clone,
491 G::EdgeWeight: PartialOrd,
492{
493 type Item = Element<G::NodeWeight, G::EdgeWeight>;
494
495 fn next(&mut self) -> Option<Self::Item> {
496 if let Some(ref mut iter) = self.node_ids {
497 if let Some(node) = iter.next() {
498 return Some(Element::Node { weight: node.weight().clone() });
499 }
500 }
501 self.node_ids = None;
502
503 while let Some(MinScored(score, (a, b))) = self.sort_edges.pop() {
513 let g = self.graph;
514 if self.subgraphs.union(g.to_index(a), g.to_index(b)) {
516 return Some(Element::Edge {
517 source: g.to_index(a),
518 target: g.to_index(b),
519 weight: score,
520 });
521 }
522 }
523 None
524 }
525}
526
527#[derive(Clone, Debug, PartialEq)]
529pub struct Cycle<N>(N);
530
531impl<N> Cycle<N> {
532 pub fn node_id(&self) -> N
534 where N: Copy
535 {
536 self.0
537 }
538}
539#[derive(Clone, Debug, PartialEq)]
541pub struct NegativeCycle(());
542
543pub fn bellman_ford<G>(g: G, source: G::NodeId)
555 -> Result<(Vec<G::EdgeWeight>, Vec<Option<G::NodeId>>), NegativeCycle>
556 where G: NodeCount + IntoNodeIdentifiers + IntoEdges + NodeIndexable,
557 G::EdgeWeight: FloatMeasure,
558{
559 let mut predecessor = vec![None; g.node_bound()];
560 let mut distance = vec![<_>::infinite(); g.node_bound()];
561
562 let ix = |i| g.to_index(i);
563
564 distance[ix(source)] = <_>::zero();
565 for _ in 1..g.node_count() {
567 let mut did_update = false;
568 for i in g.node_identifiers() {
569 for edge in g.edges(i) {
570 let i = edge.source();
571 let j = edge.target();
572 let w = *edge.weight();
573 if distance[ix(i)] + w < distance[ix(j)] {
574 distance[ix(j)] = distance[ix(i)] + w;
575 predecessor[ix(j)] = Some(i);
576 did_update = true;
577 }
578 }
579 }
580 if !did_update {
581 break;
582 }
583 }
584
585 for i in g.node_identifiers() {
587 for edge in g.edges(i) {
588 let j = edge.target();
589 let w = *edge.weight();
590 if distance[ix(i)] + w < distance[ix(j)] {
591 return Err(NegativeCycle(()));
593 }
594 }
595 }
596
597 Ok((distance, predecessor))
598}
599
600use std::ops::Add;
601use std::fmt::Debug;
602
603pub trait Measure : Debug + PartialOrd + Add<Self, Output=Self> + Default + Clone {
605}
606
607impl<M> Measure for M
608 where M: Debug + PartialOrd + Add<M, Output=M> + Default + Clone,
609{ }
610
611pub trait FloatMeasure : Measure + Copy {
613 fn zero() -> Self;
614 fn infinite() -> Self;
615}
616
617impl FloatMeasure for f32 {
618 fn zero() -> Self { 0. }
619 fn infinite() -> Self { 1./0. }
620}
621
622impl FloatMeasure for f64 {
623 fn zero() -> Self { 0. }
624 fn infinite() -> Self { 1./0. }
625}
626