|
|
|
@ -313,7 +313,8 @@ public class StateModelChecker extends PrismComponent |
|
|
|
|
|
|
|
// Do model checking and store result vector |
|
|
|
timer = System.currentTimeMillis(); |
|
|
|
vals = checkExpression(model, expr); |
|
|
|
// check expression for all states (null => statesOfInterest=all) |
|
|
|
vals = checkExpression(model, expr, null); |
|
|
|
timer = System.currentTimeMillis() - timer; |
|
|
|
mainLog.println("\nTime for model checking: " + timer / 1000.0 + " seconds."); |
|
|
|
|
|
|
|
@ -338,26 +339,28 @@ public class StateModelChecker extends PrismComponent |
|
|
|
* For other required info (labels, reward structures, etc.), use the methods |
|
|
|
* {@link #setModulesFile} and {@link #setPropertiesFile} |
|
|
|
* to attach the original model/properties files. |
|
|
|
* @param statesOfInterest a set of states for which results should be calculated (null = all states). |
|
|
|
* The calculated values for states not of interest are arbitrary and should to be ignored. |
|
|
|
*/ |
|
|
|
public StateValues checkExpression(Model model, Expression expr) throws PrismException |
|
|
|
public StateValues checkExpression(Model model, Expression expr, BitSet statesOfInterest) throws PrismException |
|
|
|
{ |
|
|
|
StateValues res = null; |
|
|
|
|
|
|
|
// If-then-else |
|
|
|
if (expr instanceof ExpressionITE) { |
|
|
|
res = checkExpressionITE(model, (ExpressionITE) expr); |
|
|
|
res = checkExpressionITE(model, (ExpressionITE) expr, statesOfInterest); |
|
|
|
} |
|
|
|
// Binary ops |
|
|
|
else if (expr instanceof ExpressionBinaryOp) { |
|
|
|
res = checkExpressionBinaryOp(model, (ExpressionBinaryOp) expr); |
|
|
|
res = checkExpressionBinaryOp(model, (ExpressionBinaryOp) expr, statesOfInterest); |
|
|
|
} |
|
|
|
// Unary ops |
|
|
|
else if (expr instanceof ExpressionUnaryOp) { |
|
|
|
res = checkExpressionUnaryOp(model, (ExpressionUnaryOp) expr); |
|
|
|
res = checkExpressionUnaryOp(model, (ExpressionUnaryOp) expr, statesOfInterest); |
|
|
|
} |
|
|
|
// Functions |
|
|
|
else if (expr instanceof ExpressionFunc) { |
|
|
|
res = checkExpressionFunc(model, (ExpressionFunc) expr); |
|
|
|
res = checkExpressionFunc(model, (ExpressionFunc) expr, statesOfInterest); |
|
|
|
} |
|
|
|
// Identifiers |
|
|
|
else if (expr instanceof ExpressionIdent) { |
|
|
|
@ -376,25 +379,25 @@ public class StateModelChecker extends PrismComponent |
|
|
|
else if (expr instanceof ExpressionFormula) { |
|
|
|
// This should have been defined or expanded by now. |
|
|
|
if (((ExpressionFormula) expr).getDefinition() != null) |
|
|
|
return checkExpression(model, ((ExpressionFormula) expr).getDefinition()); |
|
|
|
return checkExpression(model, ((ExpressionFormula) expr).getDefinition(), statesOfInterest); |
|
|
|
else |
|
|
|
throw new PrismException("Unexpanded formula \"" + ((ExpressionFormula) expr).getName() + "\""); |
|
|
|
} |
|
|
|
// Variables |
|
|
|
else if (expr instanceof ExpressionVar) { |
|
|
|
res = checkExpressionVar(model, (ExpressionVar) expr); |
|
|
|
res = checkExpressionVar(model, (ExpressionVar) expr, statesOfInterest); |
|
|
|
} |
|
|
|
// Labels |
|
|
|
else if (expr instanceof ExpressionLabel) { |
|
|
|
res = checkExpressionLabel(model, (ExpressionLabel) expr); |
|
|
|
res = checkExpressionLabel(model, (ExpressionLabel) expr, statesOfInterest); |
|
|
|
} |
|
|
|
// Property refs |
|
|
|
else if (expr instanceof ExpressionProp) { |
|
|
|
res = checkExpressionProp(model, (ExpressionProp) expr); |
|
|
|
res = checkExpressionProp(model, (ExpressionProp) expr, statesOfInterest); |
|
|
|
} |
|
|
|
// Filter |
|
|
|
else if (expr instanceof ExpressionFilter) { |
|
|
|
res = checkExpressionFilter(model, (ExpressionFilter) expr); |
|
|
|
res = checkExpressionFilter(model, (ExpressionFilter) expr, statesOfInterest); |
|
|
|
} |
|
|
|
// Anything else - error |
|
|
|
else { |
|
|
|
@ -406,16 +409,17 @@ public class StateModelChecker extends PrismComponent |
|
|
|
|
|
|
|
/** |
|
|
|
* Model check a binary operator. |
|
|
|
* @param statesOfInterest the states of interest, see checkExpression() |
|
|
|
*/ |
|
|
|
protected StateValues checkExpressionITE(Model model, ExpressionITE expr) throws PrismException |
|
|
|
protected StateValues checkExpressionITE(Model model, ExpressionITE expr, BitSet statesOfInterest) throws PrismException |
|
|
|
{ |
|
|
|
StateValues res1 = null, res2 = null, res3 = null; |
|
|
|
|
|
|
|
// Check operands recursively |
|
|
|
try { |
|
|
|
res1 = checkExpression(model, expr.getOperand1()); |
|
|
|
res2 = checkExpression(model, expr.getOperand2()); |
|
|
|
res3 = checkExpression(model, expr.getOperand3()); |
|
|
|
res1 = checkExpression(model, expr.getOperand1(), statesOfInterest); |
|
|
|
res2 = checkExpression(model, expr.getOperand2(), statesOfInterest); |
|
|
|
res3 = checkExpression(model, expr.getOperand3(), statesOfInterest); |
|
|
|
} catch (PrismException e) { |
|
|
|
if (res1 != null) |
|
|
|
res1.clear(); |
|
|
|
@ -434,16 +438,17 @@ public class StateModelChecker extends PrismComponent |
|
|
|
|
|
|
|
/** |
|
|
|
* Model check a binary operator. |
|
|
|
* @param statesOfInterest the states of interest, see checkExpression() |
|
|
|
*/ |
|
|
|
protected StateValues checkExpressionBinaryOp(Model model, ExpressionBinaryOp expr) throws PrismException |
|
|
|
protected StateValues checkExpressionBinaryOp(Model model, ExpressionBinaryOp expr, BitSet statesOfInterest) throws PrismException |
|
|
|
{ |
|
|
|
StateValues res1 = null, res2 = null; |
|
|
|
int op = expr.getOperator(); |
|
|
|
|
|
|
|
// Check operands recursively |
|
|
|
try { |
|
|
|
res1 = checkExpression(model, expr.getOperand1()); |
|
|
|
res2 = checkExpression(model, expr.getOperand2()); |
|
|
|
res1 = checkExpression(model, expr.getOperand1(), statesOfInterest); |
|
|
|
res2 = checkExpression(model, expr.getOperand2(), statesOfInterest); |
|
|
|
} catch (PrismException e) { |
|
|
|
if (res1 != null) |
|
|
|
res1.clear(); |
|
|
|
@ -459,14 +464,15 @@ public class StateModelChecker extends PrismComponent |
|
|
|
|
|
|
|
/** |
|
|
|
* Model check a unary operator. |
|
|
|
* @param statesOfInterest the states of interest, see checkExpression() |
|
|
|
*/ |
|
|
|
protected StateValues checkExpressionUnaryOp(Model model, ExpressionUnaryOp expr) throws PrismException |
|
|
|
protected StateValues checkExpressionUnaryOp(Model model, ExpressionUnaryOp expr, BitSet statesOfInterest) throws PrismException |
|
|
|
{ |
|
|
|
StateValues res1 = null; |
|
|
|
int op = expr.getOperator(); |
|
|
|
|
|
|
|
// Check operand recursively |
|
|
|
res1 = checkExpression(model, expr.getOperand()); |
|
|
|
res1 = checkExpression(model, expr.getOperand(), statesOfInterest); |
|
|
|
|
|
|
|
// Parentheses are easy - nothing to do: |
|
|
|
if (op == ExpressionUnaryOp.PARENTH) |
|
|
|
@ -480,20 +486,21 @@ public class StateModelChecker extends PrismComponent |
|
|
|
|
|
|
|
/** |
|
|
|
* Model check a function. |
|
|
|
* @param statesOfInterest the states of interest, see checkExpression() |
|
|
|
*/ |
|
|
|
protected StateValues checkExpressionFunc(Model model, ExpressionFunc expr) throws PrismException |
|
|
|
protected StateValues checkExpressionFunc(Model model, ExpressionFunc expr, BitSet statesOfInterest) throws PrismException |
|
|
|
{ |
|
|
|
switch (expr.getNameCode()) { |
|
|
|
case ExpressionFunc.MIN: |
|
|
|
case ExpressionFunc.MAX: |
|
|
|
return checkExpressionFuncNary(model, expr); |
|
|
|
return checkExpressionFuncNary(model, expr, statesOfInterest); |
|
|
|
case ExpressionFunc.FLOOR: |
|
|
|
case ExpressionFunc.CEIL: |
|
|
|
return checkExpressionFuncUnary(model, expr); |
|
|
|
return checkExpressionFuncUnary(model, expr, statesOfInterest); |
|
|
|
case ExpressionFunc.POW: |
|
|
|
case ExpressionFunc.MOD: |
|
|
|
case ExpressionFunc.LOG: |
|
|
|
return checkExpressionFuncBinary(model, expr); |
|
|
|
return checkExpressionFuncBinary(model, expr, statesOfInterest); |
|
|
|
case ExpressionFunc.MULTI: |
|
|
|
throw new PrismException("Multi-objective model checking is not supported for " + model.getModelType() + "s"); |
|
|
|
default: |
|
|
|
@ -501,13 +508,13 @@ public class StateModelChecker extends PrismComponent |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected StateValues checkExpressionFuncUnary(Model model, ExpressionFunc expr) throws PrismException |
|
|
|
protected StateValues checkExpressionFuncUnary(Model model, ExpressionFunc expr, BitSet statesOfInterest) throws PrismException |
|
|
|
{ |
|
|
|
StateValues res1 = null; |
|
|
|
int op = expr.getNameCode(); |
|
|
|
|
|
|
|
// Check operand recursively |
|
|
|
res1 = checkExpression(model, expr.getOperand(0)); |
|
|
|
res1 = checkExpression(model, expr.getOperand(0), statesOfInterest); |
|
|
|
|
|
|
|
// Apply operation |
|
|
|
try { |
|
|
|
@ -523,15 +530,15 @@ public class StateModelChecker extends PrismComponent |
|
|
|
return res1; |
|
|
|
} |
|
|
|
|
|
|
|
protected StateValues checkExpressionFuncBinary(Model model, ExpressionFunc expr) throws PrismException |
|
|
|
protected StateValues checkExpressionFuncBinary(Model model, ExpressionFunc expr, BitSet statesOfInterest) throws PrismException |
|
|
|
{ |
|
|
|
StateValues res1 = null, res2 = null; |
|
|
|
int op = expr.getNameCode(); |
|
|
|
|
|
|
|
// Check operands recursively |
|
|
|
try { |
|
|
|
res1 = checkExpression(model, expr.getOperand(0)); |
|
|
|
res2 = checkExpression(model, expr.getOperand(1)); |
|
|
|
res1 = checkExpression(model, expr.getOperand(0), statesOfInterest); |
|
|
|
res2 = checkExpression(model, expr.getOperand(1), statesOfInterest); |
|
|
|
} catch (PrismException e) { |
|
|
|
if (res1 != null) |
|
|
|
res1.clear(); |
|
|
|
@ -555,19 +562,19 @@ public class StateModelChecker extends PrismComponent |
|
|
|
return res1; |
|
|
|
} |
|
|
|
|
|
|
|
protected StateValues checkExpressionFuncNary(Model model, ExpressionFunc expr) throws PrismException |
|
|
|
protected StateValues checkExpressionFuncNary(Model model, ExpressionFunc expr, BitSet statesOfInterest) throws PrismException |
|
|
|
{ |
|
|
|
StateValues res1 = null, res2 = null; |
|
|
|
int i, n, op = expr.getNameCode(); |
|
|
|
|
|
|
|
// Check first operand recursively |
|
|
|
res1 = checkExpression(model, expr.getOperand(0)); |
|
|
|
res1 = checkExpression(model, expr.getOperand(0), statesOfInterest); |
|
|
|
// Go through remaining operands |
|
|
|
n = expr.getNumOperands(); |
|
|
|
for (i = 1; i < n; i++) { |
|
|
|
// Check next operand recursively |
|
|
|
try { |
|
|
|
res2 = checkExpression(model, expr.getOperand(i)); |
|
|
|
res2 = checkExpression(model, expr.getOperand(i), statesOfInterest); |
|
|
|
} catch (PrismException e) { |
|
|
|
if (res2 != null) |
|
|
|
res2.clear(); |
|
|
|
@ -609,9 +616,12 @@ public class StateModelChecker extends PrismComponent |
|
|
|
|
|
|
|
/** |
|
|
|
* Model check a variable reference. |
|
|
|
* @param statesOfInterest the states of interest, see checkExpression() |
|
|
|
*/ |
|
|
|
protected StateValues checkExpressionVar(Model model, ExpressionVar expr) throws PrismException |
|
|
|
protected StateValues checkExpressionVar(Model model, ExpressionVar expr, BitSet statesOfInterest) throws PrismException |
|
|
|
{ |
|
|
|
// TODO (JK): optimize evaluation using statesOfInterest |
|
|
|
|
|
|
|
int numStates = model.getNumStates(); |
|
|
|
StateValues res = new StateValues(expr.getType(), model); |
|
|
|
List<State> statesList = model.getStatesList(); |
|
|
|
@ -633,9 +643,12 @@ public class StateModelChecker extends PrismComponent |
|
|
|
|
|
|
|
/** |
|
|
|
* Model check a label. |
|
|
|
* @param statesOfInterest the states of interest, see checkExpression() |
|
|
|
*/ |
|
|
|
protected StateValues checkExpressionLabel(Model model, ExpressionLabel expr) throws PrismException |
|
|
|
protected StateValues checkExpressionLabel(Model model, ExpressionLabel expr, BitSet statesOfInterest) throws PrismException |
|
|
|
{ |
|
|
|
// TODO: optimize evaluation using statesOfInterest |
|
|
|
|
|
|
|
LabelList ll; |
|
|
|
int i; |
|
|
|
|
|
|
|
@ -666,19 +679,19 @@ public class StateModelChecker extends PrismComponent |
|
|
|
if (i == -1) |
|
|
|
throw new PrismException("Unknown label \"" + expr.getName() + "\" in property"); |
|
|
|
// check recursively |
|
|
|
return checkExpression(model, ll.getLabel(i)); |
|
|
|
return checkExpression(model, ll.getLabel(i), statesOfInterest); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Check property ref |
|
|
|
|
|
|
|
protected StateValues checkExpressionProp(Model model, ExpressionProp expr) throws PrismException |
|
|
|
protected StateValues checkExpressionProp(Model model, ExpressionProp expr, BitSet statesOfInterest) throws PrismException |
|
|
|
{ |
|
|
|
// Look up property and check recursively |
|
|
|
Property prop = propertiesFile.lookUpPropertyObjectByName(expr.getName()); |
|
|
|
if (prop != null) { |
|
|
|
mainLog.println("\nModel checking : " + prop); |
|
|
|
return checkExpression(model, prop.getExpression()); |
|
|
|
return checkExpression(model, prop.getExpression(), statesOfInterest); |
|
|
|
} else { |
|
|
|
throw new PrismException("Unknown property reference " + expr); |
|
|
|
} |
|
|
|
@ -686,7 +699,7 @@ public class StateModelChecker extends PrismComponent |
|
|
|
|
|
|
|
// Check filter |
|
|
|
|
|
|
|
protected StateValues checkExpressionFilter(Model model, ExpressionFilter expr) throws PrismException |
|
|
|
protected StateValues checkExpressionFilter(Model model, ExpressionFilter expr, BitSet statesOfInterest) throws PrismException |
|
|
|
{ |
|
|
|
// Filter info |
|
|
|
Expression filter; |
|
|
|
@ -712,7 +725,10 @@ public class StateModelChecker extends PrismComponent |
|
|
|
filterTrue = Expression.isTrue(filter); |
|
|
|
// Store some more info |
|
|
|
filterStatesString = filterTrue ? "all states" : "states satisfying filter"; |
|
|
|
bsFilter = checkExpression(model, filter).getBitSet(); |
|
|
|
|
|
|
|
// get the BitSet of states matching the filter, without taking statesOfInterest into account |
|
|
|
bsFilter = checkExpression(model, filter, null).getBitSet(); |
|
|
|
|
|
|
|
// Check if filter state set is empty; we treat this as an error |
|
|
|
if (bsFilter.isEmpty()) { |
|
|
|
throw new PrismException("Filter satisfies no states"); |
|
|
|
@ -733,8 +749,8 @@ public class StateModelChecker extends PrismComponent |
|
|
|
currentFilter = null; |
|
|
|
} |
|
|
|
|
|
|
|
// Check operand recursively |
|
|
|
vals = checkExpression(model, expr.getOperand()); |
|
|
|
// Check operand recursively, using bsFilter as statesOfInterest |
|
|
|
vals = checkExpression(model, expr.getOperand(), bsFilter); |
|
|
|
|
|
|
|
// Print out number of states satisfying filter |
|
|
|
if (!filterInit) |
|
|
|
@ -1090,7 +1106,7 @@ public class StateModelChecker extends PrismComponent |
|
|
|
// Model check |
|
|
|
StateValues sv; |
|
|
|
try { |
|
|
|
sv = mc.checkExpression(model, e); |
|
|
|
sv = mc.checkExpression(model, e, null); |
|
|
|
} catch (PrismException ex) { |
|
|
|
throw new PrismLangException(ex.getMessage()); |
|
|
|
} |
|
|
|
|