diff --git a/prism/src/explicit/MDPModelChecker.java b/prism/src/explicit/MDPModelChecker.java index 78549e10..916af42e 100644 --- a/prism/src/explicit/MDPModelChecker.java +++ b/prism/src/explicit/MDPModelChecker.java @@ -27,6 +27,7 @@ package explicit; import java.util.BitSet; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -581,6 +582,9 @@ public class MDPModelChecker extends ProbModelChecker throw new PrismException(msg); } + // Prune adversary + restrictAdversaryToReachableStates(mdp, adv); + // Print adversary if (genAdv) { PrismLog out = new PrismFileLog(exportAdvFilename); @@ -1269,6 +1273,48 @@ public class MDPModelChecker extends ProbModelChecker return mdp.mvMultRewMinMaxSingleChoices(state, lastSoln, mdpRewards, min, val); } + /** + * Restrict a (memoryless) adversary for an MDP, stored as an integer array of choice indices, + * to the states of the MDP that are reachable under that adversary. + * @param mdp The MDP + * @param adv The adversary + */ + public void restrictAdversaryToReachableStates(MDP mdp,int adv[]) + { + BitSet restrict = new BitSet(); + BitSet explore = new BitSet(); + // Get initial states + for (int is : mdp.getInitialStates()) { + restrict.set(is); + explore.set(is); + } + // Compute reachable states (store in 'restrict') + boolean foundMore = true; + while (foundMore) { + foundMore = false; + for (int s = explore.nextSetBit(0); s >= 0; s = explore.nextSetBit(s + 1)) { + explore.set(s, false); + if (adv[s] >= 0) { + Iterator> iter = mdp.getTransitionsIterator(s, adv[s]); + while (iter.hasNext()) { + Map.Entry e = iter.next(); + int dest = e.getKey(); + if (!restrict.get(dest)) { + foundMore = true; + restrict.set(dest); + explore.set(dest); + } + } + } + } + } + // Set adversary choice for non-reachable state to -1 + int n = mdp.getNumStates(); + for (int s = restrict.nextClearBit(0); s < n; s = restrict.nextClearBit(s + 1)) { + adv[s] = -1; + } + } + /** * Simple test program. */