use of com.microsoft.z3.ArithExpr in project batfish by batfish.
the class EncoderSlice method addUnusedDefaultValueConstraints.
/*
* For performance reasons, we add constraints that if a message is not
* valid, then the other variables will use default values. This speeds
* up the solver significantly.
*/
private void addUnusedDefaultValueConstraints() {
for (SymbolicRoute vars : getAllSymbolicRecords()) {
BoolExpr notPermitted = mkNot(vars.getPermitted());
ArithExpr zero = mkInt(0);
if (vars.getAdminDist() != null) {
add(mkImplies(notPermitted, mkEq(vars.getAdminDist(), zero)));
}
if (vars.getMed() != null) {
add(mkImplies(notPermitted, mkEq(vars.getMed(), zero)));
}
if (vars.getLocalPref() != null) {
add(mkImplies(notPermitted, mkEq(vars.getLocalPref(), zero)));
}
if (vars.getPrefixLength() != null) {
add(mkImplies(notPermitted, mkEq(vars.getPrefixLength(), zero)));
}
if (vars.getMetric() != null) {
add(mkImplies(notPermitted, mkEq(vars.getMetric(), zero)));
}
if (vars.getOspfArea() != null) {
add(mkImplies(notPermitted, vars.getOspfArea().isDefaultValue()));
}
if (vars.getOspfType() != null) {
add(mkImplies(notPermitted, vars.getOspfType().isDefaultValue()));
}
if (vars.getProtocolHistory() != null) {
add(mkImplies(notPermitted, vars.getProtocolHistory().isDefaultValue()));
}
if (vars.getBgpInternal() != null) {
add(mkImplies(notPermitted, mkNot(vars.getBgpInternal())));
}
if (vars.getClientId() != null) {
add(mkImplies(notPermitted, vars.getClientId().isDefaultValue()));
}
if (vars.getIgpMetric() != null) {
add(mkImplies(notPermitted, mkEq(vars.getIgpMetric(), zero)));
}
if (vars.getRouterId() != null) {
add(mkImplies(notPermitted, mkEq(vars.getRouterId(), zero)));
}
vars.getCommunities().forEach((cvar, e) -> add(mkImplies(notPermitted, mkNot(e))));
}
}
use of com.microsoft.z3.ArithExpr in project batfish by batfish.
the class PropertyAdder method instrumentLoad.
/*
* Instruments the network with load balancing information to destination
* port for graph edge ge. Each router will split load according to the
* number of neighbors it actively uses to get to ge.
*/
Map<String, ArithExpr> instrumentLoad(Set<GraphEdge> ges) {
Context ctx = _encoderSlice.getCtx();
Solver solver = _encoderSlice.getSolver();
String sliceName = _encoderSlice.getSliceName();
Map<String, ArithExpr> loadVars = new HashMap<>();
Graph graph = _encoderSlice.getGraph();
for (String router : graph.getRouters()) {
String name = _encoderSlice.getEncoder().getId() + "_" + sliceName + "_load_" + router;
ArithExpr var = ctx.mkIntConst(name);
loadVars.put(router, var);
_encoderSlice.getAllVariables().put(var.toString(), var);
}
loadVars.forEach((name, var) -> solver.add(ctx.mkGe(var, ctx.mkInt(0))));
ArithExpr zero = ctx.mkInt(0);
ArithExpr one = ctx.mkInt(1);
for (Entry<String, List<GraphEdge>> entry : graph.getEdgeMap().entrySet()) {
String router = entry.getKey();
List<GraphEdge> edges = entry.getValue();
ArithExpr load = loadVars.get(router);
BoolExpr hasDirectRoute = ctx.mkFalse();
BoolExpr isAbsorbed = ctx.mkFalse();
SymbolicRoute r = _encoderSlice.getBestNeighborPerProtocol(router, Protocol.CONNECTED);
for (GraphEdge ge : edges) {
if (!ge.isAbstract() && ges.contains(ge)) {
// if we leave the network
if (ge.getPeer() == null) {
BoolExpr fwdIface = _encoderSlice.getForwardsAcross().get(ge.getRouter(), ge);
assert (fwdIface != null);
hasDirectRoute = ctx.mkOr(hasDirectRoute, fwdIface);
}
// if connected route and we use it despite not forwarding
if (r != null) {
BitVecExpr dstIp = _encoderSlice.getSymbolicPacket().getDstIp();
BitVecExpr ip = ctx.mkBV(ge.getStart().getAddress().getIp().asLong(), 32);
BoolExpr reach = ctx.mkAnd(r.getPermitted(), ctx.mkEq(dstIp, ip));
isAbsorbed = ctx.mkOr(isAbsorbed, reach);
}
}
}
ArithExpr acc = ctx.mkInt(0);
for (GraphEdge edge : edges) {
if (!edge.isAbstract()) {
BoolExpr fwd = _encoderSlice.getForwardsAcross().get(router, edge);
assert (fwd != null);
if (edge.getPeer() != null) {
ArithExpr peerLoad = loadVars.get(edge.getPeer());
ArithExpr x = (ArithExpr) ctx.mkITE(fwd, peerLoad, zero);
acc = ctx.mkAdd(acc, x);
}
}
}
solver.add(ctx.mkEq(load, acc));
BoolExpr guard = _encoderSlice.mkOr(hasDirectRoute, isAbsorbed);
BoolExpr cond = _encoderSlice.mkIf(guard, ctx.mkEq(load, one), ctx.mkEq(load, acc));
solver.add(cond);
}
return loadVars;
}
use of com.microsoft.z3.ArithExpr in project batfish by batfish.
the class PropertyAdder method initializeReachabilityVars.
/*
* Initialize reachability and id variables an add the constraints
* that all ids are at least 0 or higher, and reachable means non-zero.
*/
private void initializeReachabilityVars(EncoderSlice slice, Context ctx, Solver solver, Map<String, BoolExpr> reachableVars, Map<String, ArithExpr> idVars) {
String sliceName = slice.getSliceName();
ArithExpr zero = ctx.mkInt(0);
for (String r : _encoderSlice.getGraph().getRouters()) {
int id = _encoderSlice.getEncoder().getId();
String s1 = id + "_" + sliceName + "_reachable-id_" + r;
String s2 = id + "_" + sliceName + "_reachable_" + r;
ArithExpr idVar = ctx.mkIntConst(s1);
BoolExpr var = ctx.mkBoolConst(s2);
idVars.put(r, idVar);
reachableVars.put(r, var);
_encoderSlice.getAllVariables().put(idVar.toString(), idVar);
_encoderSlice.getAllVariables().put(var.toString(), var);
solver.add(ctx.mkEq(var, ctx.mkGt(idVar, zero)));
solver.add(ctx.mkGe(idVar, zero));
}
}
use of com.microsoft.z3.ArithExpr in project batfish by batfish.
the class PropertyAdder method instrumentReachability.
/*
* Also instruments reachability, but to a destination router
* rather than a destination port.
*/
Map<String, BoolExpr> instrumentReachability(String router) {
Context ctx = _encoderSlice.getCtx();
Solver solver = _encoderSlice.getSolver();
Map<String, BoolExpr> reachableVars = new HashMap<>();
Map<String, ArithExpr> idVars = new HashMap<>();
initializeReachabilityVars(_encoderSlice, ctx, solver, reachableVars, idVars);
ArithExpr baseId = idVars.get(router);
_encoderSlice.add(ctx.mkEq(baseId, ctx.mkInt(1)));
Graph g = _encoderSlice.getGraph();
for (Entry<String, List<GraphEdge>> entry : g.getEdgeMap().entrySet()) {
String r = entry.getKey();
List<GraphEdge> edges = entry.getValue();
if (!r.equals(router)) {
ArithExpr id = idVars.get(r);
BoolExpr cond = recursiveReachability(ctx, _encoderSlice, edges, idVars, r, id);
solver.add(cond);
}
}
return reachableVars;
}
use of com.microsoft.z3.ArithExpr in project batfish by batfish.
the class PropertyChecker method checkLoadBalancing.
/*
* Computes whether load balancing for each source node in a collection is
* within some threshold k of the each other.
*/
public AnswerElement checkLoadBalancing(HeaderLocationQuestion q, int k) {
return checkProperty(q, (enc, srcRouters, destPorts) -> {
PropertyAdder pa = new PropertyAdder(enc.getMainSlice());
Map<String, ArithExpr> loads = pa.instrumentLoad(destPorts);
Map<String, BoolExpr> prop = new HashMap<>();
// TODO: implement this properly after refactoring
loads.forEach((name, ae) -> prop.put(name, enc.mkTrue()));
return prop;
}, (vp) -> new SmtOneAnswerElement(vp.getResult()));
}
Aggregations