package jetbrains.mps.internal.make.runtime.util; /*Generated by MPS */ import java.util.Map; import jetbrains.mps.internal.collections.runtime.MapSequence; import java.util.HashMap; import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; import jetbrains.mps.internal.collections.runtime.ISequence; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.internal.collections.runtime.ISelector; import java.util.List; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import jetbrains.mps.internal.collections.runtime.IVisitor; import jetbrains.mps.internal.collections.runtime.IWhereFilter; public abstract class GraphAnalyzer<V> { private Map<V, GraphAnalyzer.Wrapper<V>> wrapMap = MapSequence.fromMap(new HashMap<V, GraphAnalyzer.Wrapper<V>>()); private _FunctionTypes._return_P1_E0<? extends Iterable<GraphAnalyzer.Wrapper<V>>, ? super GraphAnalyzer.Wrapper<V>> forward = new _FunctionTypes._return_P1_E0<ISequence<GraphAnalyzer.Wrapper<V>>, GraphAnalyzer.Wrapper<V>>() { public ISequence<GraphAnalyzer.Wrapper<V>> invoke(GraphAnalyzer.Wrapper<V> d) { return Sequence.fromIterable(forwardEdges(d.vertex)).select(new ISelector<V, GraphAnalyzer.Wrapper<V>>() { public GraphAnalyzer.Wrapper<V> select(V v) { return MapSequence.fromMap(wrapMap).get(v); } }); } }; private _FunctionTypes._return_P1_E0<? extends Iterable<GraphAnalyzer.Wrapper<V>>, ? super GraphAnalyzer.Wrapper<V>> backward = new _FunctionTypes._return_P1_E0<ISequence<GraphAnalyzer.Wrapper<V>>, GraphAnalyzer.Wrapper<V>>() { public ISequence<GraphAnalyzer.Wrapper<V>> invoke(GraphAnalyzer.Wrapper<V> d) { return Sequence.fromIterable(backwardEdges(d.vertex)).select(new ISelector<V, GraphAnalyzer.Wrapper<V>>() { public GraphAnalyzer.Wrapper<V> select(V v) { return MapSequence.fromMap(wrapMap).get(v); } }); } }; public GraphAnalyzer() { } public abstract Iterable<V> vertices(); public abstract Iterable<V> forwardEdges(V v); public abstract Iterable<V> backwardEdges(V v); public List<List<V>> findCycles() { Iterable<GraphAnalyzer.Wrapper<V>> ws = this.init(vertices()); return this.collectCycles(this.topoSort(ws), false); } public List<List<V>> totalOrder() { Iterable<GraphAnalyzer.Wrapper<V>> ws = this.init(vertices()); return this.collectCycles(this.topoSort(ws), true); } public Iterable<V> topologicalSort() { Iterable<GraphAnalyzer.Wrapper<V>> ws = this.init(vertices()); return ListSequence.fromList(this.topoSort(ws)).select(new ISelector<GraphAnalyzer.Wrapper<V>, V>() { public V select(GraphAnalyzer.Wrapper<V> w) { return w.vertex; } }); } public Iterable<V> precursors(V v) { Iterable<GraphAnalyzer.Wrapper<V>> ws = this.init(vertices()); return ListSequence.fromList(this.reachable(MapSequence.fromMap(wrapMap).get(v), ws, backward)).select(new ISelector<GraphAnalyzer.Wrapper<V>, V>() { public V select(GraphAnalyzer.Wrapper<V> w) { return w.vertex; } }); } private Iterable<GraphAnalyzer.Wrapper<V>> init(Iterable<V> vertices) { return Sequence.fromIterable(vertices).select(new ISelector<V, GraphAnalyzer.Wrapper<V>>() { public GraphAnalyzer.Wrapper<V> select(V v) { GraphAnalyzer.Wrapper<V> data = new GraphAnalyzer.Wrapper<V>(v); MapSequence.fromMap(wrapMap).put(v, data); return data; } }).toListSequence(); } private List<GraphAnalyzer.Wrapper<V>> topoSort(Iterable<GraphAnalyzer.Wrapper<V>> ws) { final List<GraphAnalyzer.Wrapper<V>> res = ListSequence.fromList(new ArrayList<GraphAnalyzer.Wrapper<V>>()); dfs(ws, new _FunctionTypes._void_P2_E0<GraphAnalyzer.Wrapper<V>, _FunctionTypes._void_P0_E0>() { public void invoke(GraphAnalyzer.Wrapper<V> w, _FunctionTypes._void_P0_E0 cont) { cont.invoke(); ListSequence.fromList(res).addElement(w); } }, forward); return ListSequence.fromList(res).reversedList(); } public List<GraphAnalyzer.Wrapper<V>> reachable(GraphAnalyzer.Wrapper<V> from, Iterable<GraphAnalyzer.Wrapper<V>> ws, _FunctionTypes._return_P1_E0<? extends Iterable<GraphAnalyzer.Wrapper<V>>, ? super GraphAnalyzer.Wrapper<V>> edges) { final List<GraphAnalyzer.Wrapper<V>> res = ListSequence.fromList(new ArrayList<GraphAnalyzer.Wrapper<V>>()); Sequence.fromIterable(ws).visitAll(new IVisitor<GraphAnalyzer.Wrapper<V>>() { public void visit(GraphAnalyzer.Wrapper<V> w) { w.clear(); } }); dfsVisit(from, new _FunctionTypes._void_P2_E0<GraphAnalyzer.Wrapper<V>, _FunctionTypes._void_P0_E0>() { public void invoke(GraphAnalyzer.Wrapper<V> ww, _FunctionTypes._void_P0_E0 cont) { cont.invoke(); ListSequence.fromList(res).addElement(ww); } }, edges); return res; } private List<List<V>> collectCycles(Iterable<GraphAnalyzer.Wrapper<V>> ws, final boolean trivial) { final List<List<V>> cycles = ListSequence.fromList(new ArrayList<List<V>>()); Sequence.fromIterable(ws).visitAll(new IVisitor<GraphAnalyzer.Wrapper<V>>() { public void visit(GraphAnalyzer.Wrapper<V> w) { w.clear(); } }); Sequence.fromIterable(ws).where(new IWhereFilter<GraphAnalyzer.Wrapper<V>>() { public boolean accept(GraphAnalyzer.Wrapper<V> w) { return !(w.entered); } }).visitAll(new IVisitor<GraphAnalyzer.Wrapper<V>>() { public void visit(final GraphAnalyzer.Wrapper<V> w) { dfsVisit(w, new _FunctionTypes._void_P2_E0<GraphAnalyzer.Wrapper<V>, _FunctionTypes._void_P0_E0>() { public void invoke(GraphAnalyzer.Wrapper<V> ww, _FunctionTypes._void_P0_E0 cont) { cont.invoke(); if (w != ww || Sequence.fromIterable(backward.invoke(ww)).contains(ww)) { w.successor(ww); } } }, backward); if (trivial || ListSequence.fromList(w.successors).isNotEmpty()) { ListSequence.fromList(cycles).addElement(collectSuccessors(w, ListSequence.fromListAndArray(new ArrayList<V>(), w.vertex))); } } }); return cycles; } private List<V> collectSuccessors(final GraphAnalyzer.Wrapper<V> w, final List<V> list) { ListSequence.fromList(w.successors).visitAll(new IVisitor<GraphAnalyzer.Wrapper<V>>() { public void visit(GraphAnalyzer.Wrapper<V> ww) { if (w != ww) { ListSequence.fromList(list).addElement(ww.vertex); collectSuccessors(ww, list); } } }); return list; } private void dfs(Iterable<GraphAnalyzer.Wrapper<V>> ws, final _FunctionTypes._void_P2_E0<? super GraphAnalyzer.Wrapper<V>, ? super _FunctionTypes._void_P0_E0> visitor, final _FunctionTypes._return_P1_E0<? extends Iterable<GraphAnalyzer.Wrapper<V>>, ? super GraphAnalyzer.Wrapper<V>> edges) { Sequence.fromIterable(ws).visitAll(new IVisitor<GraphAnalyzer.Wrapper<V>>() { public void visit(GraphAnalyzer.Wrapper<V> w) { w.clear(); } }); Sequence.fromIterable(ws).where(new IWhereFilter<GraphAnalyzer.Wrapper<V>>() { public boolean accept(GraphAnalyzer.Wrapper<V> w) { return !(w.entered); } }).visitAll(new IVisitor<GraphAnalyzer.Wrapper<V>>() { public void visit(GraphAnalyzer.Wrapper<V> w) { dfsVisit(w, visitor, edges); } }); } private void dfsVisit(final GraphAnalyzer.Wrapper<V> w, final _FunctionTypes._void_P2_E0<? super GraphAnalyzer.Wrapper<V>, ? super _FunctionTypes._void_P0_E0> visitor, final _FunctionTypes._return_P1_E0<? extends Iterable<GraphAnalyzer.Wrapper<V>>, ? super GraphAnalyzer.Wrapper<V>> edges) { w.enter(); visitor.invoke(w, new _FunctionTypes._void_P0_E0() { public void invoke() { Sequence.fromIterable(edges.invoke(w)).where(new IWhereFilter<GraphAnalyzer.Wrapper<V>>() { public boolean accept(GraphAnalyzer.Wrapper<V> ww) { return !(ww.entered); } }).visitAll(new IVisitor<GraphAnalyzer.Wrapper<V>>() { public void visit(GraphAnalyzer.Wrapper<V> ww) { dfsVisit(ww, visitor, edges); } }); } }); w.exit(); } private static class Wrapper<V> { private V vertex; private boolean entered = false; private boolean exited = false; private List<GraphAnalyzer.Wrapper<V>> successors = ListSequence.fromList(new ArrayList<GraphAnalyzer.Wrapper<V>>()); private Wrapper(V v) { this.vertex = v; } private void successor(GraphAnalyzer.Wrapper<V> succ) { ListSequence.fromList(this.successors).addElement(succ); } private void enter() { this.entered = true; } private void exit() { this.exited = true; } private void clear() { this.entered = false; this.exited = false; } } }