예제 #1
0
  @Override
  public void exportToPrismExplicitTra(PrismLog out) throws PrismException {
    super.exportToPrismExplicitTra(out);

    out.println(this);
    out.println("FDEvents: " + getNumFDEvents());
  }
예제 #2
0
 @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();
   }
 }
예제 #3
0
 @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");
   }
 }
예제 #4
0
  /** 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();
       }
     }
   }
 }
예제 #7
0
  /**
   * 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;
  }
예제 #8
0
  /** 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;
  }