@Override public void exportToPrismExplicitTra(PrismLog out) throws PrismException { super.exportToPrismExplicitTra(out); out.println(this); out.println("FDEvents: " + getNumFDEvents()); }
@Override public void exportToPrismExplicitTra(PrismLog out) { int i; TreeMap<Integer, Pair<Double, Object>> sorted; // Output transitions to .tra file out.print(numStates + " " + getNumTransitions() + "\n"); sorted = new TreeMap<Integer, Pair<Double, Object>>(); for (i = 0; i < numStates; i++) { // Extract transitions and sort by destination state index (to match PRISM-exported files) Iterator<Map.Entry<Integer, Pair<Double, Object>>> iter = getTransitionsAndActionsIterator(i); while (iter.hasNext()) { Map.Entry<Integer, Pair<Double, Object>> e = iter.next(); sorted.put(e.getKey(), e.getValue()); } // Print out (sorted) transitions for (Map.Entry<Integer, Pair<Double, Object>> e : sorted.entrySet()) { // Note use of PrismUtils.formatDouble to match PRISM-exported files out.print(i + " " + e.getKey() + " " + PrismUtils.formatDouble(e.getValue().first)); Object action = e.getValue().second; if (action != null && !"".equals(action)) out.print(" " + action); out.print("\n"); } sorted.clear(); } }
@Override public void exportTransitionsToDotFile(int i, PrismLog out) { Iterator<Map.Entry<Integer, Double>> iter = getTransitionsIterator(i); while (iter.hasNext()) { Map.Entry<Integer, Double> e = iter.next(); out.print(i + " -> " + e.getKey() + " [ label=\""); out.print(e.getValue() + "\" ];\n"); } }
/** Model check a P operator. */ private Result checkExpressionProb(ExpressionProb expr) throws PrismException { boolean min; ExpressionTemporal exprTemp; Expression exprTarget; BitSet targetLocs; int timeBound; boolean timeBoundStrict; double prob; // Check whether Pmin=? or Pmax=? (only two cases allowed) if (expr.getProb() != null) { throw new PrismException( "PTA model checking currently only supports Pmin=? and Pmax=? properties (try the digital clocks engine instead)"); } min = expr.getRelOp().equals("min="); // Check this is a F path property (only case allowed at the moment) if (!(expr.getExpression() instanceof ExpressionTemporal)) throw new PrismException( "PTA model checking currently only supports the F path operator (try the digital clocks engine instead)"); exprTemp = (ExpressionTemporal) expr.getExpression(); if (exprTemp.getOperator() != ExpressionTemporal.P_F || !exprTemp.isSimplePathFormula()) throw new PrismException( "PTA model checking currently only supports the F path operator (try the digital clocks engine instead)"); // Determine locations satisfying target exprTarget = exprTemp.getOperand2(); targetLocs = checkLocationExpression(exprTarget); mainLog.println( "Target (" + exprTarget + ") satisfied by " + targetLocs.cardinality() + " locations."); // mainLog.println(targetLocs); // If there is a time bound, add a clock and encode this into target if (exprTemp.hasBounds()) { mainLog.println("Modifying PTA to encode time bound from property..."); // Get time bound info (is always of form <=T or <T) timeBound = exprTemp.getUpperBound().evaluateInt(constantValues); timeBoundStrict = exprTemp.upperBoundIsStrict(); // Modify PTA to include time bound; get new target targetLocs = buildTimeBoundIntoPta(pta, targetLocs, timeBound, timeBoundStrict); mainLog.println("New PTA: " + pta.infoString()); } // Compute probability of reaching the set of target locations prob = computeProbabilisticReachability(targetLocs, min); // Return result return new Result(new Double(prob)); }
@Override protected void exportTransitionsToDotFile(int i, PrismLog out) { int j, k; String nij, nijk; j = -1; for (DistributionSet distrs : trans.get(i)) { j++; nij = "n" + i + "_" + j; out.print(i + " -> " + nij + " [ arrowhead=none,label=\"" + j + "\" ];\n"); out.print(nij + " [ shape=circle,width=0.1,height=0.1,label=\"\" ];\n"); k = -1; for (Distribution distr : distrs) { k++; nijk = "n" + i + "_" + j + "_" + k; out.print(nij + " -> " + nijk + " [ arrowhead=none,label=\"" + k + "\" ];\n"); out.print(nijk + " [ shape=point,label=\"\" ];\n"); for (Map.Entry<Integer, Double> e : distr) { out.print(nijk + " -> " + e.getKey() + " [ label=\"" + e.getValue() + "\" ];\n"); } } } }
@Override public void exportToPrismExplicitTra(PrismLog out) { int i, j, k; TreeMap<Integer, Double> sorted; // Output transitions to .tra file out.print(numStates + " " + numDistrSets + " " + numDistrs + " " + numTransitions + "\n"); sorted = new TreeMap<Integer, Double>(); for (i = 0; i < numStates; i++) { j = -1; for (DistributionSet distrs : trans.get(i)) { j++; k = -1; for (Distribution distr : distrs) { k++; // Extract transitions and sort by destination state index (to match PRISM-exported files) for (Map.Entry<Integer, Double> e : distr) { sorted.put(e.getKey(), e.getValue()); } // Print out (sorted) transitions for (Map.Entry<Integer, Double> e : distr) { // Note use of PrismUtils.formatDouble to match PRISM-exported files out.print( i + " " + j + " " + k + " " + e.getKey() + " " + PrismUtils.formatDouble(e.getValue()) + "\n"); } sorted.clear(); } } } }
/** * 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; }
/** Model check a property. */ public Result check(Expression expr) throws PrismException { Modules2PTA m2pta; Result res; String resultString; long timer; // Starting model checking timer = System.currentTimeMillis(); // Check for system...endsystem - not supported yet if (modulesFile.getSystemDefn() != null) { throw new PrismException( "The system...endsystem construct is not supported yet (try the digital clocks engine instead)"); } // Translate ModulesFile object into a PTA object mainLog.println("\nBuilding PTA..."); m2pta = new Modules2PTA(prism, modulesFile); pta = m2pta.translate(); mainLog.println("\nPTA: " + pta.infoString()); // Check for references to clocks - not allowed (yet) // (do this before modifications below for better error reporting) expr.accept( new ASTTraverseModify() { public Object visit(ExpressionVar e) throws PrismLangException { if (e.getType() instanceof TypeClock) { throw new PrismLangException( "Properties cannot contain references to clocks (try the digital clocks engine instead)", e); } else { return e; } } }); // Take a copy of property, since will modify expr = expr.deepCopy(); // Remove property refs ands labels from property expr = (Expression) expr.expandPropRefsAndLabels(propertiesFile, labelList); // Evaluate constants in property (easier to do now) expr = (Expression) expr.replaceConstants(constantValues); // Also simplify expression to optimise model checking expr = (Expression) expr.simplify(); // Do model checking res = checkExpression(expr); // Model checking complete timer = System.currentTimeMillis() - timer; mainLog.println("\nModel checking completed in " + (timer / 1000.0) + " secs."); // Print result to log resultString = "Result"; if (!("Result".equals(expr.getResultName()))) resultString += " (" + expr.getResultName().toLowerCase() + ")"; resultString += ": " + res; mainLog.print("\n" + resultString + "\n"); // Return result return res; }