diff --git a/prism/src/prism/NondetModelChecker.java b/prism/src/prism/NondetModelChecker.java index ee84021f..27575f55 100644 --- a/prism/src/prism/NondetModelChecker.java +++ b/prism/src/prism/NondetModelChecker.java @@ -131,12 +131,11 @@ public class NondetModelChecker extends StateModelChecker double p = 0; // probability bound (actual value) String relOp; // relational operator boolean min; // are we finding min (true) or max (false) probs - PathExpression pe; // path expression JDDNode sol; StateProbs probs = null; - // get info from prob operator + // Get info from prob operator relOp = expr.getRelOp(); pb = expr.getProb(); if (pb != null) { @@ -145,7 +144,7 @@ public class NondetModelChecker extends StateModelChecker throw new PrismException("Invalid probability bound " + p + " in P operator"); } - // check for trivial (i.e. stupid) cases + // Check for trivial (i.e. stupid) cases if (pb != null) { if ((p == 0 && relOp.equals(">=")) || (p == 1 && relOp.equals("<="))) { mainLog.print("\nWarning: checking for probability " + relOp + " " + p @@ -159,7 +158,7 @@ public class NondetModelChecker extends StateModelChecker } } - // determine whether min or max probabilities needed + // Determine whether min or max probabilities needed if (relOp.equals(">") || relOp.equals(">=") || relOp.equals("min=")) { // min min = true; @@ -170,42 +169,11 @@ public class NondetModelChecker extends StateModelChecker throw new PrismException("Can't use \"P=?\" for MDPs; use \"Pmin=?\" or \"Pmax=?\""); } - // compute probabilities - pe = expr.getPathExpression(); - if (pe instanceof PathExpressionTemporal) { - if (((PathExpressionTemporal) pe).hasBounds()) { - switch (((PathExpressionTemporal) pe).getOperator()) { - case PathExpressionTemporal.P_U: - probs = checkProbBoundedUntil((PathExpressionTemporal) pe, min); - break; - case PathExpressionTemporal.P_F: - probs = checkProbBoundedFuture((PathExpressionTemporal) pe, min); - break; - case PathExpressionTemporal.P_G: - probs = checkProbBoundedGlobal((PathExpressionTemporal) pe, min); - break; - } - } else { - switch (((PathExpressionTemporal) pe).getOperator()) { - case PathExpressionTemporal.P_X: - probs = checkProbNext((PathExpressionTemporal) pe, min); - break; - case PathExpressionTemporal.P_U: - probs = checkProbUntil((PathExpressionTemporal) pe, pb, p, min); - break; - case PathExpressionTemporal.P_F: - probs = checkProbFuture((PathExpressionTemporal) pe, pb, p, min); - break; - case PathExpressionTemporal.P_G: - probs = checkProbGlobal((PathExpressionTemporal) pe, pb, p, min); - break; - } - } - } - if (probs == null) - throw new PrismException("Unrecognised path operator in P operator"); + // Compute probabilities + boolean qual = pb != null && ((p == 0) || (p == 1)) && precomp; + probs = checkProbPathExpression(expr.getPathExpression(), qual, min); - // print out probabilities + // Print out probabilities if (verbose) { mainLog.print("\n" + (min ? "Minimum" : "Maximum") + " probabilities (non-zero only) for all states:\n"); probs.print(mainLog); @@ -332,6 +300,50 @@ public class NondetModelChecker extends StateModelChecker } } + // Contents of a P operator + + protected StateProbs checkProbPathExpression(PathExpression pe, boolean qual, boolean min) + throws PrismException + { + StateProbs probs = null; + + // Logial operators + if (pe instanceof PathExpressionLogical) { + PathExpressionLogical pel = (PathExpressionLogical) pe; + // Negation + if (pel.getOperator() == PathExpressionLogical.NOT) { + // Flip min/max, then subtract from 1 + probs = checkProbPathExpression(pel.getOperand2(), qual, !min); + probs.subtractFromOne(); + } + } + // Temporal operators + else if (pe instanceof PathExpressionTemporal) { + PathExpressionTemporal pet = (PathExpressionTemporal) pe; + // Next + if (pet.getOperator() == PathExpressionTemporal.P_X) { + probs = checkProbNext(pet, min); + } + // Until + else if (pet.getOperator() == PathExpressionTemporal.P_U) { + if (pet.hasBounds()) { + probs = checkProbBoundedUntil(pet, min); + } else { + probs = checkProbUntil(pet, qual, min); + } + } + // Anything else - convert to until and recurse + else { + probs = checkProbPathExpression(pet.convertToUntilForm(), qual, min); + } + } + + if (probs == null) + throw new PrismException("Unrecognised path operator in P operator"); + + return probs; + } + // next protected StateProbs checkProbNext(PathExpressionTemporal pe, boolean min) throws PrismException @@ -423,8 +435,7 @@ public class NondetModelChecker extends StateModelChecker // until (unbounded) - protected StateProbs checkProbUntil(PathExpressionTemporal pe, Expression pb, double p, boolean min) - throws PrismException + protected StateProbs checkProbUntil(PathExpressionTemporal pe, boolean qual, boolean min) throws PrismException { Expression expr1, expr2; JDDNode b1, b2, splus, newb1, newb2; @@ -486,11 +497,11 @@ public class NondetModelChecker extends StateModelChecker // allDDRowVars.n()) + " states\n"); } - // if p is 0 or 1 and precomputation algorithms are enabled, compute - // probabilities qualitatively - if (pb != null && ((p == 0) || (p == 1)) && precomp) { - mainLog.print("\nWarning: probability bound in formula is " + p - + " so exact probabilities may not be computed\n"); + // if requested (i.e. when prob bound is 0 or 1 and precomputation algorithms are enabled), + // compute probabilities qualitatively + if (qual) { + mainLog.print("\nWarning: probability bound in formula is" + + " 0/1 so exact probabilities may not be computed\n"); // for fairness, we compute max here probs = computeUntilProbsQual(trans01, b1, b2, min && !fairness); } @@ -520,63 +531,6 @@ public class NondetModelChecker extends StateModelChecker return probs; } - // bounded future (eventually) - // F<=k phi == true U<=k phi - - protected StateProbs checkProbBoundedFuture(PathExpressionTemporal pe, boolean min) throws PrismException - { - PathExpressionTemporal pe2; - pe2 = new PathExpressionTemporal(PathExpressionTemporal.P_U, new PathExpressionExpr(Expression.True()), pe - .getOperand2(), pe.getLowerBound(), pe.getUpperBound()); - return checkProbBoundedUntil(pe2, min); - } - - // future (eventually) - // F phi == true U phi - - protected StateProbs checkProbFuture(PathExpressionTemporal pe, Expression pb, double p, boolean min) - throws PrismException - { - PathExpressionTemporal pe2; - pe2 = new PathExpressionTemporal(PathExpressionTemporal.P_U, new PathExpressionExpr(Expression.True()), pe - .getOperand2()); - return checkProbUntil(pe2, pb, p, min); - } - - // bounded global (always) - // F<=k phi == true U<=k phi - // P(G<=k phi) == 1-P(true U<=k !phi) - // Pmin(G<=k phi) == 1-Pmax(true U<=k !phi) - - protected StateProbs checkProbBoundedGlobal(PathExpressionTemporal pe, boolean min) throws PrismException - { - PathExpressionTemporal pe2; - StateProbs probs; - pe2 = new PathExpressionTemporal(PathExpressionTemporal.P_U, new PathExpressionExpr(Expression.True()), - new PathExpressionExpr(Expression.Not(((PathExpressionExpr) pe.getOperand2()).getExpression())), pe - .getLowerBound(), pe.getUpperBound()); - probs = checkProbBoundedUntil(pe2, !min); - probs.subtractFromOne(); - return probs; - } - - // global (always) - // G phi == !(true U !phi) - // P(G phi) == 1-P(true U !phi) - // Pmin(G phi) == 1-Pmax(true U !phi) - - protected StateProbs checkProbGlobal(PathExpressionTemporal pe, Expression pb, double p, boolean min) - throws PrismException - { - PathExpressionTemporal pe2; - StateProbs probs; - pe2 = new PathExpressionTemporal(PathExpressionTemporal.P_U, new PathExpressionExpr(Expression.True()), - new PathExpressionExpr(Expression.Not(((PathExpressionExpr) pe.getOperand2()).getExpression()))); - probs = checkProbUntil(pe2, pb, p, !min); - probs.subtractFromOne(); - return probs; - } - // inst reward protected StateProbs checkRewardInst(PathExpressionTemporal pe, JDDNode stateRewards, JDDNode transRewards, @@ -665,8 +619,8 @@ public class NondetModelChecker extends StateModelChecker // compute probabilities for bounded until - protected StateProbs computeBoundedUntilProbs(JDDNode tr, JDDNode tr01, JDDNode b1, JDDNode b2, int time, boolean min) - throws PrismException + protected StateProbs computeBoundedUntilProbs(JDDNode tr, JDDNode tr01, JDDNode b1, JDDNode b2, int time, + boolean min) throws PrismException { JDDNode yes, no, maybe; JDDNode probsMTBDD; diff --git a/prism/src/prism/ProbModelChecker.java b/prism/src/prism/ProbModelChecker.java index 2ebafd71..9a51752a 100644 --- a/prism/src/prism/ProbModelChecker.java +++ b/prism/src/prism/ProbModelChecker.java @@ -140,12 +140,11 @@ public class ProbModelChecker extends StateModelChecker Expression pb; // probability bound (expression) double p = 0; // probability bound (actual value) String relOp; // relational operator - PathExpression pe; // path expression JDDNode sol; StateProbs probs = null; - // get info from prob operator + // Get info from prob operator relOp = expr.getRelOp(); pb = expr.getProb(); if (pb != null) { @@ -154,7 +153,7 @@ public class ProbModelChecker extends StateModelChecker throw new PrismException("Invalid probability bound " + p + " in P operator"); } - // check for trivial (i.e. stupid) cases + // Check for trivial (i.e. stupid) cases if (pb != null) { if ((p == 0 && relOp.equals(">=")) || (p == 1 && relOp.equals("<="))) { mainLog.print("\nWarning: checking for probability " + relOp + " " + p @@ -168,47 +167,16 @@ public class ProbModelChecker extends StateModelChecker } } - // print a warning if Pmin/Pmax used + // Print a warning if Pmin/Pmax used if (relOp.equals("min=") || relOp.equals("max=")) { mainLog.print("\nWarning: \"Pmin=?\" and \"Pmax=?\" operators are identical to \"P=?\" for DTMCs\n"); } - // compute probabilities - pe = expr.getPathExpression(); - if (pe instanceof PathExpressionTemporal) { - if (((PathExpressionTemporal) pe).hasBounds()) { - switch (((PathExpressionTemporal) pe).getOperator()) { - case PathExpressionTemporal.P_U: - probs = checkProbBoundedUntil((PathExpressionTemporal) pe); - break; - case PathExpressionTemporal.P_F: - probs = checkProbBoundedFuture((PathExpressionTemporal) pe); - break; - case PathExpressionTemporal.P_G: - probs = checkProbBoundedGlobal((PathExpressionTemporal) pe); - break; - } - } else { - switch (((PathExpressionTemporal) pe).getOperator()) { - case PathExpressionTemporal.P_X: - probs = checkProbNext((PathExpressionTemporal) pe); - break; - case PathExpressionTemporal.P_U: - probs = checkProbUntil((PathExpressionTemporal) pe, pb, p); - break; - case PathExpressionTemporal.P_F: - probs = checkProbFuture((PathExpressionTemporal) pe, pb, p); - break; - case PathExpressionTemporal.P_G: - probs = checkProbGlobal((PathExpressionTemporal) pe, pb, p); - break; - } - } - } - if (probs == null) - throw new PrismException("Unrecognised path operator in P operator"); + // Compute probabilities + boolean qual = pb != null && ((p == 0) || (p == 1)) && precomp; + probs = checkProbPathExpression(expr.getPathExpression(), qual); - // print out probabilities + // Print out probabilities if (prism.getVerbose()) { mainLog.print("\nProbabilities (non-zero only) for all states:\n"); probs.print(mainLog); @@ -534,6 +502,49 @@ public class ProbModelChecker extends StateModelChecker } } + // Contents of a P operator + + protected StateProbs checkProbPathExpression(PathExpression pe, boolean qual) throws PrismException + { + StateProbs probs = null; + + // Logial operators + if (pe instanceof PathExpressionLogical) { + PathExpressionLogical pel = (PathExpressionLogical) pe; + // Negation + if (pel.getOperator() == PathExpressionLogical.NOT) { + // Compute, then subtract from 1 + probs = checkProbPathExpression(pel.getOperand2(), qual); + probs.subtractFromOne(); + } + } + // Temporal operators + else if (pe instanceof PathExpressionTemporal) { + PathExpressionTemporal pet = (PathExpressionTemporal) pe; + // Next + if (pet.getOperator() == PathExpressionTemporal.P_X) { + probs = checkProbNext(pet); + } + // Until + else if (pet.getOperator() == PathExpressionTemporal.P_U) { + if (pet.hasBounds()) { + probs = checkProbBoundedUntil(pet); + } else { + probs = checkProbUntil(pet, qual); + } + } + // Anything else - convert to until and recurse + else { + probs = checkProbPathExpression(pet.convertToUntilForm(), qual); + } + } + + if (probs == null) + throw new PrismException("Unrecognised path operator in P operator"); + + return probs; + } + // next protected StateProbs checkProbNext(PathExpressionTemporal pe) throws PrismException @@ -625,7 +636,7 @@ public class ProbModelChecker extends StateModelChecker // until (unbounded) - protected StateProbs checkProbUntil(PathExpressionTemporal pe, Expression pb, double p) throws PrismException + protected StateProbs checkProbUntil(PathExpressionTemporal pe, boolean qual) throws PrismException { Expression expr1, expr2; JDDNode b1, b2; @@ -654,12 +665,12 @@ public class ProbModelChecker extends StateModelChecker // compute probabilities - // if prob bound is 0 or 1 and precomputation algorithms are enabled, + // if requested (i.e. when prob bound is 0 or 1 and precomputation algorithms are enabled), // compute probabilities qualitatively - if (pb != null && ((p == 0) || (p == 1)) && precomp) { - mainLog.print("\nWarning: Probability bound in formula is " + p - + " so exact probabilities may not be computed\n"); - probs = computeUntilProbsQual(trans01, b1, b2, p); + if (qual) { + mainLog.print("\nWarning: probability bound in formula is" + + " 0/1 so exact probabilities may not be computed\n"); + probs = computeUntilProbsQual(trans01, b1, b2); } // otherwise actually compute probabilities else { @@ -679,59 +690,6 @@ public class ProbModelChecker extends StateModelChecker return probs; } - // bounded future (eventually) - // F<=k phi == true U<=k phi - - protected StateProbs checkProbBoundedFuture(PathExpressionTemporal pe) throws PrismException - { - PathExpressionTemporal pe2; - pe2 = new PathExpressionTemporal(PathExpressionTemporal.P_U, new PathExpressionExpr(Expression.True()), pe - .getOperand2(), pe.getLowerBound(), pe.getUpperBound()); - return checkProbBoundedUntil(pe2); - } - - // future (eventually) - // F phi == true U phi - - protected StateProbs checkProbFuture(PathExpressionTemporal pe, Expression pb, double p) throws PrismException - { - PathExpressionTemporal pe2; - pe2 = new PathExpressionTemporal(PathExpressionTemporal.P_U, new PathExpressionExpr(Expression.True()), pe - .getOperand2()); - return checkProbUntil(pe2, pb, p); - } - - // bounded global (always) - // F<=k phi == true U<=k phi - // P(G<=k phi) == 1-P(true U<=k !phi) - - protected StateProbs checkProbBoundedGlobal(PathExpressionTemporal pe) throws PrismException - { - PathExpressionTemporal pe2; - StateProbs probs; - pe2 = new PathExpressionTemporal(PathExpressionTemporal.P_U, new PathExpressionExpr(Expression.True()), - new PathExpressionExpr(Expression.Not(((PathExpressionExpr) pe.getOperand2()).getExpression())), pe - .getLowerBound(), pe.getUpperBound()); - probs = checkProbBoundedUntil(pe2); - probs.subtractFromOne(); - return probs; - } - - // global (always) - // G phi == !(true U !phi) - // P(G phi) == 1-P(true U !phi) - - protected StateProbs checkProbGlobal(PathExpressionTemporal pe, Expression pb, double p) throws PrismException - { - PathExpressionTemporal pe2; - StateProbs probs; - pe2 = new PathExpressionTemporal(PathExpressionTemporal.P_U, new PathExpressionExpr(Expression.True()), - new PathExpressionExpr(Expression.Not(((PathExpressionExpr) pe.getOperand2()).getExpression()))); - probs = checkProbUntil(pe2, pb, p); - probs.subtractFromOne(); - return probs; - } - // cumulative reward protected StateProbs checkRewardCumul(PathExpressionTemporal pe, JDDNode stateRewards, JDDNode transRewards) @@ -1258,7 +1216,7 @@ public class ProbModelChecker extends StateModelChecker // compute probabilities for until (for qualitative properties) - protected StateProbs computeUntilProbsQual(JDDNode tr01, JDDNode b1, JDDNode b2, double p) + protected StateProbs computeUntilProbsQual(JDDNode tr01, JDDNode b1, JDDNode b2) { JDDNode yes, no, maybe; StateProbs probs = null; @@ -1304,20 +1262,18 @@ public class ProbModelChecker extends StateModelChecker JDD.Ref(yes); probs = new StateProbsMTBDD(yes, model); } - // p = 0 - else if (p == 0) { - // anything that's unknown but definitely > 0 - // may as well be 1 - JDD.Ref(yes); - JDD.Ref(maybe); - probs = new StateProbsMTBDD(JDD.Or(yes, maybe), model); - } - // p = 1 + // otherwise we set the probabilities for maybe states to be 0.5 + // (actual probabilities for these states are unknown but definitely >0 + // and <1) + // (this is safe because the results of this function will only be used + // to compare against 0/1 bounds) + // (this is not entirely elegant but is simpler and less error prone + // than + // trying to work out whether to use 0/1 for all case of future/global, etc.) else { - // anything that's unknown but definitely < 1 - // may as well be 0 JDD.Ref(yes); - probs = new StateProbsMTBDD(yes, model); + JDD.Ref(maybe); + probs = new StateProbsMTBDD(JDD.Apply(JDD.PLUS, yes, JDD.Apply(JDD.TIMES, maybe, JDD.Constant(0.5))), model); } // derefs diff --git a/prism/src/simulator/SimulatorEngine.java b/prism/src/simulator/SimulatorEngine.java index a709e64e..5984244e 100644 --- a/prism/src/simulator/SimulatorEngine.java +++ b/prism/src/simulator/SimulatorEngine.java @@ -36,178 +36,142 @@ import parser.visitor.ASTTraverse; import prism.*; /** - * The SimulatorEngine class uses the JNI to provide a Java interface to the PRISM - * simulator engine library, written in c++. There are two ways to use this API: + * The SimulatorEngine class uses the JNI to provide a Java interface to the PRISM simulator engine library, written in + * c++. There are two ways to use this API: * - * Each type of use only builds the relevant data structures of the simulator - * engine. - * + * Each type of use only builds the relevant data structures of the simulator engine. + * *

