diff --git a/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/Constraint.java b/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/Constraint.java index 1b718a2a..385bb2d6 100644 --- a/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/Constraint.java +++ b/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/Constraint.java @@ -54,7 +54,7 @@ public boolean isMatched(DFDVertex vertex) { } }; this.mitigations = determineMitigations(); - + setPreconditionLabels(); } public Constraint(List mitigations) { @@ -72,18 +72,7 @@ public List getMitigations() { } public boolean isPrecondition(CompositeLabel label) { - if (dslConstraint == null) { - return preconditionLabel.contains(label); - } - var translation = new CNFTranslation(dslConstraint); - var literals = translation.constructCNF().get(0).literals(); - - for (var literal : literals) { - if (!literal.positive() && literal.compositeLabel().equals(label)) { - return true; - } - } - return false; + return preconditionLabel.contains(label); } public void addPrecondition(CompositeLabel label) { @@ -112,6 +101,12 @@ public void findAlternativeMitigations() { public Set determineViolations(DFDFlowGraphCollection flowGraph) { return evaluationFunction.evaluate(flowGraph); } + + private void setPreconditionLabels(){ + for (var lit : new CNFTranslation(dslConstraint).constructCNF().get(0).literals()) { + if (!lit.positive()) preconditionLabel.add(lit.compositeLabel()); + } + } private Set getDSLViolations(DFDFlowGraphCollection flowGraph) { Set violatingNodes = new HashSet<>(); diff --git a/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/ILPSolver.java b/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/ILPSolver.java index 6df71fc5..8ec078f6 100644 --- a/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/ILPSolver.java +++ b/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/ILPSolver.java @@ -137,27 +137,37 @@ public List solve(List> mitigations, Set chosen = new ArrayList<>(); - for (MPVariable variable : solver.variables()) { - if (variable.solutionValue() > 0.5) { - // skip auxiliary variables introduced by required semantic - if (variable.name().startsWith("required_") || variable.name().startsWith("y_")) { - continue; - } - - Optional mitigation = allMitigations.stream() - .filter(m -> variable.name().equals(m.toString())).findFirst(); - if (mitigation.isPresent()) { - chosen.add(mitigation.get()); - } - } - } - return chosen; - } else { - System.out.println("No feasible solution: " + status); - return null; + try { + if (status == MPSolver.ResultStatus.OPTIMAL || status == MPSolver.ResultStatus.FEASIBLE) { + List chosen = new ArrayList<>(); + for (MPVariable variable : solver.variables()) { + if (variable.solutionValue() > 0.5) { + // skip auxiliary variables introduced by required semantic + if (variable.name().startsWith("required_") || variable.name().startsWith("y_")) { + continue; + } + + Optional mitigation = allMitigations.stream() + .filter(m -> variable.name().equals(m.toString())).findFirst(); + if (mitigation.isPresent()) { + chosen.add(mitigation.get()); + } + } + } + return chosen; + } else { + System.out.println("No feasible solution: " + status); + return null; + } } + finally { + // Explicitly free the native SCIP instance now rather than waiting for GC. + // Without this, the finalizer of a previous MPSolver may run during a later + // test's solve() call and corrupt SCIP's global state, causing sync_status_ + // to reset to MUST_RELOAD even when Solve() returned OPTIMAL. + solver.delete(); + } + } /*** diff --git a/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/Node.java b/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/Node.java index 47d9b7f6..4a0e61b2 100644 --- a/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/Node.java +++ b/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/Node.java @@ -66,7 +66,7 @@ public List> getPrevious() { return previous; } - public List getPossibleMitigations() { + public List getPossibleMitigations(boolean restrictedToAdding) { List mitigations = new ArrayList<>(); for (var constraint : violatingConstraints) { for (var mitigation : constraint.getMitigations()) { @@ -79,41 +79,56 @@ public List getPossibleMitigations() { mitigations.addAll(getDataMitigations(mitigation, ActionType.Adding)); } case DeleteNodeLabel -> { - mitigation.checkIfAllowed(vertex); - mitigations.add(new Mitigation(new ActionTerm(this.name, mitigation.label, ActionType.Removing), - mitigation.cost, getAllRequiredMitigations(mitigation))); + if (!restrictedToAdding) { + mitigation.checkIfAllowed(vertex); + mitigations.add(new Mitigation(new ActionTerm(this.name, mitigation.label, ActionType.Removing), + mitigation.cost, getAllRequiredMitigations(mitigation))); + } } case DeleteDataLabel -> { - mitigations.addAll(getDataMitigations(mitigation, ActionType.Removing)); + if (!restrictedToAdding) { + mitigations.addAll(getDataMitigations(mitigation, ActionType.Removing)); + } } case AddNode -> { - if (this.outgoingFlow == null) { - mitigations.add(new Mitigation(new ActionTerm(this.name, mitigation.label, ActionType.AddSink), - mitigation.cost, getAllRequiredMitigations(mitigation))); - } else { - mitigations.add(new Mitigation( - new ActionTerm(this.outgoingFlow.getId(), mitigation.label, ActionType.AddNode), - mitigation.cost, getAllRequiredMitigations(mitigation))); - mitigations.addAll(getNodeAdditionMitigations(mitigation)); + if (!restrictedToAdding) { + if (this.outgoingFlow == null) { + mitigations + .add(new Mitigation(new ActionTerm(this.name, mitigation.label, ActionType.AddSink), + mitigation.cost, getAllRequiredMitigations(mitigation))); + } else { + mitigations.add(new Mitigation( + new ActionTerm(this.outgoingFlow.getId(), mitigation.label, ActionType.AddNode), + mitigation.cost, getAllRequiredMitigations(mitigation))); + mitigations.addAll(getNodeAdditionMitigations(mitigation)); + } + } } case AddSink -> { - mitigations.add(new Mitigation(new ActionTerm(this.name, mitigation.label, ActionType.AddSink), - mitigation.cost, getAllRequiredMitigations(mitigation))); - mitigations.addAll(getSinkAdditionMitigations(mitigation)); + if (!restrictedToAdding) { + mitigations.add(new Mitigation(new ActionTerm(this.name, mitigation.label, ActionType.AddSink), + mitigation.cost, getAllRequiredMitigations(mitigation))); + mitigations.addAll(getSinkAdditionMitigations(mitigation)); + } } case DeleteNode -> { - mitigations.add(new Mitigation(new ActionTerm(this.name, mitigation.label, ActionType.RemoveNode), - mitigation.cost, getAllRequiredMitigations(mitigation))); - } - case DeleteFlow -> { - for (var incomingFlow : this.vertex.getPinFlowMap().values()) { + if (!restrictedToAdding) { mitigations - .add(new Mitigation(new ActionTerm(incomingFlow.getId(), null, ActionType.RemoveFlow), + .add(new Mitigation(new ActionTerm(this.name, mitigation.label, ActionType.RemoveNode), mitigation.cost, getAllRequiredMitigations(mitigation))); } } + case DeleteFlow -> { + if (!restrictedToAdding) { + for (var incomingFlow : this.vertex.getPinFlowMap().values()) { + mitigations.add( + new Mitigation(new ActionTerm(incomingFlow.getId(), null, ActionType.RemoveFlow), + mitigation.cost, getAllRequiredMitigations(mitigation))); + } + } + } default -> throw new IllegalArgumentException("Unexpected value: " + mitigation.type); @@ -194,8 +209,7 @@ private List> getAllRequiredMitigations(MitigationStrategy miti ActionType type; if (mitgation.type.toString().startsWith("Delete")) { type = ActionType.Removing; - } - else if (mitgation.type == MitigationType.AddNode) { + } else if (mitgation.type == MitigationType.AddNode) { type = ActionType.AddNode; } else if (mitgation.type == MitigationType.AddSink) { type = ActionType.AddSink; diff --git a/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/OptimizationManager.java b/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/OptimizationManager.java index 076f9aa6..e322fcad 100644 --- a/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/OptimizationManager.java +++ b/bundles/dev.arcovia.mitigation.ilp/src/dev/arcovia/mitigation/ilp/OptimizationManager.java @@ -28,10 +28,11 @@ import dev.arcovia.mitigation.sat.CompositeLabel; import dev.arcovia.mitigation.sat.LabelCategory; +import dev.arcovia.mitigation.sat.MitigationApproach; import dev.arcovia.mitigation.sat.NodeLabel; import dev.arcovia.mitigation.sat.timeMeasurement; -public class OptimizationManager { +public class OptimizationManager implements MitigationApproach{ private final DataFlowDiagramAndDictionary dfd; Map outPinToAssignmentMap = new HashMap<>(); @@ -50,6 +51,8 @@ public class OptimizationManager { private List actions; private List result; + + private boolean isRestritedToLabelAddition = false; public OptimizationManager(String dfdLocation, List constraints) { this.dfd = new Web2DFDConverter().convert(new WebEditorConverterModel(dfdLocation)); @@ -91,7 +94,7 @@ public DataFlowDiagramAndDictionary repair() throws Exception { analyseDFD(); for (var node : violatingNodes) { - addMitigations(node.getPossibleMitigations()); + addMitigations(node.getPossibleMitigations(isRestritedToLabelAddition)); } for (var mitigation : allMitigations) { @@ -99,6 +102,11 @@ public DataFlowDiagramAndDictionary repair() throws Exception { contradictions.addAll(determineContradictions(mitigation)); } } + + //if no violation found return dfd + if (mitigations.isEmpty()) { + return dfd; + } var solver = new ILPSolver(); result = solver.solve(mitigations, allMitigations, contradictions); @@ -121,7 +129,7 @@ public DataFlowDiagramAndDictionary repair(timeMeasurement timer) throws Excepti timer.analysis(); for (var node : violatingNodes) { - addMitigations(node.getPossibleMitigations()); + addMitigations(node.getPossibleMitigations(isRestritedToLabelAddition)); } for (var mitigation : allMitigations) { @@ -129,6 +137,13 @@ public DataFlowDiagramAndDictionary repair(timeMeasurement timer) throws Excepti contradictions.addAll(determineContradictions(mitigation)); } } + + //if no violation found return dfd + if (mitigations.isEmpty()) { + timer.solving(); + timer.stop(); + return dfd; + } var solver = new ILPSolver(); result = solver.solve(mitigations, allMitigations, contradictions); @@ -143,7 +158,12 @@ public DataFlowDiagramAndDictionary repair(timeMeasurement timer) throws Excepti return dfd; } - + + @Override + public void restrictToLabelAddition() { + isRestritedToLabelAddition = true; + } + public int getCost() { int cost = 0; for (var mitigation : result) { @@ -448,12 +468,9 @@ private void addNodes(DataFlowDiagramAndDictionary dfd, List actions var flow = dataFlowDiagram.getFlows().stream().filter(f -> f.getId().equals(action.domain())) .findFirst().orElseThrow(); - var node = flow.getSourceNode(); - var name = action.compositeLabels().get(0).label().value(); - var behaviorOld = node.getBehavior(); - + var dfdFactory = dataflowdiagramFactory.eINSTANCE; var vertex = dfdFactory.createProcess(); @@ -481,8 +498,6 @@ private void addNodes(DataFlowDiagramAndDictionary dfd, List actions behaviorNew.getInPin().add(inPin); - Set