/** * Compute next=state probabilities. i.e. compute the probability of being in a state in {@code * target} in the next step. * * @param stpg The STPG * @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) */ public ModelCheckerResult computeNextProbs(STPG stpg, BitSet target, boolean min1, boolean min2) throws PrismException { ModelCheckerResult res = null; int n; double soln[], soln2[]; long timer; timer = System.currentTimeMillis(); // Store num states n = stpg.getNumStates(); // Create/initialise solution vector(s) soln = Utils.bitsetToDoubleArray(target, n); soln2 = new double[n]; // Next-step probabilities stpg.mvMultMinMax(soln, min1, min2, soln2, null, false, null); // Return results res = new ModelCheckerResult(); res.soln = soln2; res.numIters = 1; res.timeTaken = timer / 1000.0; return res; }
/** * 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 reachability probabilities using value iteration. * * @param stpg The STPG * @param no Probability 0 states * @param yes Probability 1 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 (will 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. */ protected ModelCheckerResult computeReachProbsValIter( STPG stpg, BitSet no, BitSet yes, boolean min1, boolean min2, double init[], BitSet known) throws PrismException { ModelCheckerResult res = null; BitSet unknown; int i, n, iters; double soln[], soln2[], tmpsoln[], initVal; int adv[] = null; boolean genAdv, done; long timer; // Are we generating an optimal adversary? genAdv = exportAdv; // Start value iteration timer = System.currentTimeMillis(); if (verbosity >= 1) mainLog.println( "Starting value iteration (" + (min1 ? "min" : "max") + (min2 ? "min" : "max") + ")..."); // 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 (where available) the following in order of preference: // (1) exact answer, if already known; (2) 1.0/0.0 if in yes/no; (3) passed in initial value; // (4) initVal // where initVal is 0.0 or 1.0, depending on whether we converge from below/above. initVal = (valIterDir == ValIterDir.BELOW) ? 0.0 : 1.0; if (init != null) { if (known != null) { for (i = 0; i < n; i++) soln[i] = soln2[i] = known.get(i) ? init[i] : yes.get(i) ? 1.0 : no.get(i) ? 0.0 : init[i]; } else { for (i = 0; i < n; i++) soln[i] = soln2[i] = yes.get(i) ? 1.0 : no.get(i) ? 0.0 : init[i]; } } else { for (i = 0; i < n; i++) soln[i] = soln2[i] = yes.get(i) ? 1.0 : no.get(i) ? 0.0 : initVal; } // Determine set of states actually need to compute values for unknown = new BitSet(); unknown.set(0, n); unknown.andNot(yes); unknown.andNot(no); if (known != null) unknown.andNot(known); // Create/initialise adversary storage if (genAdv) { adv = new int[n]; for (i = 0; i < n; i++) { adv[i] = -1; } } // Start iterations iters = 0; done = false; while (!done && iters < maxIters) { iters++; // Matrix-vector multiply and min/max ops stpg.mvMultMinMax(soln, min1, min2, soln2, unknown, false, genAdv ? adv : null); // Check termination done = PrismUtils.doublesAreClose(soln, soln2, termCritParam, termCrit == TermCrit.ABSOLUTE); // Swap vectors for next iter tmpsoln = soln; soln = soln2; soln2 = tmpsoln; } // Finished value iteration timer = System.currentTimeMillis() - timer; if (verbosity >= 1) { mainLog.print("Value iteration (" + (min1 ? "min" : "max") + (min2 ? "min" : "max") + ")"); mainLog.println(" took " + iters + " iterations and " + timer / 1000.0 + " seconds."); } // Non-convergence is an error (usually) if (!done && errorOnNonConverge) { String msg = "Iterative method did not converge within " + iters + " iterations."; msg += "\nConsider using a different numerical method or increasing the maximum number of iterations"; throw new PrismException(msg); } // Print adversary if (genAdv) { PrismLog out = new PrismFileLog(exportAdvFilename); for (i = 0; i < n; i++) { out.println(i + " " + (adv[i] != -1 ? stpg.getAction(i, adv[i]) : "-")); } out.println(); } // Return results res = new ModelCheckerResult(); res.soln = soln; res.numIters = iters; res.timeTaken = timer / 1000.0; return res; }