use of org.batfish.symbolic.answers.SmtDeterminismAnswerElement in project batfish by batfish.
the class PropertyChecker method checkDeterminism.
/*
* Check if there exist multiple stable solutions to the network.
* If so, reports the forwarding differences between the two cases.
*/
public AnswerElement checkDeterminism(HeaderQuestion q) {
Graph graph = new Graph(_batfish);
Encoder enc1 = new Encoder(_settings, graph, q);
Encoder enc2 = new Encoder(enc1, graph, q);
enc1.computeEncoding();
enc2.computeEncoding();
addEnvironmentConstraints(enc1, q.getBaseEnvironmentType());
BoolExpr relatedFailures = relateFailures(enc1, enc2);
BoolExpr relatedEnvs = relateEnvironments(enc1, enc2);
BoolExpr relatedPkts = relatePackets(enc1, enc2);
BoolExpr related = enc1.mkAnd(relatedFailures, relatedEnvs, relatedPkts);
BoolExpr required = enc1.mkTrue();
for (GraphEdge ge : graph.getAllRealEdges()) {
SymbolicDecisions d1 = enc1.getMainSlice().getSymbolicDecisions();
SymbolicDecisions d2 = enc2.getMainSlice().getSymbolicDecisions();
BoolExpr dataFwd1 = d1.getDataForwarding().get(ge.getRouter(), ge);
BoolExpr dataFwd2 = d2.getDataForwarding().get(ge.getRouter(), ge);
assert dataFwd1 != null;
assert dataFwd2 != null;
required = enc1.mkAnd(required, enc1.mkEq(dataFwd1, dataFwd2));
}
enc1.add(related);
enc1.add(enc1.mkNot(required));
Tuple<VerificationResult, Model> tup = enc1.verify();
VerificationResult res = tup.getFirst();
Model model = tup.getSecond();
SortedSet<String> case1 = null;
SortedSet<String> case2 = null;
Flow flow = null;
CounterExample ce = new CounterExample(model);
if (!res.isVerified()) {
case1 = new TreeSet<>();
case2 = new TreeSet<>();
flow = ce.buildFlow(enc1.getMainSlice().getSymbolicPacket(), "(none)");
for (GraphEdge ge : graph.getAllRealEdges()) {
SymbolicDecisions d1 = enc1.getMainSlice().getSymbolicDecisions();
SymbolicDecisions d2 = enc2.getMainSlice().getSymbolicDecisions();
BoolExpr dataFwd1 = d1.getDataForwarding().get(ge.getRouter(), ge);
BoolExpr dataFwd2 = d2.getDataForwarding().get(ge.getRouter(), ge);
assert dataFwd1 != null;
assert dataFwd2 != null;
boolean b1 = ce.boolVal(dataFwd1);
boolean b2 = ce.boolVal(dataFwd2);
if (b1 != b2) {
if (b1) {
String route = ce.buildRoute(enc1.getMainSlice(), ge);
String msg = ge + " -- " + route;
case1.add(msg);
}
if (b2) {
String route = ce.buildRoute(enc2.getMainSlice(), ge);
String msg = ge + " -- " + route;
case2.add(msg);
}
}
}
}
// Ensure canonical order
boolean less = (case1 == null || (case1.first().compareTo(case2.first()) < 0));
if (less) {
return new SmtDeterminismAnswerElement(flow, case1, case2);
} else {
return new SmtDeterminismAnswerElement(flow, case2, case1);
}
}