use of com.microsoft.z3.Context in project Dat3M by hernanponcedeleon.
the class Encodings method getReachedStateLow.
public static BoolExpr getReachedStateLow(Program p, Model model, Context ctx) {
Set<Location> locs = p.getEvents().stream().filter(e -> e instanceof MemEvent).map(e -> e.getLoc()).filter(l -> !(l instanceof HighLocation)).collect(Collectors.toSet());
BoolExpr reachedState = ctx.mkTrue();
for (Location loc : locs) {
reachedState = ctx.mkAnd(reachedState, ctx.mkEq(lastValueLoc(loc, ctx), model.getConstInterp(lastValueLoc(loc, ctx))));
}
return reachedState;
}
use of com.microsoft.z3.Context in project Dat3M by hernanponcedeleon.
the class Encodings method diffInitialHigh.
public static BoolExpr diffInitialHigh(Program p, Context ctx) {
Set<Event> highInits = p.getEvents().stream().filter(e -> e instanceof Init).filter(e -> e.getLoc() instanceof HighLocation).collect(Collectors.toSet());
BoolExpr initState = ctx.mkTrue();
for (Event e : highInits) {
if (e.getLoc().getIValue() == null) {
initState = ctx.mkAnd(initState, ctx.mkNot(ctx.mkEq(initValue(e, ctx), initValue2(e, ctx))));
}
}
return initState;
}
use of com.microsoft.z3.Context in project Dat3M by hernanponcedeleon.
the class Porthos method main.
public static void main(String[] args) throws Z3Exception, IOException {
List<String> MCMs = Arrays.asList("sc", "tso", "pso", "rmo", "alpha", "power", "arm");
Options options = new Options();
Option sourceOpt = new Option("s", "source", true, "source MCM");
sourceOpt.setRequired(true);
options.addOption(sourceOpt);
Option targetOpt = new Option("t", "target", true, "target MCM");
targetOpt.setRequired(true);
options.addOption(targetOpt);
Option inputOpt = new Option("i", "input", true, "input file path");
inputOpt.setRequired(true);
options.addOption(inputOpt);
options.addOption("state", false, "PORTHOS performs state portability");
options.addOption(Option.builder("draw").hasArg().desc("If a buf is found, it outputs a graph \\path_to_file.dot").build());
options.addOption(Option.builder("rels").hasArgs().desc("Relations to be drawn in the graph").build());
options.addOption(Option.builder("unroll").hasArg().desc("Unrolling steps").build());
CommandLineParser parserCmd = new DefaultParser();
HelpFormatter formatter = new HelpFormatter();
CommandLine cmd;
try {
cmd = parserCmd.parse(options, args);
} catch (ParseException e) {
System.out.println(e.getMessage());
formatter.printHelp("PORTHOS", options);
System.exit(1);
return;
}
String source = cmd.getOptionValue("source");
if (!MCMs.stream().anyMatch(mcms -> mcms.trim().equals(source))) {
System.out.println("Unrecognized source");
System.exit(0);
return;
}
String target = cmd.getOptionValue("target");
if (!MCMs.stream().anyMatch(mcms -> mcms.trim().equals(target))) {
System.out.println("Unrecognized target");
System.exit(0);
return;
}
String inputFilePath = cmd.getOptionValue("input");
if (!inputFilePath.endsWith("pts") && !inputFilePath.endsWith("litmus")) {
System.out.println("Unrecognized program format");
System.exit(0);
return;
}
File file = new File(inputFilePath);
boolean statePortability = cmd.hasOption("state");
String[] rels = new String[100];
if (cmd.hasOption("rels")) {
rels = cmd.getOptionValues("rels");
}
String program = FileUtils.readFileToString(file, "UTF-8");
ANTLRInputStream input = new ANTLRInputStream(program);
Program p = new Program(inputFilePath);
if (inputFilePath.endsWith("litmus")) {
LitmusLexer lexer = new LitmusLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
LitmusParser parser = new LitmusParser(tokens);
p = parser.program(inputFilePath).p;
}
if (inputFilePath.endsWith("pts")) {
PorthosLexer lexer = new PorthosLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
PorthosParser parser = new PorthosParser(tokens);
p = parser.program(inputFilePath).p;
}
int steps = 1;
if (cmd.hasOption("unroll")) {
steps = Integer.parseInt(cmd.getOptionValue("unroll"));
}
p.initialize(steps);
Program pSource = p.clone();
Program pTarget = p.clone();
pSource.compile(source, false, true);
Integer startEId = Collections.max(pSource.getEvents().stream().filter(e -> e instanceof Init).map(e -> e.getEId()).collect(Collectors.toSet())) + 1;
pTarget.compile(target, false, true, startEId);
Context ctx = new Context();
ctx.setPrintMode(Z3_ast_print_mode.Z3_PRINT_SMTLIB_FULL);
Solver s = ctx.mkSolver();
Solver s2 = ctx.mkSolver();
BoolExpr sourceDF = pSource.encodeDF(ctx);
BoolExpr sourceCF = pSource.encodeCF(ctx);
BoolExpr sourceDF_RF = pSource.encodeDF_RF(ctx);
BoolExpr sourceDomain = Domain.encode(pSource, ctx);
BoolExpr sourceMM = pSource.encodeMM(ctx, source);
s.add(pTarget.encodeDF(ctx));
s.add(pTarget.encodeCF(ctx));
s.add(pTarget.encodeDF_RF(ctx));
s.add(Domain.encode(pTarget, ctx));
s.add(pTarget.encodeMM(ctx, target));
s.add(pTarget.encodeConsistent(ctx, target));
s.add(sourceDF);
s.add(sourceCF);
s.add(sourceDF_RF);
s.add(sourceDomain);
s.add(sourceMM);
s.add(pSource.encodeInconsistent(ctx, source));
s.add(encodeCommonExecutions(pTarget, pSource, ctx));
s2.add(sourceDF);
s2.add(sourceCF);
s2.add(sourceDF_RF);
s2.add(sourceDomain);
s2.add(sourceMM);
s2.add(pSource.encodeConsistent(ctx, source));
if (!statePortability) {
if (s.check() == Status.SATISFIABLE) {
System.out.println("The program is not portable");
// System.out.println(" 0");
if (cmd.hasOption("draw")) {
String outputPath = cmd.getOptionValue("draw");
Utils.drawGraph(p, pSource, pTarget, ctx, s.getModel(), outputPath, rels);
}
return;
} else {
System.out.println("The program is portable");
// System.out.println(" 1");
return;
}
}
int iterations = 0;
Status lastCheck = Status.SATISFIABLE;
Set<Expr> visited = new HashSet<Expr>();
while (lastCheck == Status.SATISFIABLE) {
lastCheck = s.check();
if (lastCheck == Status.SATISFIABLE) {
iterations = iterations + 1;
Model model = s.getModel();
s2.push();
BoolExpr reachedState = encodeReachedState(pTarget, model, ctx);
visited.add(reachedState);
assert (iterations == visited.size());
s2.add(reachedState);
if (s2.check() == Status.UNSATISFIABLE) {
System.out.println("The program is not state-portable");
System.out.println("Iterations: " + iterations);
// System.out.println(" 0");
return;
} else {
s2.pop();
s.add(ctx.mkNot(reachedState));
}
} else {
System.out.println("The program is state-portable");
System.out.println("Iterations: " + iterations);
// System.out.println(" 1");
return;
}
}
}
use of com.microsoft.z3.Context in project batfish by batfish.
the class PropertyAdder method instrumentPathLength.
// Potentially useful in the future to optimize reachability when we know
// that there can't be routing loops e.g., due to a preliminary static analysis
/* public Map<String, BoolExpr> instrumentReachabilityFast(String router) {
Context ctx = _encoderSlice.getCtx();
Solver solver = _encoderSlice.getSolver();
Map<String, BoolExpr> reachableVars = new HashMap<>();
String sliceName = _encoderSlice.getSliceName();
_encoderSlice
.getGraph()
.getConfigurations()
.forEach(
(r, conf) -> {
int id = _encoderSlice.getEncoder().getId();
String s2 = id + "_" + sliceName + "_reachable_" + r;
BoolExpr var = ctx.mkBoolConst(s2);
reachableVars.put(r, var);
_encoderSlice.getAllVariables().put(var.toString(), var);
});
BoolExpr baseReach = reachableVars.get(router);
_encoderSlice.add(baseReach);
_encoderSlice
.getGraph()
.getEdgeMap()
.forEach(
(r, edges) -> {
if (!r.equals(router)) {
BoolExpr reach = reachableVars.get(r);
BoolExpr hasRecursiveRoute = ctx.mkFalse();
for (GraphEdge edge : edges) {
if (!edge.isAbstract()) {
BoolExpr fwd = _encoderSlice.getForwardsAcross().get(r, edge);
if (edge.getPeer() != null) {
BoolExpr peerReachable = reachableVars.get(edge.getPeer());
BoolExpr sendToReachable = ctx.mkAnd(fwd, peerReachable);
hasRecursiveRoute = ctx.mkOr(hasRecursiveRoute, sendToReachable);
}
}
}
solver.add(ctx.mkEq(reach, hasRecursiveRoute));
}
});
return reachableVars;
}
public Map<String, BoolExpr> instrumentReachabilityFast(Set<GraphEdge> ges) {
Context ctx = _encoderSlice.getCtx();
Solver solver = _encoderSlice.getSolver();
EncoderSlice slice = _encoderSlice;
String sliceName = _encoderSlice.getSliceName();
Graph g = slice.getGraph();
Map<String, BoolExpr> reachableVars = new HashMap<>();
_encoderSlice
.getGraph()
.getConfigurations()
.forEach(
(r, conf) -> {
int id = _encoderSlice.getEncoder().getId();
String s2 = id + "_" + sliceName + "_reachable_" + r;
BoolExpr var = ctx.mkBoolConst(s2);
reachableVars.put(r, var);
_encoderSlice.getAllVariables().put(var.toString(), var);
});
for (Entry<String, List<GraphEdge>> entry : g.getEdgeMap().entrySet()) {
String router = entry.getKey();
List<GraphEdge> edges = entry.getValue();
BoolExpr reach = reachableVars.get(router);
// Add the base case, reachable if we forward to a directly connected interface
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 a host, consider reachable
if (g.isHost(router)) {
hasDirectRoute = ctx.mkTrue();
break;
}
// Reachable 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);
}
// Also reachable if connected route and we use it despite not forwarding
if (r != null) {
BitVecExpr dstIp = _encoderSlice.getSymbolicPacket().getDstIp();
BitVecExpr ip = ctx.mkBV(ge.getStart().getIp().getIp().asLong(), 32);
BoolExpr reachable = ctx.mkAnd(r.getPermitted(), ctx.mkEq(dstIp, ip));
isAbsorbed = ctx.mkOr(isAbsorbed, reachable);
}
}
}
// Add the recursive case, where it is reachable through a neighbor
BoolExpr hasRecursiveRoute = ctx.mkFalse();
for (GraphEdge edge : edges) {
if (!edge.isAbstract()) {
BoolExpr fwd = _encoderSlice.getForwardsAcross().get(router, edge);
if (edge.getPeer() != null) {
BoolExpr peerReachable = reachableVars.get(edge.getPeer());
BoolExpr sendToReachable = ctx.mkAnd(fwd, peerReachable);
hasRecursiveRoute = ctx.mkOr(hasRecursiveRoute, sendToReachable);
}
}
}
BoolExpr cond = slice.mkOr(hasDirectRoute, isAbsorbed, hasRecursiveRoute);
solver.add(slice.mkEq(reach, cond));
}
return reachableVars;
} */
/*
* Instruments the network with path length information to a
* destination port corresponding to a graph edge ge.
* A router has a path of length n if some neighbor has a path
* with length n-1.
*/
Map<String, ArithExpr> instrumentPathLength(Set<GraphEdge> ges) {
Context ctx = _encoderSlice.getCtx();
Solver solver = _encoderSlice.getSolver();
String sliceName = _encoderSlice.getSliceName();
// Initialize path length variables
Graph graph = _encoderSlice.getGraph();
Map<String, ArithExpr> lenVars = new HashMap<>();
for (String router : graph.getRouters()) {
String name = _encoderSlice.getEncoder().getId() + "_" + sliceName + "_path-length_" + router;
ArithExpr var = ctx.mkIntConst(name);
lenVars.put(router, var);
_encoderSlice.getAllVariables().put(var.toString(), var);
}
ArithExpr zero = ctx.mkInt(0);
ArithExpr one = ctx.mkInt(1);
ArithExpr minusOne = ctx.mkInt(-1);
// Lower bound for all lengths
lenVars.forEach((name, var) -> solver.add(ctx.mkGe(var, minusOne)));
for (Entry<String, List<GraphEdge>> entry : graph.getEdgeMap().entrySet()) {
String router = entry.getKey();
List<GraphEdge> edges = entry.getValue();
ArithExpr length = lenVars.get(router);
// If there is a direct route, then we have length 0
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)) {
// Reachable 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);
}
// Also reachable 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);
}
}
}
// Otherwise, we find length recursively
BoolExpr accNone = ctx.mkTrue();
BoolExpr accSome = ctx.mkFalse();
for (GraphEdge edge : edges) {
if (!edge.isAbstract() && edge.getPeer() != null) {
BoolExpr dataFwd = _encoderSlice.getForwardsAcross().get(router, edge);
assert (dataFwd != null);
ArithExpr peerLen = lenVars.get(edge.getPeer());
accNone = ctx.mkAnd(accNone, ctx.mkOr(ctx.mkLt(peerLen, zero), ctx.mkNot(dataFwd)));
ArithExpr newVal = ctx.mkAdd(peerLen, one);
BoolExpr fwd = ctx.mkAnd(ctx.mkGe(peerLen, zero), dataFwd, ctx.mkEq(length, newVal));
accSome = ctx.mkOr(accSome, fwd);
}
}
BoolExpr guard = _encoderSlice.mkOr(hasDirectRoute, isAbsorbed);
BoolExpr cond1 = _encoderSlice.mkIf(accNone, ctx.mkEq(length, minusOne), accSome);
BoolExpr cond2 = _encoderSlice.mkIf(guard, ctx.mkEq(length, zero), cond1);
solver.add(cond2);
}
return lenVars;
}
use of com.microsoft.z3.Context in project batfish by batfish.
the class PropertyAdder method recursiveReachability.
/*
* Generates constraints for reachability through some neighbor.
* If a router forwards to some neighbor with id label > 0, then the id of this router is
* greater than that of all next hops. This prevents considering loops and also means that
* we interpret the router as reachable. If there is no such neighbor, then this router is
* not reachable and we set the id to 0.
*/
private BoolExpr recursiveReachability(Context ctx, EncoderSlice slice, List<GraphEdge> edges, Map<String, ArithExpr> idVars, String router, ArithExpr id) {
ArithExpr zero = ctx.mkInt(0);
BoolExpr hasRecursiveRoute = ctx.mkFalse();
BoolExpr largerIds = ctx.mkTrue();
for (GraphEdge edge : edges) {
if (!edge.isAbstract()) {
BoolExpr fwd = _encoderSlice.getForwardsAcross().get(router, edge);
if (edge.getPeer() != null) {
ArithExpr peerId = idVars.get(edge.getPeer());
BoolExpr peerReachable = ctx.mkGt(peerId, zero);
BoolExpr sendToReachable = ctx.mkAnd(fwd, peerReachable);
hasRecursiveRoute = ctx.mkOr(hasRecursiveRoute, sendToReachable);
BoolExpr increasingId = ctx.mkImplies(sendToReachable, ctx.mkGt(id, peerId));
largerIds = ctx.mkAnd(largerIds, increasingId);
}
}
}
return slice.mkIf(hasRecursiveRoute, largerIds, ctx.mkEq(id, zero));
}
Aggregations