Search in sources :

Example 1 with RatNum

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();
    }
}
Also used : Context(com.microsoft.z3.Context) FileNotFoundException(java.io.FileNotFoundException) ArrayList(java.util.ArrayList) UnsupportedEncodingException(java.io.UnsupportedEncodingException) Fraction(org.apache.commons.math3.fraction.Fraction) ResultsInstance(com.ge.verdict.vdm.synthesis.ResultsInstance) ComponentDefense(com.ge.verdict.synthesis.dtree.DLeaf.ComponentDefense) Model(com.microsoft.z3.Model) RatNum(com.microsoft.z3.RatNum) Optimize(com.microsoft.z3.Optimize) PrintWriter(java.io.PrintWriter)

Aggregations

ComponentDefense (com.ge.verdict.synthesis.dtree.DLeaf.ComponentDefense)1 ResultsInstance (com.ge.verdict.vdm.synthesis.ResultsInstance)1 Context (com.microsoft.z3.Context)1 Model (com.microsoft.z3.Model)1 Optimize (com.microsoft.z3.Optimize)1 RatNum (com.microsoft.z3.RatNum)1 FileNotFoundException (java.io.FileNotFoundException)1 PrintWriter (java.io.PrintWriter)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 ArrayList (java.util.ArrayList)1 Fraction (org.apache.commons.math3.fraction.Fraction)1