From e1366f95d8f9a1b026a255c6ed189bdb7d822485 Mon Sep 17 00:00:00 2001 From: tempiaa <tempiaa@eurecom.fr> Date: Fri, 17 Jul 2020 11:54:05 +0200 Subject: [PATCH] Extended internal loops check for loops intersections --- .../avatartranslator/AvatarSpecification.java | 25 +- .../avatartranslator/AvatarStateMachine.java | 7 +- .../modelchecker/AvatarModelChecker.java | 46 ++-- .../modelchecker/SpecificationActionLoop.java | 214 ++++++++++++++---- .../ui/window/JDialogUPPAALValidation.java | 10 +- 5 files changed, 219 insertions(+), 83 deletions(-) diff --git a/src/main/java/avatartranslator/AvatarSpecification.java b/src/main/java/avatartranslator/AvatarSpecification.java index d6b46e511c..532aa9ac1c 100644 --- a/src/main/java/avatartranslator/AvatarSpecification.java +++ b/src/main/java/avatartranslator/AvatarSpecification.java @@ -453,27 +453,6 @@ public class AvatarSpecification extends AvatarElement { } } - public List<ArrayList<AvatarTransition>> checkStaticInternalLoops() { - List<ArrayList<AvatarTransition>> loops = new ArrayList<ArrayList<AvatarTransition>>(); - - //collect all the possible loops which do not contain signal communication - for(AvatarBlock block: blocks) { - block.getStateMachine().checkStaticInternalLoops(loops); - } - - return loops; - -// //check presence of unguarded loops -// for (ArrayList<AvatarTransition> trace : loops) { -// boolean guarded = false; -// for (AvatarTransition at : trace) { -// guarded |= at.isGuarded(); -// } -// if (!guarded) { -// //no transition has a guard check --> reachability of first state -// } -// } - } // // private void renameTimers() { // // Check whether timers have the same name in different blocks @@ -643,9 +622,9 @@ public class AvatarSpecification extends AvatarElement { if (ancientGuard == null) continue; - //TraceManager.addDev("[[[[[[[[[[[[[[[ Guard before: " + ancientGuard.toString()); + TraceManager.addDev("[[[[[[[[[[[[[[[ Guard before: " + ancientGuard.toString()); at.setGuard (ancientGuard.getRealGuard (asme)); - //TraceManager.addDev("]]]]]]]]]]]]]]] Guard after: " + at.getGuard().toString()); + TraceManager.addDev("]]]]]]]]]]]]]]] Guard after: " + at.getGuard().toString()); } } } diff --git a/src/main/java/avatartranslator/AvatarStateMachine.java b/src/main/java/avatartranslator/AvatarStateMachine.java index 4c8b6310f3..8e2503ca02 100644 --- a/src/main/java/avatartranslator/AvatarStateMachine.java +++ b/src/main/java/avatartranslator/AvatarStateMachine.java @@ -1869,11 +1869,12 @@ public class AvatarStateMachine extends AvatarElement { } - public boolean checkStaticInternalLoops(List<ArrayList<AvatarTransition>> loops) { + public List<ArrayList<AvatarTransition>> checkStaticInternalLoops() { if (allStates == null) { - return false; + return null; } + List<ArrayList<AvatarTransition>> loops = new ArrayList<ArrayList<AvatarTransition>>(); List<AvatarTransition> trace = new ArrayList<AvatarTransition>(); Set<AvatarStateMachineElement> visited= new HashSet<AvatarStateMachineElement>(); @@ -1881,7 +1882,7 @@ public class AvatarStateMachine extends AvatarElement { checkStaticInternalLoopsRec(state, state, trace, visited, loops, 0); visited.add(state); //avoid cycles permutations } - return true; + return loops; } diff --git a/src/main/java/avatartranslator/modelchecker/AvatarModelChecker.java b/src/main/java/avatartranslator/modelchecker/AvatarModelChecker.java index 1d79f836e4..84bbba7817 100644 --- a/src/main/java/avatartranslator/modelchecker/AvatarModelChecker.java +++ b/src/main/java/avatartranslator/modelchecker/AvatarModelChecker.java @@ -570,22 +570,44 @@ public class AvatarModelChecker implements Runnable, myutil.Graph { if (studyAL) { studySafety = true; ignoreConcurrenceBetweenInternalActions = true; - List<ArrayList<AvatarTransition>> internalLoops = spec.checkStaticInternalLoops(); - if (!internalLoops.isEmpty()) { - actionLoops = new ArrayList<SpecificationActionLoop>(); - for (ArrayList<AvatarTransition> loop : internalLoops) { - SpecificationActionLoop sap = new SpecificationActionLoop(loop, spec); + actionLoops = new ArrayList<SpecificationActionLoop>(); + List<ArrayList<AvatarTransition>> internalLoops; + for(AvatarBlock block : spec.getListOfBlocks()) { + internalLoops = block.getStateMachine().checkStaticInternalLoops(); + if (internalLoops != null && internalLoops.isEmpty() == false) { +// for (ArrayList<AvatarTransition> loop : internalLoops) { +// SpecificationActionLoop sap = new SpecificationActionLoop(loop, spec); +// if (!sap.hasError()) { +// actionLoops.add(sap); +// safety = sap.getReachability(); +// startModelChecking(nbOfThreads); +// resetModelChecking(); +// if (sap.hasProperty()) { +// safety = sap.getProperty(); +// startModelChecking(nbOfThreads); +// resetModelChecking(); +// } +// sap.setResult(); +// } +// } + SpecificationActionLoop sap = new SpecificationActionLoop(internalLoops, spec); if (!sap.hasError()) { actionLoops.add(sap); - safety = sap.getReachability(); - startModelChecking(nbOfThreads); - resetModelChecking(); - if (sap.hasProperty()) { - safety = sap.getProperty(); + do { + safety = sap.getReachability(); startModelChecking(nbOfThreads); resetModelChecking(); - } + if (sap.hasProperty()) { + safety = sap.getProperty(); + startModelChecking(nbOfThreads); + resetModelChecking(); + } + if (sap.setCover()) { + break; + } + } while (sap.increasePointer()); sap.setResult(); + } } } @@ -833,8 +855,6 @@ public class AvatarModelChecker implements Runnable, myutil.Graph { prepareTransitions(); prepareBlocks(); - - spec.checkStaticInternalLoops(); nbOfThreads = Runtime.getRuntime().availableProcessors(); TraceManager.addDev("Starting the model checking with " + nbOfThreads + " threads"); diff --git a/src/main/java/avatartranslator/modelchecker/SpecificationActionLoop.java b/src/main/java/avatartranslator/modelchecker/SpecificationActionLoop.java index c5da755352..d49c6af052 100644 --- a/src/main/java/avatartranslator/modelchecker/SpecificationActionLoop.java +++ b/src/main/java/avatartranslator/modelchecker/SpecificationActionLoop.java @@ -1,53 +1,96 @@ package avatartranslator.modelchecker; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import avatartranslator.AvatarBlock; import avatartranslator.AvatarSpecification; +import avatartranslator.AvatarStateMachineElement; import avatartranslator.AvatarTransition; public class SpecificationActionLoop { - private List<AvatarTransition> path; - private SafetyProperty reachability; - private SafetyProperty property; - private boolean hasProperty; + private List<ArrayList<AvatarTransition>> internalLoops; + private SafetyProperty [] reachabilities; + private SafetyProperty [] properties; + private AvatarStateMachineElement [] states; + private int [] cover; //0: non reachable; 1: reachable; 2: reachable with exit private boolean result; private boolean error; + private int pointer; - public SpecificationActionLoop(List<AvatarTransition> path, AvatarSpecification spec) { - this.path = path; + + public SpecificationActionLoop(List<ArrayList<AvatarTransition>> paths, AvatarSpecification spec) { + //this.path = path; this.error = false; + pointer = 0; + internalLoops = paths; init(spec); } + private void init(AvatarSpecification spec) { - //check presence of unguarded loops - boolean guarded = false; - StringBuilder condition = new StringBuilder("!("); - for (AvatarTransition at : path) { - if (at.isGuarded()) { - String guard = at.getGuard().toString().replaceAll("\\[", "").trim().replaceAll("\\]", ""); - if (guarded) { - condition.append(" && " + guard); + Map<AvatarStateMachineElement, Set<AvatarTransition>> map = new HashMap<>(); + + for (List<AvatarTransition> list : internalLoops) { + AvatarStateMachineElement state = list.get(list.size() -1).getNext(0); //loop state + for (AvatarTransition at : list) { + if (map.containsKey(state)) { + map.get(state).add(at); } else { - condition.append(guard); - } - guarded = true; + Set<AvatarTransition> transitions = new HashSet<>(); + transitions.add(at); + map.put(state, transitions); + } + state = at.getNext(0); } } - condition.append(")"); - AvatarTransition at = path.get(path.size() - 1); - //no transition has a guard check --> reachability of first state - reachability = new SafetyProperty("E<> " + at.getBlock().getName() + "." + at.getNext(0).getName()); - reachability.analyzeProperty(spec); - error = reachability.hasError(); - hasProperty = false; - if (guarded) { - hasProperty = true; - property = new SafetyProperty("E<> " + at.getNext(0).getName() + " && " + condition.toString()); - property.analyzeProperty((AvatarBlock) at.getBlock(), spec); - error |= property.hasError(); + + reachabilities = new SafetyProperty[map.keySet().size()]; + properties = new SafetyProperty[map.keySet().size()]; + states = new AvatarStateMachineElement[map.keySet().size()]; + cover = new int[internalLoops.size()]; + + AvatarBlock block = (AvatarBlock) internalLoops.get(0).get(0).getBlock(); + + int i = 0; + for (AvatarStateMachineElement el : map.keySet()) { + Set<AvatarTransition> set = map.get(el); + + states[i] = el; + + SafetyProperty reachability = new SafetyProperty("E<> " + el.getName()); + reachability.analyzeProperty(block, spec); + error |= reachability.hasError(); + reachabilities[i] = reachability; + + boolean guarded = false; + StringBuilder subCondition = new StringBuilder("!("); + for (AvatarTransition at : set) { + if (at.isGuarded()) { + String guard = at.getGuard().toString().replaceAll("\\[", "").trim().replaceAll("\\]", ""); + if (guarded) { + subCondition.append(" || " + guard); + } else { + subCondition.append(guard); + } + guarded = true; + } + } + subCondition.append(")"); + if (guarded) { + SafetyProperty property = new SafetyProperty("E<> " + el.getName() + " && " + subCondition.toString()); + property.analyzeProperty(block, spec); + error |= property.hasError(); + properties[i] = property; + } + i++; } + + } public boolean hasError() { @@ -55,21 +98,71 @@ public class SpecificationActionLoop { } public boolean hasProperty() { - return hasProperty; + if (pointer < properties.length && reachabilities[pointer].result) { + return properties[pointer] != null; + } + return false; } public SafetyProperty getReachability() { - return reachability; + if (pointer < reachabilities.length) { + return reachabilities[pointer]; + } + return null; } public SafetyProperty getProperty() { - return property; + if (pointer < properties.length && reachabilities[pointer].result) { + return properties[pointer]; + } + return null; + } + + public boolean increasePointer() { + if (pointer < states.length - 1) { + pointer++; + return true; + } + return false; } - public void setResult() { - result = reachability.result; - if (hasProperty) { - result &= !property.result; + public boolean setCover() { + int i = 0; + + if (reachabilities[pointer].result) { + AvatarStateMachineElement state = states[pointer]; + for (List<AvatarTransition> list : internalLoops) { + if (cover[i] != 2) { + for (AvatarTransition at : list) { + if (at.getNext(0) == state) { + if (properties[pointer] != null && properties[pointer].result) { + cover[i] = 2; + } else { + cover[i] = 1; + } + break; + } + } + } + i++; + } + } + + for (i = 0; i < internalLoops.size(); i++) { + if (cover[i] != 2) { + return false; + } + } + return true; + } + + public void setResult() { + result = false; + for (int i = 0; i < internalLoops.size(); i++) { + if (cover[i] == 1) { + result = true; + break; + } } } @@ -80,11 +173,54 @@ public class SpecificationActionLoop { public String toString() { StringBuilder s = new StringBuilder(); - s.append("In block " + path.get(path.size() - 1).getBlock().getName() + " : " + path.get(path.size() - 1).getNext(0).getName()); - for (AvatarTransition at : path) { - s.append(" --> " + at.getNext(0).getName()); + if(internalLoops == null) { + return ""; + } + + int i = 0; + for (List<AvatarTransition> list : internalLoops) { + if (cover[i] == 1) { + s.append("In block " + list.get(list.size() - 1).getBlock().getName() + " : " + list.get(list.size() - 1).getNext(0).getName()); + for (AvatarTransition at : list) { + s.append(" --> " + at.getNext(0).getName()); + } + } + i++; + s.append("\n"); } return s.toString(); } + +// public static void findIntersectionSets(List<ArrayList<AvatarTransition>> internalLoops) { +// if (internalLoops == null || internalLoops.size() <= 1) { +// return; +// } +// +// internalLoops.sort((x1, x2) -> {return x2.size() - x1.size();}); +// +// Set<AvatarStateMachineElement> states = new HashSet<>(); +// Set<AvatarStateMachineElement> intersection = new HashSet<>(); +// +// for (AvatarTransition at : internalLoops.get(0)) { +// states.add(at.getNext(0)); +// } +// +// int i = 0; +// for (List<AvatarTransition> list : internalLoops) { +// if (i == 0) { +// i++; +// continue; +// } +// for (AvatarTransition at : list) { +// if (states.contains(at.getNext(0))) { +// intersection.add(at.getNext(0)); +// } +// } +// if (intersection.size() != 0) { +// states = intersection; +// intersection = new HashSet<>(); +// } +// } +// } } diff --git a/src/main/java/ui/window/JDialogUPPAALValidation.java b/src/main/java/ui/window/JDialogUPPAALValidation.java index aee1119315..322db10b84 100644 --- a/src/main/java/ui/window/JDialogUPPAALValidation.java +++ b/src/main/java/ui/window/JDialogUPPAALValidation.java @@ -82,11 +82,11 @@ public class JDialogUPPAALValidation extends javax.swing.JDialog implements Acti "for UPPAALVerifierPath and UPPAALVerifierHost configurations."; static { - for (final String label : ConfigurationTTool.UPPAALPropertyVerifMessage.split(",")) { - if (!label.trim().isEmpty()) { - PROP_VERIFIED_LABELS.add(label.trim()); - } - } +// for (final String label : ConfigurationTTool.UPPAALPropertyVerifMessage.split(",")) { +// if (!label.trim().isEmpty()) { +// PROP_VERIFIED_LABELS.add(label.trim()); +// } +// } // Handle the case where nothing is defined in the configuration if (PROP_VERIFIED_LABELS.isEmpty()) { -- GitLab