Model Exploration

- * - * In order to load a PRISM model into the simulator engine, a valid - * ModulesFile, that has had all of its constants defined, can - * be loaded using the startNewPath method. If the simulator engine - * is to be used to reason with path properties, a PropertiesFile object is - * passed. The initial state must also be provided. - * - * At this point, the simulator engine will automatically calculate the set of - * updates to that initial state. This update set can be queried by the methods - * such as: - * + * + * In order to load a PRISM model into the simulator engine, a valid ModulesFile, that has had all of its + * constants defined, can be loaded using the startNewPath method. If the simulator engine is to be used to + * reason with path properties, a PropertiesFile object is passed. The initial state must also be provided. + * + * At this point, the simulator engine will automatically calculate the set of updates to that initial state. This + * update set can be queried by the methods such as: + * * - * - * It should be noted that all references to variables, action labels - * etc... are of the simulators stored index. There are a number of methods - * provided to convert the string representations of these items to their - * appropriate indices: - * + * + * It should be noted that all references to variables, action labels etc... are of the simulators stored index. There + * are a number of methods provided to convert the string representations of these items to their appropriate indices: + * * - * + * * At this point, there are three options: - * + * * - * - * The simulator engine maintains an execution path of all of the previous - * states of the system. It is possible to access the information using - * the following methods: - * + * + * The simulator engine maintains an execution path of all of the previous states of the system. It is possible to + * access the information using the following methods: + * * - * - * The simulator engine automatically detects loops in execution paths, and - * there are a couple of methods used to query this: boolean isPathLooping() - * and int loopStart() - * - * Functionality to backtrack to previous states of the path is provided by the - * backtrack(int toPathIndex) method and the ability to remove states - * from the path before a given index is provids by the + * + * The simulator engine automatically detects loops in execution paths, and there are a couple of methods used to query + * this: boolean isPathLooping() and int loopStart() + * + * Functionality to backtrack to previous states of the path is provided by the backtrack(int toPathIndex) + * method and the ability to remove states from the path before a given index is provids by the * removePrecedingStates method. - * + * * There are two ways in which the path can be analysed: - * + * * - * - * The deallocateEngine() method should be used after using the engine, - * or before a new model, or path is started. This simply cleans up the memory - * in the c++ engine. - * + * + * The deallocateEngine() method should be used after using the engine, or before a new model, or path is + * started. This simply cleans up the memory in the c++ engine. + * *

Monte-Carlo Sampling

- * - * Three methods are provided to make the interface cleaner, if it is only used - * for approximate model checking. Each method deals with all model loading, - * algorithm execution and tidying up afterwards. The three methods are: - * + * + * Three methods are provided to make the interface cleaner, if it is only used for approximate model checking. Each + * method deals with all model loading, algorithm execution and tidying up afterwards. The three methods are: + * * - * + * *

Path Generation

