/** * Compute bounded reachability/until probabilities. i.e. compute the min/max probability of * reaching a state in {@code target}, within k steps, and while remaining in states in @{code * remain}. * * @param stpg The STPG * @param remain Remain in these states (optional: null means "all") * @param target Target states * @param k Bound * @param min1 Min or max probabilities for player 1 (true=lower bound, false=upper bound) * @param min2 Min or max probabilities for player 2 (true=min, false=max) * @param init Initial solution vector - pass null for default * @param results Optional array of size k+1 to store (init state) results for each step (null if * unused) */ public ModelCheckerResult computeBoundedReachProbs( STPG stpg, BitSet remain, BitSet target, int k, boolean min1, boolean min2, double init[], double results[]) throws PrismException { // TODO: implement until ModelCheckerResult res = null; int i, n, iters; double soln[], soln2[], tmpsoln[]; long timer; // Start bounded probabilistic reachability timer = System.currentTimeMillis(); if (verbosity >= 1) mainLog.println("\nStarting bounded probabilistic reachability..."); // Store num states n = stpg.getNumStates(); // Create solution vector(s) soln = new double[n]; soln2 = (init == null) ? new double[n] : init; // Initialise solution vectors. Use passed in initial vector, if present if (init != null) { for (i = 0; i < n; i++) soln[i] = soln2[i] = target.get(i) ? 1.0 : init[i]; } else { for (i = 0; i < n; i++) soln[i] = soln2[i] = target.get(i) ? 1.0 : 0.0; } // Store intermediate results if required // (compute min/max value over initial states for first step) if (results != null) { results[0] = Utils.minMaxOverArraySubset(soln2, stpg.getInitialStates(), min2); } // Start iterations iters = 0; while (iters < k) { iters++; // Matrix-vector multiply and min/max ops stpg.mvMultMinMax(soln, min1, min2, soln2, target, true, null); // Store intermediate results if required // (compute min/max value over initial states for this step) if (results != null) { results[iters] = Utils.minMaxOverArraySubset(soln2, stpg.getInitialStates(), min2); } // Swap vectors for next iter tmpsoln = soln; soln = soln2; soln2 = tmpsoln; } // Print vector (for debugging) // mainLog.println(soln); // Finished bounded probabilistic reachability timer = System.currentTimeMillis() - timer; if (verbosity >= 1) { mainLog.print( "Bounded probabilistic reachability (" + (min1 ? "min" : "max") + (min2 ? "min" : "max") + ")"); mainLog.println(" took " + iters + " iterations and " + timer / 1000.0 + " seconds."); } // Return results res = new ModelCheckerResult(); res.soln = soln; res.lastSoln = soln2; res.numIters = iters; res.timeTaken = timer / 1000.0; res.timePre = 0.0; return res; }
/** * Compute expected reachability rewards. i.e. compute the min/max reward accumulated to reach a * state in {@code target}. * * @param stpg The STPG * @param rewards The rewards * @param target Target states * @param min1 Min or max rewards for player 1 (true=min, false=max) * @param min2 Min or max rewards for player 2 (true=min, false=max) * @param init Optionally, an initial solution vector (may be overwritten) * @param known Optionally, a set of states for which the exact answer is known Note: if 'known' * is specified (i.e. is non-null, 'init' must also be given and is used for the exact values. */ public ModelCheckerResult computeReachRewards( STPG stpg, STPGRewards rewards, BitSet target, boolean min1, boolean min2, double init[], BitSet known) throws PrismException { ModelCheckerResult res = null; BitSet inf; int i, n, numTarget, numInf; long timer, timerProb1; // Start expected reachability timer = System.currentTimeMillis(); if (verbosity >= 1) mainLog.println("\nStarting expected reachability..."); // Check for deadlocks in non-target state (because breaks e.g. prob1) stpg.checkForDeadlocks(target); // Store num states n = stpg.getNumStates(); // Optimise by enlarging target set (if more info is available) if (init != null && known != null) { BitSet targetNew = new BitSet(n); for (i = 0; i < n; i++) { targetNew.set(i, target.get(i) || (known.get(i) && init[i] == 0.0)); } target = targetNew; } // Precomputation (not optional) timerProb1 = System.currentTimeMillis(); inf = prob1(stpg, null, target, !min1, !min2); inf.flip(0, n); timerProb1 = System.currentTimeMillis() - timerProb1; // Print results of precomputation numTarget = target.cardinality(); numInf = inf.cardinality(); if (verbosity >= 1) mainLog.println( "target=" + numTarget + ", inf=" + numInf + ", rest=" + (n - (numTarget + numInf))); // Compute rewards switch (solnMethod) { case VALUE_ITERATION: res = computeReachRewardsValIter(stpg, rewards, target, inf, min1, min2, init, known); break; default: throw new PrismException("Unknown STPG solution method " + solnMethod); } // Finished expected reachability timer = System.currentTimeMillis() - timer; if (verbosity >= 1) mainLog.println("Expected reachability took " + timer / 1000.0 + " seconds."); // Update time taken res.timeTaken = timer / 1000.0; res.timePre = timerProb1 / 1000.0; return res; }
/** * Compute reachability/until probabilities. i.e. compute the min/max probability of reaching a * state in {@code target}, while remaining in those in @{code remain}. * * @param stpg The STPG * @param remain Remain in these states (optional: null means "all") * @param target Target states * @param min1 Min or max probabilities for player 1 (true=lower bound, false=upper bound) * @param min2 Min or max probabilities for player 2 (true=min, false=max) * @param init Optionally, an initial solution vector (may be overwritten) * @param known Optionally, a set of states for which the exact answer is known Note: if 'known' * is specified (i.e. is non-null, 'init' must also be given and is used for the exact values. */ public ModelCheckerResult computeReachProbs( STPG stpg, BitSet remain, BitSet target, boolean min1, boolean min2, double init[], BitSet known) throws PrismException { ModelCheckerResult res = null; BitSet no, yes; int i, n, numYes, numNo; long timer, timerProb0, timerProb1; boolean genAdv; // Check for some unsupported combinations if (solnMethod == SolnMethod.VALUE_ITERATION && valIterDir == ValIterDir.ABOVE && !(precomp && prob0)) { throw new PrismException( "Precomputation (Prob0) must be enabled for value iteration from above"); } // Are we generating an optimal adversary? genAdv = exportAdv; // Start probabilistic reachability timer = System.currentTimeMillis(); if (verbosity >= 1) mainLog.println("\nStarting probabilistic reachability..."); // Check for deadlocks in non-target state (because breaks e.g. prob1) stpg.checkForDeadlocks(target); // Store num states n = stpg.getNumStates(); // Optimise by enlarging target set (if more info is available) if (init != null && known != null) { BitSet targetNew = new BitSet(n); for (i = 0; i < n; i++) { targetNew.set(i, target.get(i) || (known.get(i) && init[i] == 1.0)); } target = targetNew; } // Precomputation timerProb0 = System.currentTimeMillis(); if (precomp && prob0) { no = prob0(stpg, remain, target, min1, min2); } else { no = new BitSet(); } timerProb0 = System.currentTimeMillis() - timerProb0; timerProb1 = System.currentTimeMillis(); if (precomp && prob1 && !genAdv) { yes = prob1(stpg, remain, target, min1, min2); } else { yes = (BitSet) target.clone(); } timerProb1 = System.currentTimeMillis() - timerProb1; // Print results of precomputation numYes = yes.cardinality(); numNo = no.cardinality(); if (verbosity >= 1) mainLog.println( "target=" + target.cardinality() + ", yes=" + numYes + ", no=" + numNo + ", maybe=" + (n - (numYes + numNo))); // Compute probabilities switch (solnMethod) { case VALUE_ITERATION: res = computeReachProbsValIter(stpg, no, yes, min1, min2, init, known); break; case GAUSS_SEIDEL: res = computeReachProbsGaussSeidel(stpg, no, yes, min1, min2, init, known); break; default: throw new PrismException("Unknown STPG solution method " + solnMethod); } // Finished probabilistic reachability timer = System.currentTimeMillis() - timer; if (verbosity >= 1) mainLog.println("Probabilistic reachability took " + timer / 1000.0 + " seconds."); // Update time taken res.timeTaken = timer / 1000.0; res.timeProb0 = timerProb0 / 1000.0; res.timePre = (timerProb0 + timerProb1) / 1000.0; return res; }