use of com.microsoft.z3.RatNum in project VERDICT by ge-high-assurance.
the class VerdictSynthesis method performSynthesisMultiple.
/**
* Performs synthesis on multiple cyber requirements. This is the only version of synthesis that
* should be used.
*
* @param tree the defense tree
* @param factory the dleaf factory used to construct the defense tree
* @param costModel the cost model
* @param partialSolution whether we are using partial solutions
* @param inputSat whether the input tree is satisfied
* @param meritAssignment whether to perform merit assignment if the input is satisfied
* @param dumpSmtLib whether to output the intermediate SMT-LIB file for debugging
* @return the result, if successful
*/
public static Optional<ResultsInstance> performSynthesisMultiple(DTree tree, DLeaf.Factory factory, CostModel costModel, boolean partialSolution, boolean inputSat, boolean meritAssignment, boolean dumpSmtLib) {
Context context = new Context();
Optimize optimizer = context.mkOptimize();
System.out.println("performSynthesisMultiple, configuration: partialSolution=" + partialSolution + ", inputSat=" + inputSat + ", meritAssignment=" + meritAssignment);
Collection<ComponentDefense> compDefPairs = factory.allComponentDefensePairs();
// Encode the logical structure of defense tree in MaxSMT
// Encode cost(impl_defense_dal) >= the target cost (based on the severity of cyber req)
// With merit assignment off and partial solution on, you will
// subtract the cost of each DAL by the impl DAL cost, and use 0 if the result is negative.
optimizer.Assert(tree.toZ3Multi(context));
if (meritAssignment) {
// set upper bounds at the current values, so that no upgrades are reported
// Encode component_defense_var <= the the implemented DAL cost
optimizer.Assert(context.mkAnd(compDefPairs.stream().map(pair -> context.mkLe(pair.toZ3Multi(context), DLeaf.fractionToZ3(pair.dalToRawCost(pair.implDal), context))).collect(Collectors.toList()).toArray(new BoolExpr[] {})));
}
// Make all component-defense var >= Cost(DAL(0));
optimizer.Assert(// to DAL, then this can be changed to the minimum of all costs.
context.mkAnd(compDefPairs.stream().map(pair -> context.mkGe(pair.toZ3Multi(context), DLeaf.fractionToZ3(pair.dalToRawCost(0), context))).collect(Collectors.toList()).toArray(new BoolExpr[] {})));
// Encode objective function: the sum of all component-defense vars
if (compDefPairs.isEmpty()) {
optimizer.MkMinimize(context.mkInt(0));
} else {
optimizer.MkMinimize(context.mkAdd(compDefPairs.stream().map(pair -> pair.toZ3Multi(context)).collect(Collectors.toList()).toArray(new ArithExpr[] {})));
}
if (dumpSmtLib) {
try {
// this dumps the file in the working directory, i.e. where the process was started
// from
PrintWriter writer = new PrintWriter("verdict-synthesis-dump.smtlib", "UTF-8");
writer.println(optimizer.toString());
writer.flush();
writer.close();
} catch (FileNotFoundException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
if (optimizer.Check().equals(Status.SATISFIABLE)) {
List<ResultsInstance.Item> items = new ArrayList<>();
Fraction totalInputCost = new Fraction(0), totalOutputCost = new Fraction(0);
Model model = optimizer.getModel();
for (ComponentDefense pair : compDefPairs) {
// get the value in the model
RatNum expr = (RatNum) model.eval(pair.toZ3Multi(context), true);
Fraction rawCost = new Fraction(expr.getNumerator().getInt(), expr.getDenominator().getInt());
// convert back to DAL (the value in the model is cost rather than DAL)
int dal = pair.rawCostToDal(rawCost);
// but we don't trust the cost obtained directly from the model.
// instead, we re-calculate using the cost model because it is less prone to failure
// The cost of implemented DAL
Fraction inputCost = costModel.cost(pair.defenseProperty, pair.component, pair.implDal);
// The cost of output DAL from SMT
Fraction outputCost = costModel.cost(pair.defenseProperty, pair.component, dal);
// keep track of total cost
totalInputCost = totalInputCost.add(inputCost);
totalOutputCost = totalOutputCost.add(outputCost);
items.add(new ResultsInstance.Item(pair.component, pair.defenseProperty, pair.implDal, dal, inputCost, outputCost));
}
return Optional.of(new ResultsInstance(partialSolution, meritAssignment, inputSat, totalInputCost, totalOutputCost, items));
} else {
System.err.println("Synthesis: SMT not satisfiable, perhaps there are unmitigatable attacks");
return Optional.empty();
}
}
Aggregations