Adding checks to ensure that a predecessor is only recorded once for a transition.
[jpf-core.git] / src / main / gov / nasa / jpf / listener / DPORStateReducerEfficient.java
index 7512691915478dfd6c6bd197864a5fbb3d602957..aa54e5ee1e85c2203b5262276bcb2bb7fc2ec1e1 100644 (file)
@@ -444,6 +444,11 @@ public class DPORStateReducerEfficient extends ListenerAdapter {
     }
 
     public HashMap<Integer, SummaryNode> getReachableTransitionsSummary(int stateId) {
+      // Just return an empty map if the state ID is not recorded yet
+      // This means that there is no reachable transition from this state
+      if (!graphSummary.containsKey(stateId)) {
+        return new HashMap<>();
+      }
       return graphSummary.get(stateId);
     }
 
@@ -613,6 +618,8 @@ public class DPORStateReducerEfficient extends ListenerAdapter {
     private int choiceCounter;                 // Choice counter at this transition
     private Execution execution;               // The execution where this transition belongs
     private HashSet<Predecessor> predecessors; // Maps incoming events/transitions (execution and choice)
+    private HashMap<Execution, HashSet<Integer>> recordedPredecessors;
+                                               // Memorize event and choice number to not record them twice
     private int stateId;                       // State at this transition
     private IntChoiceFromSet transitionCG;     // CG at this transition
 
@@ -621,6 +628,7 @@ public class DPORStateReducerEfficient extends ListenerAdapter {
       choiceCounter = 0;
       execution = null;
       predecessors = new HashSet<>();
+      recordedPredecessors = new HashMap<>();
       stateId = 0;
       transitionCG = null;
     }
@@ -647,8 +655,28 @@ public class DPORStateReducerEfficient extends ListenerAdapter {
 
     public IntChoiceFromSet getTransitionCG() { return transitionCG; }
 
+    private boolean isRecordedPredecessor(Execution execution, int choice) {
+      // See if we have recorded this predecessor earlier
+      HashSet<Integer> recordedChoices;
+      if (recordedPredecessors.containsKey(execution)) {
+        recordedChoices = recordedPredecessors.get(execution);
+        if (recordedChoices.contains(choice)) {
+          return true;
+        }
+      } else {
+        recordedChoices = new HashSet<>();
+        recordedPredecessors.put(execution, recordedChoices);
+      }
+      // Record the choice if we haven't seen it
+      recordedChoices.add(choice);
+
+      return false;
+    }
+
     public void recordPredecessor(Execution execution, int choice) {
-      predecessors.add(new Predecessor(choice, execution));
+      if (!isRecordedPredecessor(execution, choice)) {
+        predecessors.add(new Predecessor(choice, execution));
+      }
     }
 
     public void setChoice(int cho) {