- * - * The following utility method is used for generating (and exporting) - * a single path satsifying certain criteria: - * + * + * The following utility method is used for generating (and exporting) a single path satsifying certain criteria: + * * - * + * * @author Andrew Hinton */ public class SimulatorEngine { - //------------------------------------------------------------------------------ - // CONSTANTS - //------------------------------------------------------------------------------ - - //Errors + // ------------------------------------------------------------------------------ + // CONSTANTS + // ------------------------------------------------------------------------------ + + // Errors /** - * Used by the simulator engine to report that something has caused an exception. - * The actual content of the error can be queried using the - * getLastErrorMessage() method. + * Used by the simulator engine to report that something has caused an exception. The actual content of the error + * can be queried using the getLastErrorMessage() method. */ public static final int ERROR = -1; /** - * Used by the simulator engine to report that an index parameter was out - * of range. + * Used by the simulator engine to report that an index parameter was out of range. */ public static final int OUTOFRANGE = -1; /** * Used by the simulator engine to indicate that a returned pointer is NULL. */ public static final int NULL = 0; - - //Model type + + // Model type /** * A constant for the model type */ @@ -215,33 +179,33 @@ public class SimulatorEngine /** * A constant for the model type */ - public static final int PROBABILISTIC = ModulesFile.PROBABILISTIC; //dtmc + public static final int PROBABILISTIC = ModulesFile.PROBABILISTIC; // dtmc /** * A constant for the model type */ - public static final int NONDETERMINISTIC = ModulesFile.NONDETERMINISTIC; //mdp + public static final int NONDETERMINISTIC = ModulesFile.NONDETERMINISTIC; // mdp /** * A constant for the model type */ - public static final int STOCHASTIC = ModulesFile.STOCHASTIC; //ctmc - - //Undefined values + public static final int STOCHASTIC = ModulesFile.STOCHASTIC; // ctmc + + // Undefined values /** * Used throughout the simulator for undefined integers */ - public static final int UNDEFINED_INT = Integer.MIN_VALUE+1; + public static final int UNDEFINED_INT = Integer.MIN_VALUE + 1; /** * Used throughout the simulator for undefined doubles */ public static final double UNDEFINED_DOUBLE = -10E23f; - - //Infinity + + // Infinity /** * Used by the simulator engine, usually for infinite rewards. etc... */ public static final double INFINITY = 10E23f; - - //Expression types + + // Expression types /** * Used to refer to the type of an expression */ @@ -254,20 +218,20 @@ public class SimulatorEngine * Used to refer to the type of an expression */ public static final int BOOLEAN = Expression.BOOLEAN; - + // Types of random path to generate public static final int SIM_PATH_NUM_STEPS = 0; public static final int SIM_PATH_TIME = 1; public static final int SIM_PATH_DEADLOCK = 2; - - //------------------------------------------------------------------------------ - // CLASS MEMBERS - //------------------------------------------------------------------------------ - - //The current parsed model + + // ------------------------------------------------------------------------------ + // CLASS MEMBERS + // ------------------------------------------------------------------------------ + + // The current parsed model private ModulesFile modulesFile; - - //Current model + + // Current model private Values constants; private Map varIndices; private String[] varNames; @@ -276,40 +240,34 @@ public class SimulatorEngine private String[] actionNames; private Map moduleIndices; private String[] moduleNames; - - //PRISM parsed properties files + + // PRISM parsed properties files private PropertiesFile propertiesFile; - - //Current Properties + + // Current Properties private Values propertyConstants; private ArrayList loadedProperties; - - - //------------------------------------------------------------------------------ - // STATIC INITIALISER - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // STATIC INITIALISER + // ------------------------------------------------------------------------------ + /** - * Load jni stuff from shared library + * Load jni stuff from shared library */ - static - { - try - { + static { + try { System.loadLibrary("simengine"); - } - catch (UnsatisfiedLinkError e) - { + } catch (UnsatisfiedLinkError e) { System.out.println(e); System.exit(1); } } - - - //------------------------------------------------------------------------------ - // CONSTRUCTOR - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // CONSTRUCTOR + // ------------------------------------------------------------------------------ + /** * Constructor for the simulator Engine. */ @@ -328,39 +286,42 @@ public class SimulatorEngine propertyConstants = null; loadedProperties = null; } - - //------------------------------------------------------------------------------ - // PRISM LOG - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // PRISM LOG + // ------------------------------------------------------------------------------ + // place to store main log for java code private static PrismLog mainLog; + // jni method to set main log for native code private static native void Set_Main_Log(PrismLog log); + // method to set main log both in java and c++ public static void setMainLog(PrismLog log) { mainLog = log; Set_Main_Log(log); } - - - //------------------------------------------------------------------------------ - // MODEL INITIALISATION - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // MODEL INITIALISATION + // ------------------------------------------------------------------------------ + /** * Deallocates all simulator data structures from memory. - * @throws SimulatorException If there was a problem with the deallocation, an exception is thrown. + * + * @throws SimulatorException + * If there was a problem with the deallocation, an exception is thrown. */ public void deallocateEngine() throws SimulatorException { - //Call tidy up code in the c++ engine - int num = tidyUpEverything(); - - if(num == ERROR) + // Call tidy up code in the c++ engine + int num = tidyUpEverything(); + + if (num == ERROR) throw new SimulatorException(getLastErrorMessage()); - + varIndices = null; varNames = null; varTypes = null; @@ -373,1468 +334,1480 @@ public class SimulatorEngine constants = null; propertyConstants = null; loadedProperties = null; - - + } - + /** - * Cleans up all c++ structures including the loaded model, - * loaded properties, the current path and any sampling - * information. Returns ERROR if there was a problem. + * Cleans up all c++ structures including the loaded model, loaded properties, the current path and any sampling + * information. Returns ERROR if there was a problem. */ private static native int tidyUpEverything(); - - - //------------------------------------------------------------------------------ - // MODEL LOADING METHODS - //------------------------------------------------------------------------------ - - /** - * Notifies the simulator engine of a PRISM parsed ModulesFile. - * Loads in the model stored in modulesFile with the constants stored in constants. - * It also initialises the state space with the appropriate number of variables. - * If there are any problems with loading the model, - * is called before a SimulatorException is thrown. + + // ------------------------------------------------------------------------------ + // MODEL LOADING METHODS + // ------------------------------------------------------------------------------ + + /** + * Notifies the simulator engine of a PRISM parsed ModulesFile. Loads in the model stored in modulesFile with the + * constants stored in constants. It also initialises the state space with the appropriate number of variables. If + * there are any problems with loading the model, is called before a SimulatorException is thrown. */ private void loadModulesFile(ModulesFile modulesFile, Values constants) throws SimulatorException { this.modulesFile = modulesFile; this.constants = constants; - + // check for presence of system...endsystem if (modulesFile.getSystemDefn() != null) { - throw new SimulatorException("Sorry - the simulator does not currently handle the system...endsystem construct"); + throw new SimulatorException( + "Sorry - the simulator does not currently handle the system...endsystem construct"); } - - try - { - int result; //used to look for errors - - //ALLOCATE STATE SPACE AND SETUP VARIABLES + + try { + int result; // used to look for errors + + // ALLOCATE STATE SPACE AND SETUP VARIABLES varIndices = new HashMap(); - //count variables to set up array + // count variables to set up array int numVars = modulesFile.getNumGlobals(); - for(int i = 0; i < modulesFile.getNumModules(); i++) + for (int i = 0; i < modulesFile.getNumModules(); i++) numVars += modulesFile.getModule(i).getNumDeclarations(); - + varNames = new String[numVars]; varTypes = new int[numVars]; - - //Get globals from ModulesFile + + // Get globals from ModulesFile numVars = modulesFile.getNumGlobals(); - for(int i = 0; i < numVars; i++) - { - varIndices.put(modulesFile.getGlobal(i).getName(), new Integer(i)); //variable table to help later + for (int i = 0; i < numVars; i++) { + varIndices.put(modulesFile.getGlobal(i).getName(), new Integer(i)); // variable table to help later varNames[i] = modulesFile.getGlobal(i).getName(); varTypes[i] = modulesFile.getGlobal(i).getType(); } - - //Get variables from each Module + + // Get variables from each Module int start = numVars; - for(int i = 0; i < modulesFile.getNumModules(); i++) - { + for (int i = 0; i < modulesFile.getNumModules(); i++) { Module m = modulesFile.getModule(i); int numDec = m.getNumDeclarations(); - for(int j = 0; j < numDec; j++) - { + for (int j = 0; j < numDec; j++) { Declaration d = m.getDeclaration(j); - varIndices.put(m.getDeclaration(j).getName(), new Integer(start+j)); - varNames[start+j] = m.getDeclaration(j).getName(); - varTypes[start+j] = m.getDeclaration(j).getType(); + varIndices.put(m.getDeclaration(j).getName(), new Integer(start + j)); + varNames[start + j] = m.getDeclaration(j).getName(); + varTypes[start + j] = m.getDeclaration(j).getType(); } - - numVars+= numDec; + + numVars += numDec; start = numVars; } - - - result = allocateStateSpace(numVars); //notify the c++ engine to construct variable table - if(result == ERROR) - { + + result = allocateStateSpace(numVars); // notify the c++ engine to construct variable table + if (result == ERROR) { throw new SimulatorException(getLastErrorMessage()); } - - - //Initialise model - + + // Initialise model + actionIndices = new HashMap(); moduleIndices = new HashMap(); - - //SETUP MODEL + + // SETUP MODEL int type = modulesFile.getType(); - - //Count commands + + // Count commands int countCommands = 0; - for(int i = 0; i < modulesFile.getNumModules(); i++) + for (int i = 0; i < modulesFile.getNumModules(); i++) countCommands += modulesFile.getModule(i).getNumCommands(); - - //Setup actions (synchs and modules) - //This is where we may need to look at systemdefinition stuff + + // Setup actions (synchs and modules) + // This is where we may need to look at systemdefinition stuff int acind = 0; - for(int i = 0; i < modulesFile.getNumModules(); i++) - { + for (int i = 0; i < modulesFile.getNumModules(); i++) { Vector v = modulesFile.getSynchs(); - for(int j = 0; j < v.size(); j++) - { - String s = (String)v.get(j); - if(!actionIndices.containsKey(s)) - { + for (int j = 0; j < v.size(); j++) { + String s = (String) v.get(j); + if (!actionIndices.containsKey(s)) { actionIndices.put(s, new Integer(acind++)); } } - + } moduleNames = new String[modulesFile.getNumModules()]; - for(int j = 0; j < modulesFile.getNumModules(); j++) - { + for (int j = 0; j < modulesFile.getNumModules(); j++) { String s = modulesFile.getModule(j).getName(); moduleIndices.put(s, new Integer(j)); moduleNames[j] = s; } - + actionNames = new String[acind]; acind = 0; - for(int i = 0; i < modulesFile.getNumModules(); i++) - { + for (int i = 0; i < modulesFile.getNumModules(); i++) { Vector v = modulesFile.getSynchs(); - for(int j = 0; j < v.size(); j++) - { - String s = (String)v.get(j); + for (int j = 0; j < v.size(); j++) { + String s = (String) v.get(j); boolean store = true; - - for(int k = 0; k < acind; k++) - { - if(actionNames[k].equals(s)) + + for (int k = 0; k < acind; k++) { + if (actionNames[k].equals(s)) store = false; } - - if(store) actionNames[acind++] = s; - + + if (store) + actionNames[acind++] = s; + } - + } - - //Count Rewards - + + // Count Rewards + int numRewardStructs = 0; int numStateRewards[], numTransitionRewards[]; - + numRewardStructs = modulesFile.getNumRewardStructs(); numStateRewards = new int[numRewardStructs]; numTransitionRewards = new int[numRewardStructs]; - + for (int i = 0; i < numRewardStructs; i++) { - + numStateRewards[i] = 0; numTransitionRewards[i] = 0; - + RewardStruct rewards = modulesFile.getRewardStruct(i); RewardStructItem reward; - - //count the number of each type of reward - for(int j = 0; j < rewards.getNumItems(); j++) - { + + // count the number of each type of reward + for (int j = 0; j < rewards.getNumItems(); j++) { reward = rewards.getRewardStructItem(j); - if(reward.isTransitionReward()) numTransitionRewards[i]++; - else numStateRewards[i]++; + if (reward.isTransitionReward()) + numTransitionRewards[i]++; + else + numStateRewards[i]++; } } - - //Perform the allocation - - result = allocateModel(type, countCommands, numRewardStructs, numStateRewards, numTransitionRewards, modulesFile.getNumModules(), acind); - if(result == ERROR) - { + + // Perform the allocation + + result = allocateModel(type, countCommands, numRewardStructs, numStateRewards, numTransitionRewards, + modulesFile.getNumModules(), acind); + if (result == ERROR) { throw new SimulatorException(getLastErrorMessage()); } - - - - //Build transition table - for(int i = 0; i < modulesFile.getNumModules(); i++) - { + + // Build transition table + for (int i = 0; i < modulesFile.getNumModules(); i++) { Module m = modulesFile.getModule(i); - for(int j = 0; j < m.getNumCommands(); j++) - { + for (int j = 0; j < m.getNumCommands(); j++) { Command c = m.getCommand(j); - - //Find the action index for this transition - //This is where we may need to look at systemdefinition stuff + + // Find the action index for this transition + // This is where we may need to look at systemdefinition stuff String synch = c.getSynch(); - int actionIndex = - (synch.equals("")) ? -1 //if no synch - : ((Integer)(actionIndices.get(synch))).intValue(); //otherwise, use the synch - - int moduleIndex = - ((Integer)(moduleIndices.get(m.getName()))).intValue(); - - //Create the guard expression + int actionIndex = (synch.equals("")) ? -1 // if no synch + : ((Integer) (actionIndices.get(synch))).intValue(); // otherwise, use the synch + + int moduleIndex = ((Integer) (moduleIndices.get(m.getName()))).intValue(); + + // Create the guard expression long guardPointer = c.getGuard().toSimulator(this); - if(guardPointer == NULL) - { - throw new SimulatorException("Problem with loading model into simulator: null guardPointer in "+m.getName()); + if (guardPointer == NULL) { + throw new SimulatorException("Problem with loading model into simulator: null guardPointer in " + + m.getName()); } - //Find out number of updates + // Find out number of updates Updates ups = c.getUpdates(); int numUpdates = ups.getNumUpdates(); - - //Construct the command + + // Construct the command long commandPointer = createCommand(guardPointer, actionIndex, moduleIndex, numUpdates); - - if(commandPointer == NULL) - { - throw new SimulatorException("Problem with loading model into simulator: null commandPointer in "+m.getName()); + + if (commandPointer == NULL) { + throw new SimulatorException( + "Problem with loading model into simulator: null commandPointer in " + m.getName()); } - //add all the updates to the command - for(int k = 0; k < numUpdates; k++) - { - //Create probability expression for this update + // add all the updates to the command + for (int k = 0; k < numUpdates; k++) { + // Create probability expression for this update Expression p = ups.getProbability(k); - if (p == null) p = Expression.Double(1.0); + if (p == null) + p = Expression.Double(1.0); long probPointer = p.toSimulator(this); - if(probPointer == NULL) - { - throw new SimulatorException("Problem with loading model into simulator: null probPointer in "+m.getName()); + if (probPointer == NULL) { + throw new SimulatorException( + "Problem with loading model into simulator: null probPointer in " + m.getName()); } - //Construct the update + // Construct the update Update u = ups.getUpdate(k); int numAssignments = u.getNumElements(); long updatePointer = addUpdate(commandPointer, probPointer, numAssignments); - if(updatePointer == NULL) - { - throw new SimulatorException("Problem with loading model into simulator: null updatePointer in "+m.getName()); + if (updatePointer == NULL) { + throw new SimulatorException( + "Problem with loading model into simulator: null updatePointer in " + m.getName()); } - //add all the assignments to the update - for(int ii = 0; ii < numAssignments; ii++) - { - //find the index of the variable for this update + // add all the assignments to the update + for (int ii = 0; ii < numAssignments; ii++) { + // find the index of the variable for this update String varName = u.getVar(ii); - int varIndex = ((Integer)varIndices.get(varName)).intValue(); - - //construct the rhs + int varIndex = ((Integer) varIndices.get(varName)).intValue(); + + // construct the rhs long rhsPointer = u.getExpression(ii).toSimulator(this); - if(rhsPointer == NULL) - { - throw new SimulatorException("Problem with loading model into simulator: null rhs in "+m.getName()); + if (rhsPointer == NULL) { + throw new SimulatorException("Problem with loading model into simulator: null rhs in " + + m.getName()); } - //construct the assignment + // construct the assignment long assign = addAssignment(updatePointer, varIndex, rhsPointer); - if(assign == NULL) - { - throw new SimulatorException("Problem with loading model into simulator: null assignment in "+m.getName()); + if (assign == NULL) { + throw new SimulatorException( + "Problem with loading model into simulator: null assignment in " + m.getName()); } } } result = setupAddTransition(commandPointer); - if(result == ERROR) - { + if (result == ERROR) { throw new SimulatorException(getLastErrorMessage()); } } } - - - //SETUP REWARDS - + + // SETUP REWARDS + for (int i = 0; i < numRewardStructs; i++) { - + RewardStruct rewards = modulesFile.getRewardStruct(i); RewardStructItem reward; - - //count the number of each type of reward - for(int j = 0; j < rewards.getNumItems(); j++) - { + + // count the number of each type of reward + for (int j = 0; j < rewards.getNumItems(); j++) { reward = rewards.getRewardStructItem(j); long rewardPointer = reward.toSimulator(this); - if(rewardPointer == NULL) - throw new SimulatorException("Problem with loading model into simulator: null reward, "+reward.toString()); - if(reward.isTransitionReward()) + if (rewardPointer == NULL) + throw new SimulatorException("Problem with loading model into simulator: null reward, " + + reward.toString()); + if (reward.isTransitionReward()) result = setupAddTransitionReward(i, rewardPointer); else result = setupAddStateReward(i, rewardPointer); - if(result == ERROR) + if (result == ERROR) throw new SimulatorException(getLastErrorMessage()); } } - } - catch(SimulatorException e) - { + } catch (SimulatorException e) { deallocateEngine(); throw e; - } - catch(PrismLangException e) - { + } catch (PrismLangException e) { deallocateEngine(); throw new SimulatorException(e.getMessage()); } } - - - - //These set methods should ONLY be used when loading the model - - - - /** - * Model loading helper method - * Sets up the c++ engine state space variable table to have the given number of - * variables. - * Returns ERROR if there is a problem. + + // These set methods should ONLY be used when loading the model + + /** + * Model loading helper method Sets up the c++ engine state space variable table to have the given number of + * variables. Returns ERROR if there is a problem. */ private static native int allocateStateSpace(int numberOfVariables); - + /** - * Allocates space for a new model in the c++ engine according to the - * given parameters. + * Allocates space for a new model in the c++ engine according to the given parameters. */ private static native int allocateModel(int type, int noCommands, int noRewardStructs, int noStateRewards[], - int noTransitionRewards[], int noModules, int noActions); - + int noTransitionRewards[], int noModules, int noActions); + /** - * Model loading helper method - * Adds the CCommand object stored at the location of commandPointer - * to the c++ engine transition table. - * Returns ERROR if there is a problem + * Model loading helper method Adds the CCommand object stored at the location of commandPointer to the c++ engine + * transition table. Returns ERROR if there is a problem */ private static native int setupAddTransition(long commandPointer); - + /** - * Model loading helper method - * Adds the CStateRewards object stored at the location of rewardPointer - * to the ith state rewards table. - * Returns ERROR if there is a problem + * Model loading helper method Adds the CStateRewards object stored at the location of rewardPointer to the ith + * state rewards table. Returns ERROR if there is a problem */ private static native int setupAddStateReward(int i, long rewardPointer); - + /** - * Model loading helper method - * Adds the CTransitionRewards object stored at the location of rewardPointer - * to the ith transition rewards table. - * Returns ERROR if there is a problem + * Model loading helper method Adds the CTransitionRewards object stored at the location of rewardPointer to the ith + * transition rewards table. Returns ERROR if there is a problem */ private static native int setupAddTransitionReward(int i, long rewardPointer); - - - //------------------------------------------------------------------------------ - // MODEL ACCESS METHODS - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // MODEL ACCESS METHODS + // ------------------------------------------------------------------------------ + /** * Provides access to the indices of variable names. - * @param name the variable string. - * @throws SimulatorException if the string was not found or is invalid. + * + * @param name + * the variable string. + * @throws SimulatorException + * if the string was not found or is invalid. * @return the index of the given variable string. */ public int getIndexOfVar(String name) throws SimulatorException { - if(varIndices.containsKey(name)) - return ((Integer)varIndices.get(name)).intValue(); - else throw new SimulatorException("Cannot get variable index, name: "+name+" does not exist"); + if (varIndices.containsKey(name)) + return ((Integer) varIndices.get(name)).intValue(); + else + throw new SimulatorException("Cannot get variable index, name: " + name + " does not exist"); } - + /** * Provides access to the indices of action labels. - * @param name the action label name. - * @throws SimulatorException if the string was not found or invalid. + * + * @param name + * the action label name. + * @throws SimulatorException + * if the string was not found or invalid. * @return the index of the given action string. */ public int getIndexOfAction(String name) throws SimulatorException { - if(actionIndices.containsKey(name)) - return ((Integer)actionIndices.get(name)).intValue(); - else throw new SimulatorException("Cannot get action index, name: "+name+" does not exist"); + if (actionIndices.containsKey(name)) + return ((Integer) actionIndices.get(name)).intValue(); + else + throw new SimulatorException("Cannot get action index, name: " + name + " does not exist"); } - + /** * Provides access to the loaded 's constants. + * * @return the loaded 's constants. */ public Values getConstants() { - if(constants == null) - { + if (constants == null) { constants = new Values(); } return constants; } - - - //------------------------------------------------------------------------------ - // PATH INITIALISATION AND SETUP METHODS - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // PATH INITIALISATION AND SETUP METHODS + // ------------------------------------------------------------------------------ + /** * Sets up the initial state of the simulator using a Values object - */ + */ private void loadInitialState(Values initialState) throws SimulatorException { int i, ind, value; - try - { - //Define the initial values in the model - for(i = 0; i < initialState.getNumValues(); i++) - { - ind = ((Integer)varIndices.get(initialState.getName(i))).intValue(); - if(initialState.getType(i) == BOOLEAN) + try { + // Define the initial values in the model + for (i = 0; i < initialState.getNumValues(); i++) { + ind = ((Integer) varIndices.get(initialState.getName(i))).intValue(); + if (initialState.getType(i) == BOOLEAN) value = (initialState.getBooleanValue(i)) ? 1 : 0; - else if(initialState.getType(i) == INTEGER) + else if (initialState.getType(i) == INTEGER) value = initialState.getIntValue(i); - else throw new SimulatorException("Invalid type for variable " + initialState.getName(i)); + else + throw new SimulatorException("Invalid type for variable " + initialState.getName(i)); defineVariable(ind, value); } - } - catch(PrismException e) - { + } catch (PrismException e) { throw new SimulatorException(e.getMessage()); } } /** - * Starts a new path, loads the model data structure with its constants defined - * constants. Prerequisites: CONSTANTS MUST BE DEFINED BEFORE CALLING THIS - * METHOD - * @param modulesFile The ModulesFile object to be converted into the simulator - * data structure for a PRISM model. - * @param propertiesFile The PropertiesFile object that any pctl path properties - * belong to. - * @param initialState The intial state for the new path. - * @throws SimulatorException If anything goes wrong with the model loading, or the initialisation - * of the new path. - */ - public void startNewPath(ModulesFile modulesFile, PropertiesFile propertiesFile, Values initialState) throws SimulatorException + * Starts a new path, loads the model data structure with its constants defined constants. Prerequisites: CONSTANTS + * MUST BE DEFINED BEFORE CALLING THIS METHOD + * + * @param modulesFile + * The ModulesFile object to be converted into the simulator data structure for a PRISM model. + * @param propertiesFile + * The PropertiesFile object that any pctl path properties belong to. + * @param initialState + * The intial state for the new path. + * @throws SimulatorException + * If anything goes wrong with the model loading, or the initialisation of the new path. + */ + public void startNewPath(ModulesFile modulesFile, PropertiesFile propertiesFile, Values initialState) + throws SimulatorException { deallocateEngine(); - + loadModulesFile(modulesFile, modulesFile.getConstantValues()); - - if (propertiesFile == null) propertiesFile = new PropertiesFile(modulesFile); - + + if (propertiesFile == null) + propertiesFile = new PropertiesFile(modulesFile); + propertyConstants = propertiesFile.getConstantValues(); this.propertiesFile = propertiesFile; - + int result = allocatePCTLManager(); - if(result == ERROR) - { + if (result == ERROR) { throw new SimulatorException(getLastErrorMessage()); } - + result = allocatePath(); - if(result == ERROR) - { + if (result == ERROR) { throw new SimulatorException(getLastErrorMessage()); } - + // Call startNewPath to actually begin a new trace with the initial state restartNewPath(initialState); } - + /** * Restarts the simulation path with the given intial state. - * @param initialState the initial state to be set into the simulator engine. - * @throws SimulatorException if there is any problem with setting this state. + * + * @param initialState + * the initial state to be set into the simulator engine. + * @throws SimulatorException + * if there is any problem with setting this state. */ public void restartNewPath(Values initialState) throws SimulatorException { - //load the initial state into the model - try - { - //Define the initial values in the model - for(int i = 0; i < initialState.getNumValues(); i++) - { - int index = ((Integer)varIndices.get(initialState.getName(i))).intValue(); + // load the initial state into the model + try { + // Define the initial values in the model + for (int i = 0; i < initialState.getNumValues(); i++) { + int index = ((Integer) varIndices.get(initialState.getName(i))).intValue(); int value; - if(initialState.getType(i) == BOOLEAN) + if (initialState.getType(i) == BOOLEAN) value = (initialState.getBooleanValue(i)) ? 1 : 0; - else if(initialState.getType(i) == INTEGER) + else if (initialState.getType(i) == INTEGER) value = initialState.getIntValue(i); - else throw new SimulatorException("Cannot start new path: Invalid type for variable "+initialState.getName(i)); + else + throw new SimulatorException("Cannot start new path: Invalid type for variable " + + initialState.getName(i)); defineVariable(index, value); } + } catch (PrismException e) { + throw new SimulatorException("Error when starting new path: " + e.getMessage()); } - catch(PrismException e) - { - throw new SimulatorException("Error when starting new path: "+e.getMessage()); - } - + int result = startPath(); - if(result == ERROR) + if (result == ERROR) throw new SimulatorException(getLastErrorMessage()); - + } - + /** - * Allocates an execution path in memory for the purposes of model - * exploration. This should not be used if wishing to do sampling. + * Allocates an execution path in memory for the purposes of model exploration. This should not be used if wishing + * to do sampling. */ private static native int allocatePath(); - + /** - * Gives the variable at the given index a value. This is used - * to define the initial state (hence private) + * Gives the variable at the given index a value. This is used to define the initial state (hence private) */ private static native void defineVariable(int varIndex, int value); - + /** - * Adds the initial state to the path. + * Adds the initial state to the path. */ private static native int startPath(); - - - //------------------------------------------------------------------------------ - // PATH ACCESS METHODS - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // PATH ACCESS METHODS + // ------------------------------------------------------------------------------ + /** * Returns the number of variables and hence the width of the path table. + * * @return the number of variables of the current model. */ public int getNumVariables() { return varNames.length; } - + /** * Returns the name of the variable at the given index. - * @param i the variable index - * @throws SimulatorException if the variable index is out of range. + * + * @param i + * the variable index + * @throws SimulatorException + * if the variable index is out of range. * @return the string representation of the indexed variable. */ public String getVariableName(int i) throws SimulatorException { - if(varNames != null && i < varNames.length && i >= 0) - { + if (varNames != null && i < varNames.length && i >= 0) { return varNames[i]; - } - else throw new SimulatorException("Variable out of range"); + } else + throw new SimulatorException("Variable out of range"); } - + /** * Returns the type of the variable stored at the given index. - * @param i the index of the variable. - * @throws SimulatorException if the variable index is out of range. - * @return either INTEGER, DOUBLE or - * BOOLEAN or depending on the type of the - * indexed variable. + * + * @param i + * the index of the variable. + * @throws SimulatorException + * if the variable index is out of range. + * @return either INTEGER, DOUBLE or BOOLEAN or depending on the type of the + * indexed variable. */ public int getVariableType(int i) throws SimulatorException { - if(varTypes != null && i < varTypes.length && i >= 0) - { + if (varTypes != null && i < varTypes.length && i >= 0) { return varTypes[i]; - } - else throw new SimulatorException("Variable out of range"); + } else + throw new SimulatorException("Variable out of range"); } - + /** * Returns the number of states stored in the current path table. + * * @return the number of states stored in the current path table. */ public static native int getPathSize(); - + /** - * Returns the value stored for the variable at varIndex at the - * path index: stateIndex. - * @param varIndex the index of the variable of interest. - * @param stateIndex the index of the path state of interest - * @return the value stored for the variable at varIndes at the given - * stateIndex. + * Returns the value stored for the variable at varIndex at the path index: stateIndex. + * + * @param varIndex + * the index of the variable of interest. + * @param stateIndex + * the index of the path state of interest + * @return the value stored for the variable at varIndes at the given stateIndex. */ public static native int getPathData(int varIndex, int stateIndex); - + /** * Returns the time spent in the state at the given path index. - * @param stateIndex the index of the path state of interest + * + * @param stateIndex + * the index of the path state of interest * @return the time spent in the state at the given path index. */ public static native double getTimeSpentInPathState(int stateIndex); - + /** * Returns the cumulative time spent in the states upto a given path index. - * @param stateIndex the index of the path state of interest + * + * @param stateIndex + * the index of the path state of interest * @return the time spent in the state at the given path index. */ public static native double getCumulativeTimeSpentInPathState(int stateIndex); - + /** * Returns the ith state reward of the state at the given path index. - * @param stateIndex the index of the path state of interest - * @param i the index of the reward structure + * + * @param stateIndex + * the index of the path state of interest + * @param i + * the index of the reward structure * @return the state reward of the state at the given path index. */ public static native double getStateRewardOfPathState(int stateIndex, int i); - + /** - * Returns the ith transition reward of (moving out of) the state at - * the given path index. - * @param stateIndex the index of the path state of interest - * @param i the index of the reward structure - * @return the transition reward of (moving out of) the state at - * the given path index. + * Returns the ith transition reward of (moving out of) the state at the given path index. + * + * @param stateIndex + * the index of the path state of interest + * @param i + * the index of the reward structure + * @return the transition reward of (moving out of) the state at the given path index. */ public static native double getTransitionRewardOfPathState(int stateIndex, int i); - + /** * Cumulative version of getStateRewardOfPathState. */ public static native double getTotalStateRewardOfPathState(int stateIndex, int i); - + /** * Cumulative version of getTransitionRewardOfPathState. */ - public static native double getTotalTransitionRewardOfPathState(int stateIndex, int i); - + public static native double getTotalTransitionRewardOfPathState(int stateIndex, int i); + /** * Returns the total path time. + * * @return the total path time. */ public static native double getTotalPathTime(); - + /** * Returns the total path reward. + * * @return the total path reward. */ public static native double getTotalPathReward(int i); - + /** * Returns the total state reward for the path. + * * @return the total state reward for the path. */ public static native double getTotalStateReward(int i); - + /** * Returns the total transition reward for the path. + * * @return the total transition reward for the path. */ public static native double getTotalTransitionReward(int i); - + /** * Returns whether the current path is in a looping state + * * @return whether the current path is in a looping state */ public static native boolean isPathLooping(); - + /** * Returns where a loop starts + * * @return where a loop starts */ public static native int loopStart(); - + /** * Returns where a loop ends + * * @return where a loop ends */ public static native int loopEnd(); - + /** * Returns the index of the update chosen for the precalculated old update set. - * @param oldStep the old path step of interest + * + * @param oldStep + * the old path step of interest * @return the index of the update chosen for the precalculated old update set. */ public static native int getChosenIndexOfOldUpdate(int oldStep); - + /** * Exports the current path to a file in a simple space separated format. - * @param file the file to which the path should be exported to (mainLog if null). - * @throws SimulatorException if there is a problem with writing the file. + * + * @param file + * the file to which the path should be exported to (mainLog if null). + * @throws SimulatorException + * if there is a problem with writing the file. */ public void exportPath(File file) throws SimulatorException { exportPath(file, false, " ", null); } - + /** * Exports the current path to a file in a simple space separated format. - * @param file the file to which the path should be exported to (mainLog if null). - * @param timeCumul show time in cumulative form? - * @param colSep string used to separate columns in display - * @param vars only print these vars (and steps which change them) (ignore if null) - * @throws SimulatorException if there is a problem with writing the file. - */ - public void exportPath(File file, boolean timeCumul, String colSep, ArrayList vars) throws SimulatorException + * + * @param file + * the file to which the path should be exported to (mainLog if null). + * @param timeCumul + * show time in cumulative form? + * @param colSep + * string used to separate columns in display + * @param vars + * only print these vars (and steps which change them) (ignore if null) + * @throws SimulatorException + * if there is a problem with writing the file. + */ + public void exportPath(File file, boolean timeCumul, String colSep, ArrayList vars) throws SimulatorException { PrismLog log; - + // create new file log or use main log if (file != null) { log = new PrismFileLog(file.getPath()); if (!log.ready()) { - throw new SimulatorException("Could not open file \""+file+"\" for output"); + throw new SimulatorException("Could not open file \"" + file + "\" for output"); } - mainLog.println("\nExporting path to file \""+file+"\"..."); + mainLog.println("\nExporting path to file \"" + file + "\"..."); } else { log = mainLog; log.println(); } - + exportPathToLog(log, timeCumul, colSep, vars); } /** * Exports the current path to a file in a simple space separated format. - * @param filename the PrismLog to which the path should be exported to - * @param colSep string used to separate columns in display - * @param vars only print these vars (and steps which change them) (ignore if null) - * @throws SimulatorException if there is a problem with writing the file. - */ - public void exportPathToLog(PrismLog log, boolean timeCumul, String colSep, ArrayList vars) throws SimulatorException + * + * @param filename + * the PrismLog to which the path should be exported to + * @param colSep + * string used to separate columns in display + * @param vars + * only print these vars (and steps which change them) (ignore if null) + * @throws SimulatorException + * if there is a problem with writing the file. + */ + public void exportPathToLog(PrismLog log, boolean timeCumul, String colSep, ArrayList vars) + throws SimulatorException { int i, j, n, nv, nr; double d, t; boolean stochastic = (modulesFile.getType() == ModulesFile.STOCHASTIC); boolean changed; int varsNum = 0, varsIndices[] = null; - - if(modulesFile == null) - { + + if (modulesFile == null) { log.flush(); log.close(); return; } - + // Get sizes n = getPathSize(); nv = getNumVariables(); nr = modulesFile.getNumRewardStructs(); - + // if necessary, store info about which vars to display if (vars != null) { varsNum = vars.size(); varsIndices = new int[varsNum]; - for (i = 0; i < varsNum; i++) varsIndices[i] = ((Integer)vars.get(i)).intValue(); + for (i = 0; i < varsNum; i++) + varsIndices[i] = ((Integer) vars.get(i)).intValue(); } - + // Write header log.print("step"); - if (vars == null) for(j = 0; j < nv; j++) log.print(colSep+varNames[j]); - else for(j = 0; j < varsNum; j++) log.print(colSep+varNames[varsIndices[j]]); - if (stochastic) log.print(colSep+(timeCumul?"time":"time_in_state")); + if (vars == null) + for (j = 0; j < nv; j++) + log.print(colSep + varNames[j]); + else + for (j = 0; j < varsNum; j++) + log.print(colSep + varNames[varsIndices[j]]); + if (stochastic) + log.print(colSep + (timeCumul ? "time" : "time_in_state")); if (nr == 1) { - log.print(colSep+"state_reward"+colSep+"transition_reward"); + log.print(colSep + "state_reward" + colSep + "transition_reward"); } else { - for(j = 0; j < nr; j++) log.print(colSep+"state_reward"+(j+1)+colSep+"transition_reward"+(j+1)); + for (j = 0; j < nr; j++) + log.print(colSep + "state_reward" + (j + 1) + colSep + "transition_reward" + (j + 1)); } log.println(); - + // Write path t = 0.0; - for(i = 0; i < n; i++) - { + for (i = 0; i < n; i++) { // (if required) see if relevant vars have changed if (vars != null && i > 0) { changed = false; for (j = 0; j < varsNum; j++) { - if (getPathData(varsIndices[j], i) != getPathData(varsIndices[j], i-1)) changed = true; + if (getPathData(varsIndices[j], i) != getPathData(varsIndices[j], i - 1)) + changed = true; + } + if (!changed) { + d = (i < n - 1) ? getTimeSpentInPathState(i) : 0.0; + t += d; + continue; } - if (!changed) { d = (i= actionNames.length) return "[]"; - else return "[" +actionNames[actionIndex] + "]"; + if (actionIndex < 0 || actionIndex >= actionNames.length) + return "[]"; + else + return "[" + actionNames[actionIndex] + "]"; } - + /** - * Asks the c++ engine for the index of the action of the - * current update at the given index. + * Asks the c++ engine for the index of the action of the current update at the given index. */ private static native int getActionIndexOfUpdate(int i); - + /** - * Returns the module name of the udpate at the given - * index. - * @param i the index of the update of interest. - * @return the module name of the udpate at the given - * index. + * Returns the module name of the udpate at the given index. + * + * @param i + * the index of the update of interest. + * @return the module name of the udpate at the given index. */ public String getModuleNameOfUpdate(int i) { int moduleIndex = getModuleIndexOfUpdate(i); - if(moduleIndex < 0 || moduleIndex >= moduleNames.length) return ""; - else return moduleNames[moduleIndex]; + if (moduleIndex < 0 || moduleIndex >= moduleNames.length) + return ""; + else + return moduleNames[moduleIndex]; } - + /** - * Asks the c++ engine for the index of the module of the - * current update at the given index - * @param i the index of the update of interest. - * @return the index of the module of the - * current update at the given index + * Asks the c++ engine for the index of the module of the current update at the given index + * + * @param i + * the index of the update of interest. + * @return the index of the module of the current update at the given index */ public static native int getModuleIndexOfUpdate(int i); - + /** * Returns the probability/rate of the update at the given index - * @param i the index of the update of interest. + * + * @param i + * the index of the update of interest. * @return the probability/rate of the update at the given index. */ public static native double getProbabilityOfUpdate(int i); - + /** - * Returns a string representation of the assignments for the current - * update at the given index. - * @param index the index of the update of interest. - * @return a string representation of the assignments for the current - * update at the given index. + * Returns a string representation of the assignments for the current update at the given index. + * + * @param index + * the index of the update of interest. + * @return a string representation of the assignments for the current update at the given index. */ public String getAssignmentDescriptionOfUpdate(int index) { String assignment = ""; int numAssigns = getNumAssignmentsOfUpdate(index); - - - - //System.out.println("getAssignmentDesctipyionOfCurrentUpdate" + index); - for(int i = 0; i < numAssigns; i++) - { + + // System.out.println("getAssignmentDesctipyionOfCurrentUpdate" + index); + for (int i = 0; i < numAssigns; i++) { int var = getAssignmentVariableIndexOfUpdate(index, i); int value = getAssignmentValueOfUpdate(index, i); - - if(var < 0 || var >= varNames.length) return ""; + + if (var < 0 || var >= varNames.length) + return ""; String varName = varNames[var]; - if(varTypes[var] == Expression.BOOLEAN) - if(value == 0) + if (varTypes[var] == Expression.BOOLEAN) + if (value == 0) assignment += varName + "\'=false"; else assignment += varName + "\'=true"; else assignment += varName + "\'=" + value; - - if(i != numAssigns-1) assignment+=", "; + + if (i != numAssigns - 1) + assignment += ", "; } return assignment; } - + /** - * Returns the number of assignments for the current update at the - * given index. + * Returns the number of assignments for the current update at the given index. */ private static native int getNumAssignmentsOfUpdate(int i); - + /** - * Returns the index of the variable being assigned to for the - * current update at the given index (updateIndex) and for its - * assignment indexed assignmentIndex + * Returns the index of the variable being assigned to for the current update at the given index (updateIndex) and + * for its assignment indexed assignmentIndex */ private static native int getAssignmentVariableIndexOfUpdate(int updateIndex, int assignmentIndex); - + /** - * Returns the value of the assignment for the current update at - * the given index (updateIndex and for its assignment indexed - * assignmentIndex. + * Returns the value of the assignment for the current update at the given index (updateIndex and for its assignment + * indexed assignmentIndex. */ private static native int getAssignmentValueOfUpdate(int updateIndex, int assignmentIndex); - + /** - * For mdps, updates can belong to different probability distributions. These - * probability distributions are indexed. This returns the probability - * distribution that the indexed update belongs to. - * @param updateIndex the index of the update of interest. - * @return the probability - * distribution that the indexed update belongs to. + * For mdps, updates can belong to different probability distributions. These probability distributions are indexed. + * This returns the probability distribution that the indexed update belongs to. + * + * @param updateIndex + * the index of the update of interest. + * @return the probability distribution that the indexed update belongs to. */ public static native int getDistributionIndexOfUpdate(int updateIndex); - - - //------------------------------------------------------------------------------ - // PROPERTIES AND SAMPLING (not yet sorted) - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // PROPERTIES AND SAMPLING (not yet sorted) + // ------------------------------------------------------------------------------ + /** - * Allocate space for storage of PCTL Formulae + * Allocate space for storage of PCTL Formulae */ private static native int allocatePCTLManager(); - + /** - * Allocate space for storage of sampling information + * Allocate space for storage of sampling information */ private static native int allocateSampling(); - + /** * Provides access to the propertyConstants + * * @return the propertyConstants */ public Values getPropertyConstants() { - if(propertyConstants == null) - { + if (propertyConstants == null) { propertyConstants = new Values(); } return propertyConstants; } - + /** * Convenience method performing various things done before sampling - */ + */ private void setupForSampling(ModulesFile modulesFile, PropertiesFile propertiesFile) throws SimulatorException { int resultError; - + deallocateEngine(); - + loadModulesFile(modulesFile, modulesFile.getConstantValues()); - + propertyConstants = propertiesFile.getConstantValues(); this.propertiesFile = propertiesFile; - + resultError = allocatePCTLManager(); - if(resultError == ERROR) - { + if (resultError == ERROR) { throw new SimulatorException(getLastErrorMessage()); } resultError = allocateSampling(); - if(resultError == ERROR) - { + if (resultError == ERROR) { throw new SimulatorException(getLastErrorMessage()); } } - + /** * Gets (double) result from simulator for a given property/index and process result - */ + */ private Object processSamplingResult(Expression expr, int index) { - if(index == -1) - { + if (index == -1) { return new SimulatorException("Property cannot be handled by the PRISM simulator"); - } - else - { + } else { double result = getSamplingResult(index); - if(result == UNDEFINED_DOUBLE) result = Double.POSITIVE_INFINITY; - // only handle P=?/R=? properties (we could check against the bounds in P>p etc. but results would be a bit dubious) + if (result == UNDEFINED_DOUBLE) + result = Double.POSITIVE_INFINITY; + // only handle P=?/R=? properties (we could check against the bounds in P>p etc. but results would be a bit + // dubious) if (expr instanceof ExpressionProb) { - if (((ExpressionProb)expr).getProb() == null) { + if (((ExpressionProb) expr).getProb() == null) { return new Double(result); } else { return new SimulatorException("Property cannot be handled by the PRISM simulator"); } } else if (expr instanceof ExpressionReward) { - if (((ExpressionReward)expr).getReward() == null) { + if (((ExpressionReward) expr).getReward() == null) { return new Double(result); } else { return new SimulatorException("Property cannot be handled by the PRISM simulator"); } - } - else { + } else { return new SimulatorException("Property cannot be handled by the PRISM simulator"); } } } - - //PCTL Stuff - + + // PCTL Stuff + public static native int exportBinary(String filename); - - public void exportBinaryForSingleProperty( - ModulesFile modulesFile, - PropertiesFile propertiesFile, - Expression expr, - Values initialState, - String filename - ) throws SimulatorException + + public void exportBinaryForSingleProperty(ModulesFile modulesFile, PropertiesFile propertiesFile, Expression expr, + Values initialState, String filename) throws SimulatorException { setupForSampling(modulesFile, propertiesFile); - + int index = addProperty(expr); - - if(index == -1) + + if (index == -1) throw new SimulatorException("Property cannot be handled by the PRISM simulator"); - + loadInitialState(initialState); - + int resultError = exportBinary(filename); - - if(resultError == ERROR) - { + + if (resultError == ERROR) { throw new SimulatorException(getLastErrorMessage()); } - + deallocateEngine(); } - - public void exportBinaryForMultipleProperties( - ModulesFile modulesFile, - PropertiesFile propertiesFile, - ArrayList exprs, - Values initialState, - String filename - ) throws SimulatorException + + public void exportBinaryForMultipleProperties(ModulesFile modulesFile, PropertiesFile propertiesFile, + ArrayList exprs, Values initialState, String filename) throws SimulatorException { setupForSampling(modulesFile, propertiesFile); - + int[] indices = addProperties(exprs); - + boolean existsOne = false; - for(int i = 0; i < indices.length; i++) - { - if(indices[i]>=0) - { + for (int i = 0; i < indices.length; i++) { + if (indices[i] >= 0) { existsOne = true; break; } } - if(!existsOne) + if (!existsOne) throw new SimulatorException("None of the selected properties can be handled by the PRISM simulator"); - + loadInitialState(initialState); - + int resultError = exportBinary(filename); - - if(resultError == ERROR) - { + + if (resultError == ERROR) { throw new SimulatorException(getLastErrorMessage()); } - + deallocateEngine(); } - - - /** - * Returns an ArrayList of Values objects for the each propery iteration - */ - public ArrayList exportBinaryForExperiment( - userinterface.properties.GUIExperiment exp, - java.lang.Thread experimentThread, - ModulesFile modulesFile, - PropertiesFile propertiesFile, - UndefinedConstants undefinedConstants, - Expression propertyToCheck, - Values initialState, - String filename - ) throws PrismException, InterruptedException, SimulatorException + + /** + * Returns an ArrayList of Values objects for the each propery iteration + */ + public ArrayList exportBinaryForExperiment(userinterface.properties.GUIExperiment exp, + java.lang.Thread experimentThread, ModulesFile modulesFile, PropertiesFile propertiesFile, + UndefinedConstants undefinedConstants, Expression propertyToCheck, Values initialState, String filename) + throws PrismException, InterruptedException, SimulatorException { setupForSampling(modulesFile, propertiesFile); - + ArrayList definedPFConstantsCollection = new ArrayList(); Values definedPFConstants = new Values(); - - int[]indices = new int[undefinedConstants.getNumPropertyIterations()]; - int[]types = new int[undefinedConstants.getNumPropertyIterations()]; - - for(int i = 0; i < undefinedConstants.getNumPropertyIterations(); i++) - { - if (propertiesFile != null) - { + + int[] indices = new int[undefinedConstants.getNumPropertyIterations()]; + int[] types = new int[undefinedConstants.getNumPropertyIterations()]; + + for (int i = 0; i < undefinedConstants.getNumPropertyIterations(); i++) { + if (propertiesFile != null) { definedPFConstants = undefinedConstants.getPFConstantValues(); definedPFConstantsCollection.add(definedPFConstants); propertiesFile.setUndefinedConstants(definedPFConstants); - + propertyConstants = propertiesFile.getConstantValues(); } indices[i] = addProperty(propertyToCheck); types[i] = propertyToCheck.getType(); - + undefinedConstants.iterateProperty(); } - + loadInitialState(initialState); - + int resultError = exportBinary(filename); - - if(resultError == ERROR) - { + + if (resultError == ERROR) { throw new SimulatorException(getLastErrorMessage()); } - + deallocateEngine(); - + return definedPFConstantsCollection; } - - /** - * This method completely encapsulates the model checking of a property - * so long as: - * prerequisites modulesFile constants should all be defined - * propertiesFile constants should all be defined - * - *

The returned result is: + + /** + * This method completely encapsulates the model checking of a property so long as: prerequisites modulesFile + * constants should all be defined propertiesFile constants should all be defined + * + *

+ * The returned result is: *

    - *
  • A Double object: for =?[] properties + *
  • A Double object: for =?[] properties *
- * @param modulesFile The ModulesFile, constants already defined. - * @param propertiesFile The PropertiesFile containing the property of interest, constants defined. - * @param expr The property of interest - * @param initialState The initial state for the sampling. - * @param noIterations The number of iterations for the sampling algorithm - * @param maxPathLength the maximum path length for the sampling algorithm. - * @throws SimulatorException if anything goes wrong. + * + * @param modulesFile + * The ModulesFile, constants already defined. + * @param propertiesFile + * The PropertiesFile containing the property of interest, constants defined. + * @param expr + * The property of interest + * @param initialState + * The initial state for the sampling. + * @param noIterations + * The number of iterations for the sampling algorithm + * @param maxPathLength + * the maximum path length for the sampling algorithm. + * @throws SimulatorException + * if anything goes wrong. * @return the result. */ - public Object modelCheckSingleProperty( - ModulesFile modulesFile, - PropertiesFile propertiesFile, - Expression expr, - Values initialState, - int noIterations, - int maxPathLength - ) throws SimulatorException + public Object modelCheckSingleProperty(ModulesFile modulesFile, PropertiesFile propertiesFile, Expression expr, + Values initialState, int noIterations, int maxPathLength) throws SimulatorException { ArrayList exprs; Object res[]; - + exprs = new ArrayList(); exprs.add(expr); - res = modelCheckMultipleProperties(modulesFile, propertiesFile, exprs, initialState, noIterations, maxPathLength); - - if (res[0] instanceof SimulatorException) throw (SimulatorException)res[0]; else return res[0]; + res = modelCheckMultipleProperties(modulesFile, propertiesFile, exprs, initialState, noIterations, + maxPathLength); + + if (res[0] instanceof SimulatorException) + throw (SimulatorException) res[0]; + else + return res[0]; } - + /** - * This method completely encapsulates the model checking of multiple properties - * prerequisites modulesFile constants should all be defined - * propertiesFile constants should all be defined - * - *

The returned result is an array each item of which is either: + * This method completely encapsulates the model checking of multiple properties prerequisites modulesFile constants + * should all be defined propertiesFile constants should all be defined + * + *

+ * The returned result is an array each item of which is either: *

    - *
  • Double object: for =?[] properties - *
  • An exception if there was a problem + *
  • Double object: for =?[] properties + *
  • An exception if there was a problem *
- * @param modulesFile The ModulesFile, constants already defined. - * @param propertiesFile The PropertiesFile containing the property of interest, constants defined. - * @param exprs The properties of interest - * @param initialState The initial state for the sampling. - * @param noIterations The number of iterations for the sampling algorithm - * @param maxPathLength the maximum path length for the sampling algorithm. - * @throws SimulatorException if anything goes wrong. + * + * @param modulesFile + * The ModulesFile, constants already defined. + * @param propertiesFile + * The PropertiesFile containing the property of interest, constants defined. + * @param exprs + * The properties of interest + * @param initialState + * The initial state for the sampling. + * @param noIterations + * The number of iterations for the sampling algorithm + * @param maxPathLength + * the maximum path length for the sampling algorithm. + * @throws SimulatorException + * if anything goes wrong. * @return the result. */ - public Object[] modelCheckMultipleProperties( - ModulesFile modulesFile, - PropertiesFile propertiesFile, - ArrayList exprs, - Values initialState, - int noIterations, - int maxPathLength - ) throws SimulatorException + public Object[] modelCheckMultipleProperties(ModulesFile modulesFile, PropertiesFile propertiesFile, + ArrayList exprs, Values initialState, int noIterations, int maxPathLength) throws SimulatorException { setupForSampling(modulesFile, propertiesFile); - + Object[] results = new Object[exprs.size()]; int[] indices = new int[exprs.size()]; - + // Add the properties to the simulator (after a check that they are valid) int validPropsCount = 0; - for(int i = 0; i < exprs.size(); i++) { + for (int i = 0; i < exprs.size(); i++) { try { - checkPropertyForSimulation((Expression)exprs.get(i), modulesFile.getType()); - indices[i] = addProperty((Expression)exprs.get(i)); - if (indices[i] >= 0) validPropsCount++; - } - catch (SimulatorException e) { + checkPropertyForSimulation((Expression) exprs.get(i), modulesFile.getType()); + indices[i] = addProperty((Expression) exprs.get(i)); + if (indices[i] >= 0) + validPropsCount++; + } catch (SimulatorException e) { results[i] = e; indices[i] = -1; } } - + // as long as there are at least some valid props, do sampling - if(validPropsCount > 0) { + if (validPropsCount > 0) { loadInitialState(initialState); int result = doSampling(noIterations, maxPathLength); - if(result == ERROR) - { + if (result == ERROR) { throw new SimulatorException(getLastErrorMessage()); } } - + // process the results - for(int i = 0; i < results.length; i++) - { + for (int i = 0; i < results.length; i++) { // if we have already stored an error for this property, keep it as the result if (!(results[i] instanceof SimulatorException)) - results[i] = processSamplingResult((Expression)exprs.get(i), indices[i]); + results[i] = processSamplingResult((Expression) exprs.get(i), indices[i]); } - + deallocateEngine(); - + // display results to log if (results.length == 1) { - if (!(results[0] instanceof SimulatorException)) mainLog.println("\nResult: " + results[0]); - } - else { + if (!(results[0] instanceof SimulatorException)) + mainLog.println("\nResult: " + results[0]); + } else { mainLog.println("\nResults:"); - for(int i = 0; i < results.length; i++) mainLog.println(exprs.get(i) + " : " + results[i]); + for (int i = 0; i < results.length; i++) + mainLog.println(exprs.get(i) + " : " + results[i]); } - + return results; } - - /** - * Deals with all of the logistics - * of performing an experiment and storing the results in an - * appropriate ResultsCollection object. - * @param exp the experiment in which to store the results. - * @param modulesFile The ModulesFile, constants already defined. - * @param propertiesFile The PropertiesFile containing the property of interest, constants defined. - * @param undefinedConstants defining what should be done for the experiment - * @param resultsCollection where the results should be stored - * @param propertyToCheck the property to check for the experiment - * @param initialState The initial state for the sampling. - * @param maxPathLength the maximum path length for the sampling algorithm. - * @param noIterations The number of iterations for the sampling algorithm - * @throws PrismException if something goes wrong with the results reporting - * @throws InterruptedException if the thread is interrupted - * @throws SimulatorException if something goes wrong with the sampling algorithm - */ - public void modelCheckExperiment( - ModulesFile modulesFile, - PropertiesFile propertiesFile, - UndefinedConstants undefinedConstants, - ResultsCollection resultsCollection, - Expression propertyToCheck, - Values initialState, - int maxPathLength, - int noIterations - ) throws PrismException, InterruptedException, SimulatorException + + /** + * Deals with all of the logistics of performing an experiment and storing the results in an appropriate + * ResultsCollection object. + * + * @param exp + * the experiment in which to store the results. + * @param modulesFile + * The ModulesFile, constants already defined. + * @param propertiesFile + * The PropertiesFile containing the property of interest, constants defined. + * @param undefinedConstants + * defining what should be done for the experiment + * @param resultsCollection + * where the results should be stored + * @param propertyToCheck + * the property to check for the experiment + * @param initialState + * The initial state for the sampling. + * @param maxPathLength + * the maximum path length for the sampling algorithm. + * @param noIterations + * The number of iterations for the sampling algorithm + * @throws PrismException + * if something goes wrong with the results reporting + * @throws InterruptedException + * if the thread is interrupted + * @throws SimulatorException + * if something goes wrong with the sampling algorithm + */ + public void modelCheckExperiment(ModulesFile modulesFile, PropertiesFile propertiesFile, + UndefinedConstants undefinedConstants, ResultsCollection resultsCollection, Expression propertyToCheck, + Values initialState, int maxPathLength, int noIterations) throws PrismException, InterruptedException, + SimulatorException { int n; Values definedPFConstants = new Values(); - + setupForSampling(modulesFile, propertiesFile); - + n = undefinedConstants.getNumPropertyIterations(); Object[] results = new Object[n]; Values[] pfcs = new Values[n]; int[] indices = new int[n]; - + // Add the properties to the simulator (after a check that they are valid) int validPropsCount = 0; - for(int i = 0; i < n; i++) { + for (int i = 0; i < n; i++) { definedPFConstants = undefinedConstants.getPFConstantValues(); pfcs[i] = definedPFConstants; propertiesFile.setUndefinedConstants(definedPFConstants); @@ -1842,56 +1815,62 @@ public class SimulatorEngine try { checkPropertyForSimulation(propertyToCheck, modulesFile.getType()); indices[i] = addProperty(propertyToCheck); - if (indices[i] >= 0) validPropsCount++; - } - catch (SimulatorException e) { + if (indices[i] >= 0) + validPropsCount++; + } catch (SimulatorException e) { results[i] = e; indices[i] = -1; } undefinedConstants.iterateProperty(); } - + // as long as there are at least some valid props, do sampling - if(validPropsCount > 0) { + if (validPropsCount > 0) { loadInitialState(initialState); int result = doSampling(noIterations, maxPathLength); - if(result == ERROR) - { + if (result == ERROR) { throw new SimulatorException(getLastErrorMessage()); } } - + // process the results - for(int i = 0; i < n; i++) - { + for (int i = 0; i < n; i++) { // if we have already stored an error for this property, keep it as the result, otherwise process if (!(results[i] instanceof Exception)) results[i] = processSamplingResult(propertyToCheck, indices[i]); // store it in the ResultsCollection resultsCollection.setResult(undefinedConstants.getMFConstantValues(), pfcs[i], results[i]); } - + deallocateEngine(); - + // display results to log if (indices.length == 1) { - if (!(results[0] instanceof Exception)) mainLog.println("\nResult: " + results[0]); - } - else { + if (!(results[0] instanceof Exception)) + mainLog.println("\nResult: " + results[0]); + } else { mainLog.println("\nResults:"); - mainLog.print(resultsCollection.toStringPartial(undefinedConstants.getMFConstantValues(), true, " ", " : ", false)); + mainLog.print(resultsCollection.toStringPartial(undefinedConstants.getMFConstantValues(), true, " ", " : ", + false)); } } /** * Generate a random path with the simulator - * @param modulesFile The ModulesFile, constants already defined - * @param initialState The first state of the path - * @param details Information about the path to be generated - * @param file The file to output the path to (stdout if null) - * @throws SimulatorException if something goes wrong - */ - public void generateSimulationPath(ModulesFile modulesFile, Values initialState, String details, int maxPathLength, File file) throws SimulatorException, PrismException + * + * @param modulesFile + * The ModulesFile, constants already defined + * @param initialState + * The first state of the path + * @param details + * Information about the path to be generated + * @param file + * The file to output the path to (stdout if null) + * @throws SimulatorException + * if something goes wrong + */ + public void generateSimulationPath(ModulesFile modulesFile, Values initialState, String details, int maxPathLength, + File file) throws SimulatorException, PrismException { String s, ss[]; int i, j, n; @@ -1899,14 +1878,14 @@ public class SimulatorEngine boolean done; boolean stochastic = (modulesFile.getType() == ModulesFile.STOCHASTIC); int simPathType = -1; - int simPathLength = 0 ; - double simPathTime = 0.0 ; + int simPathLength = 0; + double simPathTime = 0.0; String simPathSep = " "; ArrayList simVars = null; VarList varList; boolean simLoopCheck = true; int simPathRepeat = 1; - + // parse details ss = details.split(","); n = ss.length; @@ -1916,24 +1895,31 @@ public class SimulatorEngine simPathType = SIM_PATH_TIME; try { simPathTime = Double.parseDouble(ss[i].substring(5)); - if (simPathTime < 0.0) throw new NumberFormatException(); + if (simPathTime < 0.0) + throw new NumberFormatException(); } catch (NumberFormatException e) { - throw new SimulatorException("Invalid path time limit \""+ss[i]+"\""); + throw new SimulatorException("Invalid path time limit \"" + ss[i] + "\""); } - } - else if (ss[i].equals("deadlock")) { + } else if (ss[i].equals("deadlock")) { // path until deadlock simPathType = SIM_PATH_DEADLOCK; - } - else if (ss[i].indexOf("sep=") == 0) { + } else if (ss[i].indexOf("sep=") == 0) { // specify column separator to display path simPathSep = ss[i].substring(4); - if (simPathSep.equals("space")) { simPathSep = " "; continue; } - if (simPathSep.equals("tab")) { simPathSep = "\t"; continue; } - if (simPathSep.equals("comma")) { simPathSep = ","; continue; } + if (simPathSep.equals("space")) { + simPathSep = " "; + continue; + } + if (simPathSep.equals("tab")) { + simPathSep = "\t"; + continue; + } + if (simPathSep.equals("comma")) { + simPathSep = ","; + continue; + } throw new SimulatorException("Separator must be one of: \"space\", \"tab\", \"comma\""); - } - else if (ss[i].indexOf("vars=") == 0) { + } else if (ss[i].indexOf("vars=") == 0) { // specify which variables to display varList = modulesFile.createVarList(); simVars = new ArrayList(); @@ -1942,112 +1928,154 @@ public class SimulatorEngine if (s.length() < 1 || s.charAt(0) != '(') throw new SimulatorException("Invalid format for \"vars=(...)\""); s = s.substring(1); - if (s.indexOf(')')>-1) { s = s.substring(0, s.length()-1); done = true; } + if (s.indexOf(')') > -1) { + s = s.substring(0, s.length() - 1); + done = true; + } j = varList.getIndex(s); - if (j == -1) throw new SimulatorException("Unknown variable \""+s+"\" in \"vars=(...)\" list"); + if (j == -1) + throw new SimulatorException("Unknown variable \"" + s + "\" in \"vars=(...)\" list"); simVars.add(new Integer(j)); while (i < n && !done) { s = ss[++i]; - if (s.indexOf(')')>-1) { s = s.substring(0, s.length()-1); done = true; } + if (s.indexOf(')') > -1) { + s = s.substring(0, s.length() - 1); + done = true; + } j = varList.getIndex(s); - if (j == -1) throw new SimulatorException("Unknown variable \""+s+"\" in \"vars=(...)\" list"); + if (j == -1) + throw new SimulatorException("Unknown variable \"" + s + "\" in \"vars=(...)\" list"); simVars.add(new Integer(j)); } - } - else if (ss[i].indexOf("loopcheck=") == 0) { + } else if (ss[i].indexOf("loopcheck=") == 0) { // switch loop detection on/off (default is on) s = ss[i].substring(10); - if (s.equals("true")) { simLoopCheck = true; continue; } - if (s.equals("false")) { simLoopCheck = false; continue; } + if (s.equals("true")) { + simLoopCheck = true; + continue; + } + if (s.equals("false")) { + simLoopCheck = false; + continue; + } throw new SimulatorException("Value for \"loopcheck\" flag must be \"true\" or \"false\""); - } - else if (ss[i].indexOf("repeat=") == 0) { + } else if (ss[i].indexOf("repeat=") == 0) { // how many times to repeat path generation until successful (for "deadlock" option) try { simPathRepeat = Integer.parseInt(ss[i].substring(7)); - if (simPathRepeat < 1) throw new NumberFormatException(); + if (simPathRepeat < 1) + throw new NumberFormatException(); } catch (NumberFormatException e) { throw new SimulatorException("Value for \"repeat\" option must be a positive integer"); } - } - else { + } else { // path of fixed number of steps simPathType = SIM_PATH_NUM_STEPS; try { simPathLength = Integer.parseInt(ss[i]); - if (simPathLength < 0) throw new NumberFormatException(); + if (simPathLength < 0) + throw new NumberFormatException(); } catch (NumberFormatException e) { - throw new SimulatorException("Invalid path length \""+ss[i]+"\""); + throw new SimulatorException("Invalid path length \"" + ss[i] + "\""); } } } - if (simPathType < 0) throw new SimulatorException("Invalid path details \""+details+"\""); - + if (simPathType < 0) + throw new SimulatorException("Invalid path details \"" + details + "\""); + // print details switch (simPathType) { - case SIM_PATH_NUM_STEPS: mainLog.println("\nGenerating random path of length "+simPathLength+" steps..."); break; - case SIM_PATH_TIME: mainLog.println("\nGenerating random path with time limit "+simPathTime+"..."); break; - case SIM_PATH_DEADLOCK: mainLog.println("\nGenerating random path until deadlock state..."); break; + case SIM_PATH_NUM_STEPS: + mainLog.println("\nGenerating random path of length " + simPathLength + " steps..."); + break; + case SIM_PATH_TIME: + mainLog.println("\nGenerating random path with time limit " + simPathTime + "..."); + break; + case SIM_PATH_DEADLOCK: + mainLog.println("\nGenerating random path until deadlock state..."); + break; } - + // display warning if attempt to use "repeat=" option and not "deadlock" option if (simPathRepeat > 1 && simPathType != SIM_PATH_DEADLOCK) { simPathRepeat = 1; - mainLog.println("\nWarning: Ignoring \"repeat\" option - it is only valid when looking for deadlocks."); + mainLog.println("\nWarning: Ignoring \"repeat\" option - it is only valid when looking for deadlocks."); } - + // generate path startNewPath(modulesFile, null, initialState); for (j = 0; j < simPathRepeat; j++) { - if (j > 0) restartNewPath(initialState); + if (j > 0) + restartNewPath(initialState); i = 0; t = 0.0; done = false; while (!done) { // generate a single step of path automaticChoices(1, simLoopCheck); - if (stochastic) t += getTimeSpentInPathState(i++); else t = ++i; + if (stochastic) + t += getTimeSpentInPathState(i++); + else + t = ++i; // check for termination (depending on type) switch (simPathType) { - case SIM_PATH_NUM_STEPS: if (i >= simPathLength) done = true; break; - case SIM_PATH_TIME: if (t >= simPathTime || i >= maxPathLength) done = true; break; - case SIM_PATH_DEADLOCK: if (queryIsDeadlock() == 1 || i >= maxPathLength) done = true; break; + case SIM_PATH_NUM_STEPS: + if (i >= simPathLength) + done = true; + break; + case SIM_PATH_TIME: + if (t >= simPathTime || i >= maxPathLength) + done = true; + break; + case SIM_PATH_DEADLOCK: + if (queryIsDeadlock() == 1 || i >= maxPathLength) + done = true; + break; } // stop if a loop was found (and loop checking was not disabled) - if (simLoopCheck && isPathLooping()) break; + if (simLoopCheck && isPathLooping()) + break; } - + // if we are generating multiple paths (to find a deadlock) only stop if deadlock actually found - if (simPathType == SIM_PATH_DEADLOCK && queryIsDeadlock() == 1) break; + if (simPathType == SIM_PATH_DEADLOCK && queryIsDeadlock() == 1) + break; } - if (j < simPathRepeat) j++; - + if (j < simPathRepeat) + j++; + // display warning if a deterministic loop was detected (but not in case where multiple paths generated) if (simLoopCheck && isPathLooping() && simPathRepeat == 1) { - mainLog.println("\nWarning: Deterministic loop detected after "+i+" steps (use loopcheck=false option to extend path)."); + mainLog.println("\nWarning: Deterministic loop detected after " + i + + " steps (use loopcheck=false option to extend path)."); } - + // if we needed multiple paths to find a deadlock, say how many - if (simPathRepeat > 1 && j > 1) mainLog.println("\n"+j+" paths were generated."); - + if (simPathRepeat > 1 && j > 1) + mainLog.println("\n" + j + " paths were generated."); + // export path if (simPathType == SIM_PATH_DEADLOCK && queryIsDeadlock() != 1) { - mainLog.print("\nNo deadlock state found within "+maxPathLength+" steps"); - if (simPathRepeat > 1) mainLog.print(" (generated "+simPathRepeat+" paths)"); + mainLog.print("\nNo deadlock state found within " + maxPathLength + " steps"); + if (simPathRepeat > 1) + mainLog.print(" (generated " + simPathRepeat + " paths)"); mainLog.println("."); } else { exportPath(file, true, simPathSep, simVars); } - + // warning if stopped early if (simPathType == SIM_PATH_TIME && t < simPathTime) { - mainLog.println("\nWarning: Path terminated before time "+simPathTime+" because maximum path length ("+maxPathLength+") reached."); + mainLog.println("\nWarning: Path terminated before time " + simPathTime + " because maximum path length (" + + maxPathLength + ") reached."); } } /** * Returns a pointer to the built reward formula - * @param expr the ExpressionReward to be built into the engine. + * + * @param expr + * the ExpressionReward to be built into the engine. * @return a pointer to the built reward formula */ public long addExpressionReward(ExpressionReward expr) @@ -2059,197 +2087,204 @@ public class SimulatorEngine double time; Object rs = null; int rsi = -1; - - if (!(expr.getPathExpression() instanceof PathExpressionTemporal)) return -1; - pe = (PathExpressionTemporal)expr.getPathExpression(); - + + if (!(expr.getPathExpression() instanceof PathExpressionTemporal)) + return -1; + pe = (PathExpressionTemporal) expr.getPathExpression(); + allConstants.addValues(getConstants()); allConstants.addValues(getPropertyConstants()); - + // process reward struct index rs = expr.getRewardStructIndex(); if (rs == null) { rsi = 0; - } - else if (rs instanceof Expression) { + } else if (rs instanceof Expression) { try { - rsi = ((Expression)rs).evaluateInt(allConstants, null) - 1; - } catch(PrismException e) { - System.err.println("Property: "+pe.toString()+" could not be used in the simulator because: \n"+ e.toString()); + rsi = ((Expression) rs).evaluateInt(allConstants, null) - 1; + } catch (PrismException e) { + System.err.println("Property: " + pe.toString() + " could not be used in the simulator because: \n" + + e.toString()); return -1; } + } else if (rs instanceof String) { + rsi = modulesFile.getRewardStructIndex((String) rs); } - else if (rs instanceof String) { - rsi = modulesFile.getRewardStructIndex((String)rs); - } - + try { switch (pe.getOperator()) { - + case PathExpressionTemporal.R_C: time = pe.getUpperBound().evaluateDouble(allConstants, null); return loadPctlCumulative(rsi, time); - + case PathExpressionTemporal.R_I: time = pe.getUpperBound().evaluateDouble(allConstants, null); return loadPctlInstantanious(rsi, time); - + case PathExpressionTemporal.R_F: - if (!(pe.getOperand2() instanceof PathExpressionExpr)) return -1; + if (!(pe.getOperand2() instanceof PathExpressionExpr)) + return -1; expr2 = ((PathExpressionExpr) pe.getOperand2()).getExpression(); exprPtr2 = expr2.toSimulator(this); return loadPctlReachability(rsi, exprPtr2); - - default: return -1; + + default: + return -1; } - } - catch(PrismException e) { - System.err.println("Property: "+pe.toString()+" could not be used in the simulator because: \n"+ e.toString()); + } catch (PrismException e) { + System.err.println("Property: " + pe.toString() + " could not be used in the simulator because: \n" + + e.toString()); return -1; } } - + /** * Returns a pointer to the built prob formula - * @param expr the ExpressionProb to be built into the engine. + * + * @param expr + * the ExpressionProb to be built into the engine. * @return a pointer to the built prob formula */ public long addExpressionProb(ExpressionProb expr) { Values allConstants = new Values(); - PathExpressionTemporal pe; + PathExpressionTemporal pet; + PathExpression pe2; Expression expr1, expr2; long exprPtr1, exprPtr2; double time1, time2; - - if (!(expr.getPathExpression() instanceof PathExpressionTemporal)) return -1; - pe = (PathExpressionTemporal)expr.getPathExpression(); - + boolean negated = false; + + if (!(expr.getPathExpression() instanceof PathExpressionTemporal)) + return -1; + pet = (PathExpressionTemporal) expr.getPathExpression(); + allConstants.addValues(getConstants()); allConstants.addValues(getPropertyConstants()); - + + // Convert anything that is not until/next into until + if (!(pet.getOperator() == PathExpressionTemporal.P_X || pet.getOperator() == PathExpressionTemporal.P_U)) { + try { + pe2 = pet.convertToUntilForm(); + } catch (PrismException e) { + return -1; + } + if (pe2 instanceof PathExpressionLogical + && ((PathExpressionLogical) pe2).getOperator() == PathExpressionLogical.NOT) { + pet = (PathExpressionTemporal) ((PathExpressionLogical) pe2).getOperand2(); + negated = true; + } else { + pet = (PathExpressionTemporal) pe2; + negated = false; + } + } + try { - switch (pe.getOperator()) { - + switch (pet.getOperator()) { + case PathExpressionTemporal.P_X: - if (!(pe.getOperand2() instanceof PathExpressionExpr)) return -1; - expr2 = ((PathExpressionExpr) pe.getOperand2()).getExpression(); + if (!(pet.getOperand2() instanceof PathExpressionExpr)) + return -1; + expr2 = ((PathExpressionExpr) pet.getOperand2()).getExpression(); exprPtr2 = expr2.toSimulator(this); return loadPctlNext(exprPtr2); - + case PathExpressionTemporal.P_U: - if (!(pe.getOperand1() instanceof PathExpressionExpr)) return -1; - expr1 = ((PathExpressionExpr) pe.getOperand1()).getExpression(); + if (!(pet.getOperand1() instanceof PathExpressionExpr)) + return -1; + expr1 = ((PathExpressionExpr) pet.getOperand1()).getExpression(); exprPtr1 = expr1.toSimulator(this); - if (!(pe.getOperand2() instanceof PathExpressionExpr)) return -1; - expr2 = ((PathExpressionExpr) pe.getOperand2()).getExpression(); + if (!(pet.getOperand2() instanceof PathExpressionExpr)) + return -1; + expr2 = ((PathExpressionExpr) pet.getOperand2()).getExpression(); exprPtr2 = expr2.toSimulator(this); - if (pe.hasBounds()) { - time1 = (pe.getLowerBound() == null) ?0.0 : pe.getLowerBound().evaluateDouble(allConstants, null); - time2 = (pe.getUpperBound() == null) ?Integer.MAX_VALUE : pe.getUpperBound().evaluateDouble(allConstants, null); - return loadPctlBoundedUntil(exprPtr1, exprPtr2, time1, time2); - }else { - return loadPctlUntil(exprPtr1, exprPtr2); + if (pet.hasBounds()) { + time1 = (pet.getLowerBound() == null) ? 0.0 : pet.getLowerBound() + .evaluateDouble(allConstants, null); + time2 = (pet.getUpperBound() == null) ? Integer.MAX_VALUE : pet.getUpperBound().evaluateDouble( + allConstants, null); + if (!negated) { + return loadPctlBoundedUntil(exprPtr1, exprPtr2, time1, time2); + } else { + return loadPctlBoundedUntilNegated(exprPtr1, exprPtr2, time1, time2); + } + } else { + if (!negated) { + return loadPctlUntil(exprPtr1, exprPtr2); + } else { + return loadPctlUntilNegated(exprPtr1, exprPtr2); + } } - case PathExpressionTemporal.P_F: - expr1 = Expression.True(); - exprPtr1 = expr1.toSimulator(this); - if (!(pe.getOperand2() instanceof PathExpressionExpr)) return -1; - expr2 = ((PathExpressionExpr) pe.getOperand2()).getExpression(); - exprPtr2 = expr2.toSimulator(this); - if (pe.hasBounds()) { - time1 = (pe.getLowerBound() == null) ?0.0 : pe.getLowerBound().evaluateDouble(allConstants, null); - time2 = (pe.getUpperBound() == null) ?Integer.MAX_VALUE : pe.getUpperBound().evaluateDouble(allConstants, null); - return loadPctlBoundedUntil(exprPtr1, exprPtr2, time1, time2); - }else { - return loadPctlUntil(exprPtr1, exprPtr2); - } - - case PathExpressionTemporal.P_G: - expr1 = Expression.True(); - exprPtr1 = expr1.toSimulator(this); - if (!(pe.getOperand2() instanceof PathExpressionExpr)) return -1; - expr2 = Expression.Not(((PathExpressionExpr) pe.getOperand2()).getExpression()); - exprPtr2 = expr2.toSimulator(this); - if (pe.hasBounds()) { - time1 = (pe.getLowerBound() == null) ?0.0 : pe.getLowerBound().evaluateDouble(allConstants, null); - time2 = (pe.getUpperBound() == null) ?Integer.MAX_VALUE : pe.getUpperBound().evaluateDouble(allConstants, null); - return loadPctlBoundedUntilNegated(exprPtr1, exprPtr2, time1, time2); - }else { - return loadPctlUntilNegated(exprPtr1, exprPtr2); - } - - default: return -1; + default: + return -1; } - } - catch(PrismException e) { - System.err.println("Property: "+pe.toString()+" could not be used in the simulator because: \n"+ e.toString()); + } catch (PrismException e) { + System.err.println("Property: " + pet.toString() + " could not be used in the simulator because: \n" + + e.toString()); return -1; } } - - /** Returns the index of the property, if it can be added, -1 if nots + + /** + * Returns the index of the property, if it can be added, -1 if nots */ private int addProperty(Expression prop) { Values allConstants = new Values(); allConstants.addValues(getConstants()); allConstants.addValues(getPropertyConstants()); - + long pathPointer; - if(prop instanceof ExpressionProb) { - pathPointer = addExpressionProb((ExpressionProb)prop); - if(pathPointer == -1) return -1; - - if (((ExpressionProb)prop).getProb() == null) { + if (prop instanceof ExpressionProb) { + pathPointer = addExpressionProb((ExpressionProb) prop); + if (pathPointer == -1) + return -1; + + if (((ExpressionProb) prop).getProb() == null) { return loadProbQuestion(pathPointer); - } - else { + } else { return -1; } - } - else if (prop instanceof ExpressionReward) { - pathPointer = addExpressionReward((ExpressionReward)prop); - if(pathPointer == -1) return -1; - - if (((ExpressionReward)prop).getReward() == null) { + } else if (prop instanceof ExpressionReward) { + pathPointer = addExpressionReward((ExpressionReward) prop); + if (pathPointer == -1) + return -1; + + if (((ExpressionReward) prop).getReward() == null) { return loadRewardQuestion(pathPointer); - } - else { + } else { return -1; } - } - else return -1; + } else + return -1; } - - + private static native int doSampling(int noIterations, int maxPathLength); - + private static native double getSamplingResult(int propertyIndex); - + private static native int getNumReachedMaxPath(int propertyIndex); - + /** * Used to halt the sampling algorithm in its tracks. */ public static native void stopSampling(); - + /** - * Returns an array of indices of the properties within - * the simulator... -1 means that the formula could not be - * loaded + * Returns an array of indices of the properties within the simulator... -1 means that the formula could not be + * loaded */ private int[] addProperties(ArrayList props) { - int [] indices = new int[props.size()]; - for(int i = 0; i < props.size(); i++) - { - indices[i] = addProperty((Expression)(props.get(i))); + int[] indices = new int[props.size()]; + for (int i = 0; i < props.size(); i++) { + indices[i] = addProperty((Expression) (props.get(i))); } return indices; } - + /** * Used by the recursive model/properties loading methods (not part of the API) */ @@ -2257,21 +2292,24 @@ public class SimulatorEngine { return propertiesFile.getCombinedLabelList(); } - + // Methods to compute parameters for simulation - + public double computeSimulationApproximation(double confid, int numSamples) { - return Math.sqrt((4.0 * log(10, 2.0/confid))/numSamples); + return Math.sqrt((4.0 * log(10, 2.0 / confid)) / numSamples); } + public double computeSimulationConfidence(double approx, int numSamples) { - return 2.0 / Math.pow(10, (numSamples*approx*approx)/4.0); + return 2.0 / Math.pow(10, (numSamples * approx * approx) / 4.0); } + public int computeSimulationNumSamples(double approx, double confid) { - return (int)Math.ceil(4.0 * log(10, 2.0/confid) / (approx*approx)); + return (int) Math.ceil(4.0 * log(10, 2.0 / confid) / (approx * approx)); } + public static double log(double base, double x) { return Math.log(x) / Math.log(base); @@ -2279,7 +2317,7 @@ public class SimulatorEngine // Method to check if a property is suitable for simulation // If not, throws an exception with the reason - + public void checkPropertyForSimulation(Expression prop, int modelType) throws SimulatorException { // Check general validity of property @@ -2288,447 +2326,464 @@ public class SimulatorEngine } catch (PrismLangException e) { throw new SimulatorException(e.getMessage()); } - + // Simulator can only be applied to P=? or R=? properties boolean ok = true; PathExpression pe = null; - if (!(prop instanceof ExpressionProb || prop instanceof ExpressionReward)) ok = false; + if (!(prop instanceof ExpressionProb || prop instanceof ExpressionReward)) + ok = false; else if (prop instanceof ExpressionProb) { - if ((((ExpressionProb)prop).getProb() != null)) ok = false; - pe = ((ExpressionProb)prop).getPathExpression(); + if ((((ExpressionProb) prop).getProb() != null)) + ok = false; + pe = ((ExpressionProb) prop).getPathExpression(); + } else if (prop instanceof ExpressionReward) { + if ((((ExpressionReward) prop).getReward() != null)) + ok = false; + pe = ((ExpressionReward) prop).getPathExpression(); } - else if (prop instanceof ExpressionReward) { - if ((((ExpressionReward)prop).getReward() != null)) ok = false; - pe = ((ExpressionReward)prop).getPathExpression(); - } - if (!ok) throw new SimulatorException("Simulator can only be applied to properties of the form \"P=? [ ... ]\" or \"R=? [ ... ]\""); - + if (!ok) + throw new SimulatorException( + "Simulator can only be applied to properties of the form \"P=? [ ... ]\" or \"R=? [ ... ]\""); + // Check that there are no nested probabilistic operators try { - pe.accept(new ASTTraverse() { - public void visitPre(ExpressionProb e) throws PrismLangException { throw new PrismLangException(""); } - public void visitPre(ExpressionReward e) throws PrismLangException { throw new PrismLangException(""); } - public void visitPre(ExpressionSS e) throws PrismLangException { throw new PrismLangException(""); } + pe.accept(new ASTTraverse() + { + public void visitPre(ExpressionProb e) throws PrismLangException + { + throw new PrismLangException(""); + } + + public void visitPre(ExpressionReward e) throws PrismLangException + { + throw new PrismLangException(""); + } + + public void visitPre(ExpressionSS e) throws PrismLangException + { + throw new PrismLangException(""); + } }); - } - catch (PrismLangException e) { + } catch (PrismLangException e) { throw new SimulatorException("Simulator cannot handle nested P, R or S operators"); } } - //------------------------------------------------------------------------------ - // STATE PROPOSITION METHODS - //------------------------------------------------------------------------------ - + // ------------------------------------------------------------------------------ + // STATE PROPOSITION METHODS + // ------------------------------------------------------------------------------ + /** - * Loads the boolean expression stored at exprPointer into the simulator engine. - * Returns the index of where the proposition is being stored + * Loads the boolean expression stored at exprPointer into the simulator engine. Returns the index of where the + * proposition is being stored */ public static native int loadProposition(long exprPointer); - + /** - * For the state proposition stored at the given index, this returns 1 if it - * is true in the current state and 0 if not. -1 is returned if the index - * is invalid. + * For the state proposition stored at the given index, this returns 1 if it is true in the current state and 0 if + * not. -1 is returned if the index is invalid. */ public static native int queryProposition(int index); - + /** - * For the state proposition stored at the given index, this returns 1 if it - * is true in the state at the given path step and 0 if not. -1 is returned if the index - * is invalid. + * For the state proposition stored at the given index, this returns 1 if it is true in the state at the given path + * step and 0 if not. -1 is returned if the index is invalid. */ public static native int queryProposition(int index, int step); - + /** - * For the current state, this returns 1 if it is the same as - * the initial state for the current path + * For the current state, this returns 1 if it is the same as the initial state for the current path */ public static native int queryIsInitial(); - + /** - * For the state at the given index, this returns 1 if it is - * the same as the initial state for the current path + * For the state at the given index, this returns 1 if it is the same as the initial state for the current path */ public static native int queryIsInitial(int step); - + /** - * For the current state, this returns 1 if it is a deadlock - * state. + * For the current state, this returns 1 if it is a deadlock state. */ public static native int queryIsDeadlock(); - + /** - * For the state at the given index, this returns 1 if it is - * a deadlock state. + * For the state at the given index, this returns 1 if it is a deadlock state. */ public static native int queryIsDeadlock(int step); - - //------------------------------------------------------------------------------ - // PATH FORMULA METHODS - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // PATH FORMULA METHODS + // ------------------------------------------------------------------------------ + /** - * Loads the path formula stored at pathPointer into the simulator engine. - * Returns the index of where the path is being stored + * Loads the path formula stored at pathPointer into the simulator engine. Returns the index of where the path is + * being stored */ public static native int findPathFormulaIndex(long pathPointer); - + /** - * For the path formula at the given index, this returns: - *
    - *
  • -1 if the answer is unknown - *
  • 0 if the answer is false - *
  • 1 if the answer is true - *
  • 2 if the answer is numeric - *
+ * For the path formula at the given index, this returns: + *
    + *
  • -1 if the answer is unknown + *
  • 0 if the answer is false + *
  • 1 if the answer is true + *
  • 2 if the answer is numeric + *
*/ public static native int queryPathFormula(int index); - + /** - * Returns the numberic answer for the indexed path formula + * Returns the numberic answer for the indexed path formula */ public static native double queryPathFormulaNumeric(int index); - - //------------------------------------------------------------------------------ - // EXPRESSION CREATION METHODS - // These methods provide facilities to create expressions (either for - // the model or for properties). - // The data structures are built in c++. The methods return integers - // that are actually pointers to CExpression objects. They are - // public because they are used in the - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // EXPRESSION CREATION METHODS + // These methods provide facilities to create expressions (either for + // the model or for properties). + // The data structures are built in c++. The methods return integers + // that are actually pointers to CExpression objects. They are + // public because they are used in the + // ------------------------------------------------------------------------------ + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalConstant(int constIndex, int type); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealConstant(int constIndex); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createIntegerVar(int varIndex); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createBooleanVar(int varIndex); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createDouble(double value); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createInteger(int value); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createBoolean(boolean value); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createCeil(long exprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createFloor(long exprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalPow(long baseExpressionPointer, long exponentExpressionPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealPow(long baseExpressionPointer, long exponentExpressionPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createMod(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createLog(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNot(long exprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createAnd(long[] exprPointers); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createOr(long[] exprPointers); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalMax(long[] exprPointers); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalMin(long[] exprPointers); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealMax(long[] exprPointers); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealMin(long[] exprPointers); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalTimes(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalPlus(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalMinus(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealTimes(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealPlus(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealMinus(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createDivide(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createIte(long conditionPointer, long truePointer, long falsePointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealIte(long conditionPointer, long truePointer, long falsePointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalEquals(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealEquals(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalNotEquals(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealNotEquals(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalLessThan(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealLessThan(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalGreaterThan(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealGreaterThan(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalLessThanEqual(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealLessThanEqual(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createNormalGreaterThanEqual(long lexprPointer, long rexprPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createRealGreaterThanEqual(long lexprPointer, long rexprPointer); - - - //------------------------------------------------------------------------------ - // PCTL FORMULAE CREATION METHODS - // These methods provide facilities to build PCTL and CSL Formulae - //------------------------------------------------------------------------------ - - //internal formulae (these methods return a pointer to the formula's memory - //location - - private static native long loadPctlBoundedUntil(long leftExprPointer, long rightExprPointer, double lowerBound, double upperBound); - private static native long loadPctlBoundedUntilNegated(long leftExprPointer, long rightExprPointer, double lowerBound, double upperBound); - + + // ------------------------------------------------------------------------------ + // PCTL FORMULAE CREATION METHODS + // These methods provide facilities to build PCTL and CSL Formulae + // ------------------------------------------------------------------------------ + + // internal formulae (these methods return a pointer to the formula's memory + // location + + private static native long loadPctlBoundedUntil(long leftExprPointer, long rightExprPointer, double lowerBound, + double upperBound); + + private static native long loadPctlBoundedUntilNegated(long leftExprPointer, long rightExprPointer, + double lowerBound, double upperBound); + private static native long loadPctlUntil(long leftExprPointer, long rightExprPointer); + private static native long loadPctlUntilNegated(long leftExprPointer, long rightExprPointer); - + private static native long loadPctlNext(long exprPointer); - + private static native long loadPctlReachability(int rsi, long expressionPointer); - + private static native long loadPctlCumulative(int rsi, double time); - + private static native long loadPctlInstantanious(int rsi, double time); - - //prob formulae (these return the index of the property within the engine. - + + // prob formulae (these return the index of the property within the engine. + private static native int loadProbQuestion(long pathPointer); - - - //rewards formulae (these return the index of the property within the engine. - + + // rewards formulae (these return the index of the property within the engine. + private static native int loadRewardQuestion(long pathPointer); - - - //------------------------------------------------------------------------------ - // TRANSITION TABLE CREATION METHODS - // These methods provide facilities to build the transition table's commands, - // updates and assignments. - // The data structures are built in c++. The methods return integers - // that are actually pointers. - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // TRANSITION TABLE CREATION METHODS + // These methods provide facilities to build the transition table's commands, + // updates and assignments. + // The data structures are built in c++. The methods return integers + // that are actually pointers. + // ------------------------------------------------------------------------------ + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createCommand(long guardPointer, int actionIndex, int moduleIndex, int numUpdates); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long addUpdate(long commandPointer, long probPointer, int numAssignments); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long addAssignment(long updatePointer, int varIndex, long rhsPointer); - - - //------------------------------------------------------------------------------ - // REWARDS TABLE CREATION METHODS - // These methods provide facilities to build the rewards tables. - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // REWARDS TABLE CREATION METHODS + // These methods provide facilities to build the rewards tables. + // ------------------------------------------------------------------------------ + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createStateReward(long guardPointer, long rewardPointer); - + /** * Used by the recursive model/properties loading methods (not part of the API) */ public static native long createTransitionReward(int actionIndex, long guardPointer, long rewardPointer); - - //------------------------------------------------------------------------------ - // UTILITY METHODS - // These are for debugging purposes only - //------------------------------------------------------------------------------ - + + // ------------------------------------------------------------------------------ + // UTILITY METHODS + // These are for debugging purposes only + // ------------------------------------------------------------------------------ + /** * Convienience method to print an expression at a given pointer location - * @param exprPointer the expression pointer. + * + * @param exprPointer + * the expression pointer. */ public static native void printExpression(long exprPointer); - + /** * Returns a string representation of the expression at the given pointer location. - * @param exprPointer the pointer location of the expression. + * + * @param exprPointer + * the pointer location of the expression. * @return a string representation of the expression at the given pointer location. */ public static native String expressionToString(long exprPointer); - + /** * Deletes an expression from memory. + * * @deprecated A bit drastic now. - * @param exprPointer the pointer to the location of the expression + * @param exprPointer + * the pointer to the location of the expression */ - public static native void deleteExpression(long exprPointer); //use with care! - + public static native void deleteExpression(long exprPointer); // use with care! + /** * Returns a string representation of the loaded simulator engine model. + * * @return a string representation of the loaded simulator engine model. */ public static native String modelToString(); - + /** * Returns a string representation of the stored path. + * * @return a string representation of the stored path. */ public static native String pathToString(); - + /** * Prints the current update set to the command line. */ public static native void printCurrentUpdates(); - - - //------------------------------------------------------------------------------ - // ERROR HANDLING - //------------------------------------------------------------------------------ - - /** - * If any native method has had a problem, it should have passed a message - * to the error handler. This method returns that message. + + // ------------------------------------------------------------------------------ + // ERROR HANDLING + // ------------------------------------------------------------------------------ + + /** + * If any native method has had a problem, it should have passed a message to the error handler. This method returns + * that message. + * * @return returns the last c++ error message. */ public static native String getLastErrorMessage(); - + } -//================================================================================== +// ==================================================================================