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;
}
}
}