use of edu.mit.csail.sdg.alloy4.DirectedGraph in project org.alloytools.alloy by AlloyTools.
the class ExprUnary method resolveClosure.
// ============================================================================================================//
/**
* Helper method that computes the relevant type for a closure expression.
* <p>
* Return Value == { c1->c2 | c1->c2 in childType, AND exists p1->p2 in
* parentType where p1..c1..c2..p2 is a path in the closure graph }
* <p>
* We need to do this because of situations like this follow: Suppose e's type
* is "A->B + B->C". Therefore, ^e = A->B + B->C + A->C which makes sense. But
* as we compute the relevance type back down, we may have lost some entries,
* and possibly end up with only A->B + A->C so we need to rediscover the
* relevant edges.
*/
private static Type resolveClosure(Type parent, Type child) {
LinkedHashSet<PrimSig> nodes = new LinkedHashSet<PrimSig>();
DirectedGraph<PrimSig> graph = new DirectedGraph<PrimSig>();
// For each (v1->v2) in childType, add (v1->v2) into the graph.
for (ProductType c : child) if (c.arity() == 2) {
PrimSig a = c.get(0), b = c.get(1);
nodes.add(a);
nodes.add(b);
graph.addEdge(a, b);
}
// edges v1->v2 and v2->v1.
for (PrimSig a : nodes) for (PrimSig b : nodes) if (a != b && a.intersects(b))
graph.addEdge(a, b);
// them.
for (ProductType p : parent) if (p.arity() == 2) {
PrimSig a = p.get(0), b = p.get(1);
// Add edges between a and all its subtypes and supertypes
if (!nodes.contains(a)) {
for (PrimSig x : nodes) if (a.intersects(x)) {
graph.addEdge(a, x);
graph.addEdge(x, a);
}
nodes.add(a);
}
// Add edges between b and all its subtypes and supertypes
if (!nodes.contains(b)) {
for (PrimSig x : nodes) if (b.intersects(x)) {
graph.addEdge(b, x);
graph.addEdge(x, b);
}
nodes.add(b);
}
}
// For each c1->c2 in childType, add c1->c2 into the finalType if there
// exists p1->p2 in parentType
// such that p1->..->c1->c2->..->p2 is a path in the graph.
Type answer = Type.EMPTY;
for (ProductType c : child) if (c.arity() == 2) {
PrimSig c1 = c.get(0), c2 = c.get(1);
for (ProductType p : parent) if (p.arity() == 2) {
PrimSig p1 = p.get(0), p2 = p.get(1);
if (graph.hasPath(p1, c1) && graph.hasPath(c2, p2)) {
answer = answer.merge(c);
break;
}
}
}
return answer;
}
Aggregations