use of com.ge.verdict.vdm.synthesis.ResultsInstance 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();
}
}
use of com.ge.verdict.vdm.synthesis.ResultsInstance in project VERDICT by ge-high-assurance.
the class MBASSynthesisReport method report.
public static void report(IProject project, File projectDir, File xmlFile, IWorkbenchWindow window) {
try {
ResultsInstance results = ResultsInstance.fromFile(xmlFile);
window.getShell().getDisplay().asyncExec(() -> {
try {
ResultsPageUtil.closePages();
MBASSynthesisResultsView.results = results;
MBASSynthesisResultsView.applyToProject = () -> SynthesisAadlWriter.perform(project, projectDir, results);
window.getActivePage().showView(MBASSynthesisResultsView.ID);
} catch (PartInitException e) {
e.printStackTrace();
}
});
} catch (SAXException | IOException | ParserConfigurationException e) {
e.printStackTrace();
}
}
use of com.ge.verdict.vdm.synthesis.ResultsInstance in project VERDICT by ge-high-assurance.
the class App method runMbasSynthesis.
/**
* Run MBAS Synthesis with CSV input files
*
* @param vdmPath VDM input file for synthesis
* @param modelName Name of model
* @param stemDir output directory for STEM input files
* @param soteriaDir output directory for Soteria++ input files
* @throws VerdictRunException
*/
public static void runMbasSynthesis(String vdmPath, String modelName, String stemProjectDir, String debugDir, String soteriaPpBin, boolean cyberInference, boolean safetyInference, boolean partialSolution, String costModelPath, String outputPath) throws VerdictRunException {
String stemCsvDir = (new File(stemProjectDir, "CSVData")).getAbsolutePath();
String stemOutputDir = (new File(stemProjectDir, "Output")).getAbsolutePath();
String stemGraphsDir = (new File(stemProjectDir, "Graphs")).getAbsolutePath();
String stemSadlFile = (new File(stemProjectDir, "Run.sadl")).getAbsolutePath();
File soteriaOutputDir = new File(stemOutputDir, "Soteria_Output");
soteriaOutputDir.mkdirs();
String soteriaPpOutputDir = soteriaOutputDir.getAbsolutePath();
checkFile(stemCsvDir, true, true, true, false, null);
checkFile(stemOutputDir, true, true, true, false, null);
checkFile(stemGraphsDir, true, true, true, false, null);
checkFile(stemSadlFile, true, false, false, false, null);
checkFile(soteriaPpOutputDir, true, true, true, false, null);
checkFile(soteriaPpBin, true, false, false, true, null);
checkFile(vdmPath, true, false, false, false, "xml");
checkFile(costModelPath, true, false, false, false, "xml");
checkFile(outputPath, false, false, true, false, "xml");
deleteDirectoryContents(stemGraphsDir);
deleteDirectoryContents(soteriaPpOutputDir);
if (debugDir != null) {
logHeader("DEBUGGING XML OUTPUT");
}
try {
// Copy Soteria++ pngs
for (String soteria_png : soteria_pngs) {
Binary.copyResource("soteria_pngs/" + soteria_png + ".png", new File(soteriaPpOutputDir, soteria_png + ".png"), false);
}
} catch (Binary.ExecutionException e) {
throw new VerdictRunException("Failed to copy Soteria++ pngs", e);
}
logHeader("STEM");
log("STEM project directory: " + stemProjectDir);
log("STEM output directory: " + stemOutputDir);
log("STEM graphs directory: " + stemGraphsDir);
log("STEM is running. Please be patient...");
VerdictStem stemRunner = new VerdictStem();
Metrics.timer("Timer.mbas.stem", "model", modelName).record(() -> stemRunner.runStem(new File(stemProjectDir), new File(stemOutputDir), new File(stemGraphsDir)));
log("STEM finished!");
logHeader("Synthesis");
try {
Timer.Sample sample = Timer.start(Metrics.globalRegistry);
CostModel costModel = new CostModel(new File(costModelPath));
AttackDefenseCollector collector = new AttackDefenseCollector(new File(vdmPath), new File(stemOutputDir), cyberInference);
List<AttackDefenseCollector.Result> results = collector.perform();
boolean sat = results.stream().allMatch(result -> Prob.lte(result.prob, result.cyberReq.getSeverity()));
boolean performMeritAssignment = partialSolution && sat;
DLeaf.Factory factory = new DLeaf.Factory();
DTree dtree = DTreeConstructor.construct(results, costModel, partialSolution, performMeritAssignment, factory);
Optional<ResultsInstance> selected = VerdictSynthesis.performSynthesisMultiple(dtree, factory, costModel, partialSolution, sat, performMeritAssignment, false);
if (selected.isPresent()) {
if (performMeritAssignment) {
ResultsInstance withExtraDefProps = VerdictSynthesis.addExtraImplDefenses(selected.get(), collector.getImplDal(), costModel);
withExtraDefProps.toFileXml(new File(outputPath));
} else {
selected.get().toFileXml(new File(outputPath));
}
log("Synthesis results output to " + outputPath);
} else {
logError("Synthesis failed");
}
sample.stop(Metrics.timer("Timer.mbas.synthesis", "model", modelName));
} catch (IOException | MalformedInputException e) {
throw new VerdictRunException("Failed to execute synthesis", e);
}
logHeader("Finished");
}
use of com.ge.verdict.vdm.synthesis.ResultsInstance in project VERDICT by ge-high-assurance.
the class VerdictSynthesisTest method biggerMeritAssignmentTest.
@Test
public void biggerMeritAssignmentTest() {
CostModel costModel = new CostModel(new File(getClass().getResource("meritCosts.xml").getPath()));
SystemModel system = new SystemModel("C1");
Attack attack1 = new Attack(system.getAttackable(), "A1", "An attack", Prob.certain(), CIA.I);
Defense defense1 = new Defense(attack1);
defense1.addDefenseClause(Collections.singletonList(new Defense.DefenseLeaf("D1", Optional.of(new com.ge.verdict.attackdefensecollector.Pair<>("D1", 1)))));
Attack attack2 = new Attack(system.getAttackable(), "A2", "An attack", Prob.certain(), CIA.I);
Defense defense2 = new Defense(attack2);
defense2.addDefenseClause(Collections.singletonList(new Defense.DefenseLeaf("D2", Optional.of(new com.ge.verdict.attackdefensecollector.Pair<>("D2", 1)))));
ADTree adtree = new ADAnd(new ADOr(new ADAnd(new ADNot(defense1), attack1)), new ADOr(new ADAnd(new ADNot(defense2), attack2)));
DLeaf.Factory factory = new DLeaf.Factory();
List<AttackDefenseCollector.Result> results = Arrays.asList(new AttackDefenseCollector.Result(system, new CyberReq("req1", "mission1", 1, "port1", CIA.I), adtree, Prob.certain()));
Optional<ResultsInstance> result = VerdictSynthesis.performSynthesisMultiple(DTreeConstructor.construct(results, costModel, true, true, factory), factory, costModel, true, true, true, false);
Assertions.assertThat(result.isPresent());
Assertions.assertThat(result.get().items.size()).isEqualTo(2);
Assertions.assertThat(result.get().outputCost).isEqualTo(new Fraction(1));
}
Aggregations