use of com.microsoft.z3.ArithExpr in project batfish by batfish.
the class TransferSSA method joinPoint.
/*
* The [phi] function from SSA that merges variables that may differ across
* different branches of an mkIf statement.
*/
private Pair<Expr, Expr> joinPoint(TransferParam<SymbolicRoute> p, TransferResult<BoolExpr, BoolExpr> r, BoolExpr guard, Pair<String, Pair<Expr, Expr>> values) {
String variableName = values.getFirst();
Expr trueBranch = values.getSecond().getFirst();
Expr falseBranch = values.getSecond().getSecond();
if (variableName.equals("RETURN") || variableName.equals("FALLTHROUGH")) {
Expr t = (trueBranch == null ? _enc.mkFalse() : // can use False because the value has not been assigned
trueBranch);
Expr f = (falseBranch == null ? _enc.mkFalse() : falseBranch);
Expr tass = (trueBranch == null ? r.getReturnAssignedValue() : _enc.mkTrue());
Expr fass = (falseBranch == null ? r.getReturnAssignedValue() : _enc.mkTrue());
BoolExpr newAss = _enc.mkIf(guard, (BoolExpr) tass, (BoolExpr) fass);
BoolExpr retAss = createBoolVariableWith(p, "ASSIGNED", newAss);
BoolExpr variable = (variableName.equals("RETURN") ? r.getReturnValue() : r.getFallthroughValue());
BoolExpr newValue = _enc.mkIf(r.getReturnAssignedValue(), variable, _enc.mkIf(guard, (BoolExpr) t, (BoolExpr) f));
BoolExpr ret = createBoolVariableWith(p, variableName, newValue);
return new Pair<>(ret, retAss);
}
if (variableName.equals("PREFIX-LEN")) {
Expr t = (trueBranch == null ? p.getData().getPrefixLength() : trueBranch);
Expr f = (falseBranch == null ? p.getData().getPrefixLength() : falseBranch);
ArithExpr newValue = _enc.mkIf(guard, (ArithExpr) t, (ArithExpr) f);
newValue = _enc.mkIf(r.getReturnAssignedValue(), p.getData().getPrefixLength(), newValue);
ArithExpr ret = createArithVariableWith(p, "PREFIX-LEN", newValue);
p.getData().setPrefixLength(ret);
return new Pair<>(ret, null);
}
if (variableName.equals("ADMIN-DIST")) {
Expr t = (trueBranch == null ? p.getData().getAdminDist() : trueBranch);
Expr f = (falseBranch == null ? p.getData().getAdminDist() : falseBranch);
ArithExpr newValue = _enc.mkIf(guard, (ArithExpr) t, (ArithExpr) f);
newValue = _enc.mkIf(r.getReturnAssignedValue(), p.getData().getAdminDist(), newValue);
ArithExpr ret = createArithVariableWith(p, "ADMIN-DIST", newValue);
p.getData().setAdminDist(ret);
return new Pair<>(ret, null);
}
if (variableName.equals("LOCAL-PREF")) {
Expr t = (trueBranch == null ? p.getData().getLocalPref() : trueBranch);
Expr f = (falseBranch == null ? p.getData().getLocalPref() : falseBranch);
ArithExpr newValue = _enc.mkIf(guard, (ArithExpr) t, (ArithExpr) f);
newValue = _enc.mkIf(r.getReturnAssignedValue(), p.getData().getLocalPref(), newValue);
ArithExpr ret = createArithVariableWith(p, "LOCAL-PREF", newValue);
p.getData().setLocalPref(ret);
return new Pair<>(ret, null);
}
if (variableName.equals("METRIC")) {
Expr t = (trueBranch == null ? p.getData().getMetric() : trueBranch);
Expr f = (falseBranch == null ? p.getData().getMetric() : falseBranch);
ArithExpr newValue = _enc.mkIf(guard, (ArithExpr) t, (ArithExpr) f);
newValue = _enc.mkIf(r.getReturnAssignedValue(), p.getData().getMetric(), newValue);
ArithExpr ret = createArithVariableWith(p, "METRIC", newValue);
p.getData().setMetric(ret);
return new Pair<>(ret, null);
}
if (variableName.equals("OSPF-TYPE")) {
Expr t = (trueBranch == null ? p.getData().getOspfType().getBitVec() : trueBranch);
Expr f = (falseBranch == null ? p.getData().getOspfType().getBitVec() : falseBranch);
BitVecExpr newValue = _enc.mkIf(guard, (BitVecExpr) t, (BitVecExpr) f);
newValue = _enc.mkIf(r.getReturnAssignedValue(), p.getData().getOspfType().getBitVec(), newValue);
BitVecExpr ret = createBitVecVariableWith(p, "OSPF-TYPE", 2, newValue);
p.getData().getOspfType().setBitVec(ret);
return new Pair<>(ret, null);
}
for (Map.Entry<CommunityVar, BoolExpr> entry : p.getData().getCommunities().entrySet()) {
CommunityVar cvar = entry.getKey();
if (variableName.equals(cvar.getValue())) {
Expr t = (trueBranch == null ? p.getData().getCommunities().get(cvar) : trueBranch);
Expr f = (falseBranch == null ? p.getData().getCommunities().get(cvar) : falseBranch);
BoolExpr newValue = _enc.mkIf(guard, (BoolExpr) t, (BoolExpr) f);
newValue = _enc.mkIf(r.getReturnAssignedValue(), p.getData().getCommunities().get(cvar), newValue);
BoolExpr ret = createBoolVariableWith(p, cvar.getValue(), newValue);
p.getData().getCommunities().put(cvar, ret);
return new Pair<>(ret, null);
}
}
throw new BatfishException("[joinPoint]: unhandled case for " + variableName);
}
use of com.microsoft.z3.ArithExpr in project batfish by batfish.
the class Encoder method initFailedLinkVariables.
/*
* Initialize symbolic variables to represent link failures.
*/
private void initFailedLinkVariables() {
for (List<GraphEdge> edges : _graph.getEdgeMap().values()) {
for (GraphEdge ge : edges) {
if (ge.getPeer() == null) {
Interface i = ge.getStart();
String name = getId() + "_FAILED-EDGE_" + ge.getRouter() + "_" + i.getName();
ArithExpr var = getCtx().mkIntConst(name);
_symbolicFailures.getFailedEdgeLinks().put(ge, var);
_allVariables.put(var.toString(), var);
}
}
}
for (Entry<String, Set<String>> entry : _graph.getNeighbors().entrySet()) {
String router = entry.getKey();
Set<String> peers = entry.getValue();
for (String peer : peers) {
// sort names for unique
String pair = (router.compareTo(peer) < 0 ? router + "_" + peer : peer + "_" + router);
String name = getId() + "_FAILED-EDGE_" + pair;
ArithExpr var = _ctx.mkIntConst(name);
_symbolicFailures.getFailedInternalLinks().put(router, peer, var);
_allVariables.put(var.toString(), var);
}
}
}
use of com.microsoft.z3.ArithExpr in project batfish by batfish.
the class EncoderSlice method equal.
/*
* Check for equality of a (best) symbolic record and another
* symbolic record (vars). It checks pairwise that all fields
* are equal, while filling in values missing due to optimizations
* with default values based on the protocol.
* If there is no corresponding edge e, then the value null can be used
*/
public BoolExpr equal(Configuration conf, Protocol proto, SymbolicRoute best, SymbolicRoute vars, @Nullable LogicalEdge e, boolean compareCommunities) {
ArithExpr defaultLocal = mkInt(defaultLocalPref());
ArithExpr defaultAdmin = defaultAdminDistance(conf, proto, vars);
ArithExpr defaultMet = mkInt(defaultMetric());
ArithExpr defaultMed = mkInt(defaultMed(proto));
ArithExpr defaultLen = mkInt(defaultLength());
ArithExpr defaultIgp = mkInt(defaultIgpMetric());
BoolExpr equalLen;
BoolExpr equalAd;
BoolExpr equalLp;
BoolExpr equalMet;
BoolExpr equalMed;
BoolExpr equalOspfArea;
BoolExpr equalOspfType;
BoolExpr equalId;
BoolExpr equalHistory;
BoolExpr equalBgpInternal;
BoolExpr equalClientIds;
BoolExpr equalIgpMet;
BoolExpr equalCommunities;
equalLen = equalHelper(best.getPrefixLength(), vars.getPrefixLength(), defaultLen);
equalAd = equalHelper(best.getAdminDist(), vars.getAdminDist(), defaultAdmin);
equalLp = equalHelper(best.getLocalPref(), vars.getLocalPref(), defaultLocal);
equalMet = equalHelper(best.getMetric(), vars.getMetric(), defaultMet);
equalMed = equalHelper(best.getMed(), vars.getMed(), defaultMed);
equalIgpMet = equalHelper(best.getIgpMetric(), vars.getIgpMetric(), defaultIgp);
equalOspfType = equalTypes(best, vars);
equalOspfArea = equalAreas(best, vars, e);
equalId = equalIds(best, vars, proto, e);
equalHistory = equalHistories(best, vars);
equalBgpInternal = equalBgpInternal(best, vars);
equalClientIds = equalClientIds(conf.getName(), best, vars);
equalCommunities = (compareCommunities ? equalCommunities(best, vars) : mkTrue());
return mkAnd(equalLen, equalAd, equalLp, equalMet, equalMed, equalOspfArea, equalOspfType, equalId, equalHistory, equalBgpInternal, equalClientIds, equalIgpMet, equalCommunities);
}
use of com.microsoft.z3.ArithExpr in project batfish by batfish.
the class EncoderSlice method isRelevantFor.
/*
* Check if a prefix range match is applicable for the packet destination
* Ip address, given the prefix length variable.
*/
BoolExpr isRelevantFor(ArithExpr prefixLen, PrefixRange range) {
Prefix p = range.getPrefix();
SubRange r = range.getLengthRange();
long pfx = p.getStartIp().asLong();
int len = p.getPrefixLength();
int lower = r.getStart();
int upper = r.getEnd();
// well formed prefix
assert (p.getPrefixLength() <= lower && lower <= upper);
BoolExpr lowerBitsMatch = firstBitsEqual(_symbolicPacket.getDstIp(), pfx, len);
if (lower == upper) {
BoolExpr equalLen = mkEq(prefixLen, mkInt(lower));
return mkAnd(equalLen, lowerBitsMatch);
} else {
BoolExpr lengthLowerBound = mkGe(prefixLen, mkInt(lower));
BoolExpr lengthUpperBound = mkLe(prefixLen, mkInt(upper));
return mkAnd(lengthLowerBound, lengthUpperBound, lowerBitsMatch);
}
}
use of com.microsoft.z3.ArithExpr in project batfish by batfish.
the class EncoderSlice method greaterOrEqual.
/*
* Check if a (best) symbolic record is better than another
* symbolic record (vars). This is done using a recursive lexicographic
* encoding. The encoding is as follows:
*
* (best.length > vars.length) or
* (best.length = vars.length) and (
* (best.adminDist < vars.adminDist) or
* (best.adminDist = vars.adminDist) and (
* ...
* )
* )
*
* This recursive encoding introduces a new variable for each subexpressions,
* which ends up being much more efficient than expanding out options.
*/
private BoolExpr greaterOrEqual(Configuration conf, Protocol proto, SymbolicRoute best, SymbolicRoute vars, @Nullable LogicalEdge e) {
ArithExpr defaultLocal = mkInt(defaultLocalPref());
ArithExpr defaultAdmin = defaultAdminDistance(conf, proto, vars);
ArithExpr defaultMet = mkInt(defaultMetric());
ArithExpr defaultMed = mkInt(defaultMed(proto));
ArithExpr defaultLen = mkInt(defaultLength());
ArithExpr defaultIgp = mkInt(defaultIgpMetric());
ArithExpr defaultId = mkInt(0);
BitVecExpr defaultOspfType = defaultOspfType();
BoolExpr betterLen = geBetterHelper(best.getPrefixLength(), vars.getPrefixLength(), defaultLen, false);
BoolExpr equalLen = geEqualHelper(best.getPrefixLength(), vars.getPrefixLength(), defaultLen);
BoolExpr betterAd = geBetterHelper(best.getAdminDist(), vars.getAdminDist(), defaultAdmin, true);
BoolExpr equalAd = geEqualHelper(best.getAdminDist(), vars.getAdminDist(), defaultAdmin);
BoolExpr betterLp = geBetterHelper(best.getLocalPref(), vars.getLocalPref(), defaultLocal, false);
BoolExpr equalLp = geEqualHelper(best.getLocalPref(), vars.getLocalPref(), defaultLocal);
BoolExpr betterMet = geBetterHelper(best.getMetric(), vars.getMetric(), defaultMet, true);
BoolExpr equalMet = geEqualHelper(best.getMetric(), vars.getMetric(), defaultMet);
BoolExpr betterMed = geBetterHelper(best.getMed(), vars.getMed(), defaultMed, true);
BoolExpr equalMed = geEqualHelper(best.getMed(), vars.getMed(), defaultMed);
BitVecExpr bestType = (best.getOspfType() == null ? null : best.getOspfType().getBitVec());
BitVecExpr varsType = (vars.getOspfType() == null ? null : vars.getOspfType().getBitVec());
BoolExpr betterOspfType = geBetterHelper(bestType, varsType, defaultOspfType, true);
BoolExpr equalOspfType = geEqualHelper(bestType, varsType, defaultOspfType);
BoolExpr betterInternal = geBetterHelper(best.getBgpInternal(), vars.getBgpInternal(), mkFalse(), true);
BoolExpr equalInternal = geEqualHelper(best.getBgpInternal(), vars.getBgpInternal(), mkFalse());
BoolExpr betterIgpMet = geBetterHelper(best.getIgpMetric(), vars.getIgpMetric(), defaultIgp, true);
BoolExpr equalIgpMet = geEqualHelper(best.getIgpMetric(), vars.getIgpMetric(), defaultIgp);
BoolExpr tiebreak;
if (vars.getRouterId() != null) {
tiebreak = mkLe(best.getRouterId(), vars.getRouterId());
} else if (best.getRouterId() != null) {
if (e == null) {
tiebreak = mkLe(best.getRouterId(), defaultId);
} else {
long peerId = getGraph().findRouterId(e.getEdge(), proto);
tiebreak = mkLe(best.getRouterId(), mkInt(peerId));
}
} else {
tiebreak = mkTrue();
}
BoolExpr b = mkAnd(equalOspfType, tiebreak);
BoolExpr b1 = mkOr(betterOspfType, b);
BoolExpr b2 = mkAnd(equalIgpMet, b1);
BoolExpr b3 = mkOr(betterIgpMet, b2);
BoolExpr b4 = mkAnd(equalInternal, b3);
BoolExpr b5 = mkOr(betterInternal, b4);
BoolExpr b6 = mkAnd(equalMed, b5);
BoolExpr b7 = mkOr(betterMed, b6);
BoolExpr b8 = mkAnd(equalMet, b7);
BoolExpr b9 = mkOr(betterMet, b8);
BoolExpr b10 = mkAnd(equalLp, b9);
BoolExpr b11 = mkOr(betterLp, b10);
BoolExpr b12 = mkAnd(equalAd, b11);
BoolExpr b13 = mkOr(betterAd, b12);
BoolExpr b14 = mkAnd(equalLen, b13);
return mkOr(betterLen, b14);
}
Aggregations