Browse Source

LTL for DTMCs/CTMCs (and a bit of a tidy-up of LTL stuff).

git-svn-id: https://www.prismmodelchecker.org/svn/prism/prism/trunk@917 bbc10eb1-c90d-0410-af57-cb519fbb1720
master
Dave Parker 17 years ago
parent
commit
71c4a0f6d9
  1. 476
      prism/src/prism/LTLModelChecker.java
  2. 19
      prism/src/prism/NondetModelChecker.java
  3. 153
      prism/src/prism/ProbModelChecker.java
  4. 7
      prism/src/prism/StochModelChecker.java

476
prism/src/prism/LTLModelChecker.java

@ -42,30 +42,29 @@ public class LTLModelChecker
{ {
protected Prism prism; protected Prism prism;
protected PrismLog mainLog; protected PrismLog mainLog;
protected ModelChecker parent;
// DRA/product stuff // DRA/product stuff
protected JDDVars draDDRowVars; protected JDDVars draDDRowVars;
protected JDDVars draDDColVars; protected JDDVars draDDColVars;
public LTLModelChecker(Prism prism, ModelChecker parent) throws PrismException
public LTLModelChecker(Prism prism) throws PrismException
{ {
this.prism = prism; this.prism = prism;
mainLog = prism.getMainLog(); mainLog = prism.getMainLog();
this.parent = parent;
} }
/* Extract maximal state formula from an LTL path formula, model check them (with
* parent model checker) and replace them with ExpressionLabel objects L0, L1, etc.
* As an optimisation, model checking that results in true/false for all states is
* converted to an actual true/false, and duplicate results are given the same label.
/**
* Extract maximal state formula from an LTL path formula, model check them (with passed in model checker) and
* replace them with ExpressionLabel objects L0, L1, etc. Expression passed in is modified directly, but the result
* is also returned. As an optimisation, model checking that results in true/false for all states is converted to an
* actual true/false, and duplicate results are given the same label.
*/ */
public Expression checkMaximalStateFormulas(Model model, Expression expr, Vector<JDDNode> labelDDs)
public Expression checkMaximalStateFormulas(ModelChecker mc, Model model, Expression expr, Vector<JDDNode> labelDDs)
throws PrismException throws PrismException
{ {
// A state formula // A state formula
if (expr.getType() == Expression.BOOLEAN) { if (expr.getType() == Expression.BOOLEAN) {
// Model check // Model check
JDDNode dd = parent.checkExpressionDD(expr);
JDDNode dd = mc.checkExpressionDD(expr);
// Detect special cases (true, false) for optimisation // Detect special cases (true, false) for optimisation
if (dd.equals(JDD.ZERO)) { if (dd.equals(JDD.ZERO)) {
JDD.Deref(dd); JDD.Deref(dd);
@ -82,7 +81,7 @@ public class LTLModelChecker
JDD.Deref(dd); JDD.Deref(dd);
return new ExpressionLabel("L" + i); return new ExpressionLabel("L" + i);
} }
// Otherwise, add result to list, return new label
// Otherwise, add result to list, return new label
labelDDs.add(dd); labelDDs.add(dd);
return new ExpressionLabel("L" + (labelDDs.size() - 1)); return new ExpressionLabel("L" + (labelDDs.size() - 1));
} }
@ -90,25 +89,28 @@ public class LTLModelChecker
else if (expr.getType() == Expression.PATH_BOOLEAN) { else if (expr.getType() == Expression.PATH_BOOLEAN) {
if (expr instanceof ExpressionBinaryOp) { if (expr instanceof ExpressionBinaryOp) {
ExpressionBinaryOp exprBinOp = (ExpressionBinaryOp) expr; ExpressionBinaryOp exprBinOp = (ExpressionBinaryOp) expr;
exprBinOp.setOperand1(checkMaximalStateFormulas(model, exprBinOp.getOperand1(), labelDDs));
exprBinOp.setOperand2(checkMaximalStateFormulas(model, exprBinOp.getOperand2(), labelDDs));
exprBinOp.setOperand1(checkMaximalStateFormulas(mc, model, exprBinOp.getOperand1(), labelDDs));
exprBinOp.setOperand2(checkMaximalStateFormulas(mc, model, exprBinOp.getOperand2(), labelDDs));
} else if (expr instanceof ExpressionUnaryOp) { } else if (expr instanceof ExpressionUnaryOp) {
ExpressionUnaryOp exprUnOp = (ExpressionUnaryOp) expr; ExpressionUnaryOp exprUnOp = (ExpressionUnaryOp) expr;
exprUnOp.setOperand(checkMaximalStateFormulas(model, exprUnOp.getOperand(), labelDDs));
exprUnOp.setOperand(checkMaximalStateFormulas(mc, model, exprUnOp.getOperand(), labelDDs));
} else if (expr instanceof ExpressionTemporal) { } else if (expr instanceof ExpressionTemporal) {
ExpressionTemporal exprTemp = (ExpressionTemporal) expr; ExpressionTemporal exprTemp = (ExpressionTemporal) expr;
if (exprTemp.getOperand1() != null) { if (exprTemp.getOperand1() != null) {
exprTemp.setOperand1(checkMaximalStateFormulas(model, exprTemp.getOperand1(), labelDDs));
exprTemp.setOperand1(checkMaximalStateFormulas(mc, model, exprTemp.getOperand1(), labelDDs));
} }
if (exprTemp.getOperand2() != null) { if (exprTemp.getOperand2() != null) {
exprTemp.setOperand2(checkMaximalStateFormulas(model, exprTemp.getOperand2(), labelDDs));
exprTemp.setOperand2(checkMaximalStateFormulas(mc, model, exprTemp.getOperand2(), labelDDs));
} }
} }
} }
return expr; return expr;
} }
public NondetModel constructProductModel(DRA dra, Model model, Vector<JDDNode> labelDDs) throws PrismException
/**
* Construct product of DRA and DTMC/CTMC.
*/
public ProbModel constructProductMC(DRA dra,ProbModel model, Vector<JDDNode> labelDDs) throws PrismException
{ {
// Existing model - dds, vars, etc. // Existing model - dds, vars, etc.
JDDVars varDDRowVars[]; JDDVars varDDRowVars[];
@ -143,10 +145,10 @@ public class LTLModelChecker
} }
// See how many new dd vars will be needed for DRA // See how many new dd vars will be needed for DRA
// and whether there is room to put them before rather than after the existing vars
// and whether there is room to put them before rather than after the existing vars
n = (int) Math.ceil(PrismUtils.log2(dra.size())); n = (int) Math.ceil(PrismUtils.log2(dra.size()));
before = true; before = true;
if ((allDDRowVars.getMinVarIndex() - ((NondetModel) model).getAllDDNondetVars().getMaxVarIndex()) - 1 < 2 * n) {
if (allDDRowVars.getMinVarIndex() - 1 < 2 * n) {
before = false; before = false;
} }
@ -195,7 +197,6 @@ public class LTLModelChecker
newVarList.addVar(before ? 0 : varList.getNumVars(), draVar, 0, dra.size() - 1, 0, 1, Expression.INT); newVarList.addVar(before ? 0 : varList.getNumVars(), draVar, 0, dra.size() - 1, 0, 1, Expression.INT);
// Extra references (because will get derefed when new model is done with) // Extra references (because will get derefed when new model is done with)
// TODO: tidy this up, make it corresond to model.clear()
allDDRowVars.refAll(); allDDRowVars.refAll();
allDDRowVars.refAll(); allDDRowVars.refAll();
allDDColVars.refAll(); allDDColVars.refAll();
@ -206,17 +207,167 @@ public class LTLModelChecker
} }
draDDRowVars.refAll(); draDDRowVars.refAll();
draDDColVars.refAll(); draDDColVars.refAll();
((NondetModel) model).getAllDDSchedVars().refAll();
((NondetModel) model).getAllDDSynchVars().refAll();
((NondetModel) model).getAllDDChoiceVars().refAll();
((NondetModel) model).getAllDDNondetVars().refAll();
// Build transition matrix for product
newTrans = buildTransMask(dra, labelDDs, allDDRowVars, allDDColVars, draDDRowVars, draDDColVars); newTrans = buildTransMask(dra, labelDDs, allDDRowVars, allDDColVars, draDDRowVars, draDDColVars);
JDD.Ref(model.getTrans()); JDD.Ref(model.getTrans());
newTrans = JDD.Apply(JDD.TIMES, model.getTrans(), newTrans); newTrans = JDD.Apply(JDD.TIMES, model.getTrans(), newTrans);
// Note: ... TODO
newStart = buildStartMask(dra, labelDDs);
// Build set of initial states for product
// Note that we take product of *all* states of the original MDP, not just its initial states.
// Initial states are only used for reachability in this instance.
// We need to ensure that the product model includes states corresponding to all
// states of the original MDP (because we compute probabilities for all of them)
// but some of these may not be reachable from the initial state of the product model.
newStart = buildStartMask(dra, labelDDs, draDDRowVars);
JDD.Ref(model.getReach());
newStart = JDD.And(model.getReach(), newStart);
// Create a new model model object to store the product model
ProbModel modelProd = new ProbModel(
// New transition matrix/start state
newTrans, newStart,
// Don't pass in any rewards info
new JDDNode[0], new JDDNode[0], new String[0],
// New list of all row/col vars
newAllDDRowVars, newAllDDColVars,
// New list of var names
newDDVarNames,
// Module info (unchanged)
model.getNumModules(), model.getModuleNames(), model.getModuleDDRowVars(), model.getModuleDDColVars(),
// New var info
model.getNumVars() + 1, newVarList, newVarDDRowVars, newVarDDColVars,
// Constants (no change)
model.getConstantValues());
// Do reachability/etc. for the new model
modelProd.doReachability(prism.getExtraReachInfo());
modelProd.filterReachableStates();
modelProd.findDeadlocks();
if (modelProd.getDeadlockStates().size() > 0) {
throw new PrismException("Model-DRA product has deadlock states");
}
return modelProd;
}
/**
* Construct product of DRA and MDP.
*/
public NondetModel constructProductMDP(DRA dra, NondetModel model, Vector<JDDNode> labelDDs) throws PrismException
{
// Existing model - dds, vars, etc.
JDDVars varDDRowVars[];
JDDVars varDDColVars[];
JDDVars allDDRowVars;
JDDVars allDDColVars;
Vector<String> ddVarNames;
VarList varList;
// New (product) model - dds, vars, etc.
JDDNode newTrans, newStart;
JDDVars newVarDDRowVars[], newVarDDColVars[];
JDDVars newAllDDRowVars, newAllDDColVars;
Vector<String> newDDVarNames;
VarList newVarList;
String draVar;
// Misc
int i, j, n;
boolean before;
// Get details of old model
varDDRowVars = model.getVarDDRowVars();
varDDColVars = model.getVarDDColVars();
allDDRowVars = model.getAllDDRowVars();
allDDColVars = model.getAllDDColVars();
ddVarNames = model.getDDVarNames();
varList = model.getVarList();
// Create a (new, unique) name for the variable that will represent DRA states
draVar = "_dra";
while (varList.getIndex(draVar) != -1) {
draVar = "_" + draVar;
}
// See how many new dd vars will be needed for DRA
// and whether there is room to put them before rather than after the existing vars
n = (int) Math.ceil(PrismUtils.log2(dra.size()));
before = true;
if ((allDDRowVars.getMinVarIndex() - model.getAllDDNondetVars().getMaxVarIndex()) - 1 < 2 * n) {
before = false;
}
// Create the new dd variables
draDDRowVars = new JDDVars();
draDDColVars = new JDDVars();
newDDVarNames = new Vector<String>();
newDDVarNames.addAll(ddVarNames);
j = before ? allDDRowVars.getMinVarIndex() - 2 * n : model.getAllDDColVars().getMaxVarIndex() + 1;
for (i = 0; i < n; i++) {
draDDRowVars.addVar(JDD.Var(j++));
draDDColVars.addVar(JDD.Var(j++));
if (!before) {
newDDVarNames.add("");
newDDVarNames.add("");
}
newDDVarNames.set(j - 2, draVar + "." + i);
newDDVarNames.set(j - 1, draVar + "'." + i);
}
// Create/populate new lists
newVarDDRowVars = new JDDVars[varDDRowVars.length + 1];
newVarDDColVars = new JDDVars[varDDRowVars.length + 1];
newVarDDRowVars[before ? 0 : varDDRowVars.length] = draDDRowVars;
newVarDDColVars[before ? 0 : varDDColVars.length] = draDDColVars;
for (i = 0; i < varDDRowVars.length; i++) {
newVarDDRowVars[before ? i + 1 : i] = new JDDVars();
newVarDDColVars[before ? i + 1 : i] = new JDDVars();
newVarDDRowVars[before ? i + 1 : i].addVars(varDDRowVars[i]);
newVarDDColVars[before ? i + 1 : i].addVars(varDDColVars[i]);
}
newAllDDRowVars = new JDDVars();
newAllDDColVars = new JDDVars();
if (before) {
newAllDDRowVars.addVars(draDDRowVars);
newAllDDColVars.addVars(draDDColVars);
newAllDDRowVars.addVars(allDDRowVars);
newAllDDColVars.addVars(allDDColVars);
} else {
newAllDDRowVars.addVars(allDDRowVars);
newAllDDColVars.addVars(allDDColVars);
newAllDDRowVars.addVars(draDDRowVars);
newAllDDColVars.addVars(draDDColVars);
}
newVarList = (VarList) varList.clone();
newVarList.addVar(before ? 0 : varList.getNumVars(), draVar, 0, dra.size() - 1, 0, 1, Expression.INT);
// Extra references (because will get derefed when new model is done with)
allDDRowVars.refAll();
allDDRowVars.refAll();
allDDColVars.refAll();
allDDColVars.refAll();
for (i = 0; i < model.getNumModules(); i++) {
model.getModuleDDRowVars(i).refAll();
model.getModuleDDColVars(i).refAll();
}
draDDRowVars.refAll();
draDDColVars.refAll();
model.getAllDDSchedVars().refAll();
model.getAllDDSynchVars().refAll();
model.getAllDDChoiceVars().refAll();
model.getAllDDNondetVars().refAll();
// Build transition matrix for product
newTrans = buildTransMask(dra, labelDDs, allDDRowVars, allDDColVars, draDDRowVars, draDDColVars);
JDD.Ref(model.getTrans());
newTrans = JDD.Apply(JDD.TIMES, model.getTrans(), newTrans);
// Build set of initial states for product
// Note that we take product of *all* states of the original MDP, not just its initial states.
// Initial states are only used for reachability in this instance.
// We need to ensure that the product model includes states corresponding to all
// states of the original MDP (because we compute probabilities for all of them)
// but some of these may not be reachable from the initial state of the product model.
newStart = buildStartMask(dra, labelDDs, draDDRowVars);
JDD.Ref(model.getReach()); JDD.Ref(model.getReach());
newStart = JDD.And(model.getReach(), newStart); newStart = JDD.And(model.getReach(), newStart);
@ -229,8 +380,7 @@ public class LTLModelChecker
// New list of all row/col vars // New list of all row/col vars
newAllDDRowVars, newAllDDColVars, newAllDDRowVars, newAllDDColVars,
// Nondet variables (unchanged) // Nondet variables (unchanged)
((NondetModel) model).getAllDDSchedVars(), ((NondetModel) model).getAllDDSynchVars(),
((NondetModel) model).getAllDDChoiceVars(), ((NondetModel) model).getAllDDNondetVars(),
model.getAllDDSchedVars(), model.getAllDDSynchVars(), model.getAllDDChoiceVars(), model.getAllDDNondetVars(),
// New list of var names // New list of var names
newDDVarNames, newDDVarNames,
// Module info (unchanged) // Module info (unchanged)
@ -251,14 +401,14 @@ public class LTLModelChecker
return modelProd; return modelProd;
} }
/**
* Builds a mask BDD for trans (which contains transitions between every
* DRA state after adding draRow/Colvars) that includes only the transitions
* that exist in the DRA.
* @return a referenced mask BDD over trans
/**
* Builds a mask BDD for trans (which contains transitions between every DRA state after adding draRow/ColVars) that
* includes only the transitions that exist in the DRA.
*
* @return a referenced mask BDD over trans
*/ */
public JDDNode buildTransMask(DRA dra, Vector<JDDNode> labelDDs, JDDVars allDDRowVars, JDDVars allDDColVars,
JDDVars draDDRowVars, JDDVars draDDColVars)
public JDDNode buildTransMask(DRA dra, Vector<JDDNode> labelDDs, JDDVars allDDRowVars, JDDVars allDDColVars, JDDVars draDDRowVars,
JDDVars draDDColVars)
{ {
Iterator<DA_State> it; Iterator<DA_State> it;
DA_State state; DA_State state;
@ -271,7 +421,8 @@ public class LTLModelChecker
state = it.next(); state = it.next();
for (Map.Entry<APElement, DA_State> edge : state.edges().entrySet()) { for (Map.Entry<APElement, DA_State> edge : state.edges().entrySet()) {
// Build a transition label BDD for each edge // Build a transition label BDD for each edge
//System.out.println(state.getName() + " to " + edge.getValue().getName() + " through " + edge.getKey().toString(dra.getAPSet(), false));
// System.out.println(state.getName() + " to " + edge.getValue().getName() + " through " +
// edge.getKey().toString(dra.getAPSet(), false));
label = JDD.Constant(1); label = JDD.Constant(1);
n = dra.getAPSize(); n = dra.getAPSize();
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
@ -286,8 +437,8 @@ public class LTLModelChecker
// Switch label BDD to col vars // Switch label BDD to col vars
label = JDD.PermuteVariables(label, allDDRowVars, allDDColVars); label = JDD.PermuteVariables(label, allDDRowVars, allDDColVars);
// Build a BDD for the edge // Build a BDD for the edge
transition = JDD.SetMatrixElement(JDD.Constant(0), draDDRowVars, draDDColVars, state.getName(), edge
.getValue().getName(), 1);
transition = JDD.SetMatrixElement(JDD.Constant(0), draDDRowVars, draDDColVars, state.getName(), edge.getValue().getName(),
1);
// Now get the conjunction of the two // Now get the conjunction of the two
transition = JDD.And(transition, label); transition = JDD.And(transition, label);
// Add edge BDD to the DRA transition mask // Add edge BDD to the DRA transition mask
@ -298,20 +449,21 @@ public class LTLModelChecker
return draMask; return draMask;
} }
/**
* Builds a mask BDD for start (which contains start nodes for every
* DRA state after adding draRow/ColVars) that includes only the start states
* (s, q) such that q = delta(q_in, label(s)) in the DRA.
* @return a referenced mask BDD over start
/**
* Builds a mask BDD for start (which contains start nodes for every DRA state after adding draRowVars) that
* includes only the start states (s, q) such that q = delta(q_in, label(s)) in the DRA.
*
* @return a referenced mask BDD over start
*/ */
public JDDNode buildStartMask(DRA dra, Vector<JDDNode> labelDDs)
public JDDNode buildStartMask(DRA dra, Vector<JDDNode> labelDDs, JDDVars draDDRowVars)
{ {
JDDNode startMask, label, exprBDD, dest, tmp; JDDNode startMask, label, exprBDD, dest, tmp;
startMask = JDD.Constant(0); startMask = JDD.Constant(0);
for (Map.Entry<APElement, DA_State> edge : dra.getStartState().edges().entrySet()) { for (Map.Entry<APElement, DA_State> edge : dra.getStartState().edges().entrySet()) {
// Build a transition label BDD for each edge // Build a transition label BDD for each edge
//System.out.println("To " + edge.getValue().getName() + " through " + edge.getKey().toString(dra.getAPSet(), false));
// System.out.println("To " + edge.getValue().getName() + " through " +
// edge.getKey().toString(dra.getAPSet(), false));
label = JDD.Constant(1); label = JDD.Constant(1);
for (int i = 0; i < dra.getAPSize(); i++) { for (int i = 0; i < dra.getAPSize(); i++) {
exprBDD = labelDDs.get(Integer.parseInt(dra.getAPSet().getAP(i).substring(1))); exprBDD = labelDDs.get(Integer.parseInt(dra.getAPSet().getAP(i).substring(1)));
@ -334,31 +486,105 @@ public class LTLModelChecker
return startMask; return startMask;
} }
/** /**
* computes sets of accepting states for each Rabin acceptance pair
* Computes sets of accepting states in a DTMC/CTMC for each Rabin acceptance pair
* *
* @returns a referenced BDD of the union of all the accepting sets * @returns a referenced BDD of the union of all the accepting sets
*/
public JDDNode findAcceptingStates(DRA dra, NondetModel model, boolean fairness) throws PrismException {
*/
public JDDNode findAcceptingBSCCs(DRA dra, ProbModel model) throws PrismException
{
SCCComputer sccComputer ;
JDDNode acceptingStates, allAcceptingStates;
Vector<JDDNode> vectBSCCs, newVectBSCCs;
JDDNode tmp;
int i, j, n;
// Compute BSCCs for model
sccComputer = prism.getSCCComputer(model);
sccComputer.computeBSCCs();
vectBSCCs = sccComputer.getVectBSCCs();
JDD.Deref(sccComputer.getNotInBSCCs());
allAcceptingStates = JDD.Constant(0);
// for each acceptance pair (H_i, L_i) in the DRA, build H'_i = S x H_i
// and compute the BSCCs in H'_i
for (i = 0; i < dra.acceptance().size(); i++) {
JDDNode allAcceptingStates = JDD.Constant(0);
// build the acceptance vectors H_i and L_i
JDDNode acceptanceVector_H = JDD.Constant(0);
JDDNode acceptanceVector_L = JDD.Constant(0);
for (j = 0; j < dra.size(); j++) {
/*
* [dA97] uses Rabin acceptance pairs (H_i, L_i) such that H_i contains Inf(ρ) The intersection of
* Inf(ρ) and L_i is non-empty
*
* OTOH ltl2dstar (and our port to java) uses pairs (L_i, U_i) such that The intersection of U_i and
* Inf(ρ) is empty (H_i = S - U_i) The intersection of L_i and Inf(ρ) is non-empty
*/
if (!dra.acceptance().isStateInAcceptance_U(i, j)) {
acceptanceVector_H = JDD.SetVectorElement(acceptanceVector_H, draDDRowVars, j, 1.0);
}
if (dra.acceptance().isStateInAcceptance_L(i, j)) {
acceptanceVector_L = JDD.SetVectorElement(acceptanceVector_L, draDDRowVars, j, 1.0);
}
}
// Restrict each BSCC to H_i states
n = vectBSCCs.size();
newVectBSCCs = new Vector<JDDNode>();
for (j = 0; j < n; j++) {
tmp = vectBSCCs.get(j);
JDD.Ref(tmp);
JDD.Ref(acceptanceVector_H);
tmp = JDD.And(tmp, acceptanceVector_H);
newVectBSCCs.add(tmp);
}
JDD.Deref(acceptanceVector_H);
// Compute union of BSCCs which overlap with acceptanceVector_L
acceptingStates = filteredUnion(newVectBSCCs, acceptanceVector_L);
// Add states to our destination BDD
allAcceptingStates = JDD.Or(allAcceptingStates, acceptingStates);
}
// Deref BSCCs
n = vectBSCCs.size();
for (j = 0; j < n; j++) {
JDD.Deref(vectBSCCs.get(j));
}
return allAcceptingStates;
}
/**
* Computes sets of accepting states in an MDP for each Rabin acceptance pair
*
* @returns a referenced BDD of the union of all the accepting sets
*/
public JDDNode findAcceptingStates(DRA dra, NondetModel model, boolean fairness) throws PrismException
{
JDDNode acceptingStates, allAcceptingStates;
int i, j;
allAcceptingStates = JDD.Constant(0);
// for each acceptance pair (H_i, L_i) in the DRA, build H'_i = S x H_i // for each acceptance pair (H_i, L_i) in the DRA, build H'_i = S x H_i
// and compute the maximal ECs in H'_i // and compute the maximal ECs in H'_i
for (int i = 0; i < dra.acceptance().size(); i++) {
for (i = 0; i < dra.acceptance().size(); i++) {
// build the acceptance vectors H_i and L_i // build the acceptance vectors H_i and L_i
JDDNode acceptanceVector_H = JDD.Constant(0); JDDNode acceptanceVector_H = JDD.Constant(0);
JDDNode acceptanceVector_L = JDD.Constant(0); JDDNode acceptanceVector_L = JDD.Constant(0);
for (int j = 0; j < dra.size(); j++) {
/* [dA97] uses Rabin acceptance pairs (H_i, L_i) such that
* H_i contains Inf(ρ)
* The intersection of Inf(ρ) and L_i is non-empty
*
* OTOH ltl2dstar (and our port to java) uses pairs (L_i, U_i) such that
* The intersection of U_i and Inf(ρ) is empty (H_i = S - U_i)
* The intersection of L_i and Inf(ρ) is non-empty
for (j = 0; j < dra.size(); j++) {
/*
* [dA97] uses Rabin acceptance pairs (H_i, L_i) such that H_i contains Inf(ρ) The intersection of
* Inf(ρ) and L_i is non-empty
*
* OTOH ltl2dstar (and our port to java) uses pairs (L_i, U_i) such that The intersection of U_i and
* Inf(ρ) is empty (H_i = S - U_i) The intersection of L_i and Inf(ρ) is non-empty
*/ */
if (!dra.acceptance().isStateInAcceptance_U(i, j)) { if (!dra.acceptance().isStateInAcceptance_U(i, j)) {
acceptanceVector_H = JDD.SetVectorElement(acceptanceVector_H, draDDRowVars, j, 1.0); acceptanceVector_H = JDD.SetVectorElement(acceptanceVector_H, draDDRowVars, j, 1.0);
@ -367,7 +593,7 @@ public class LTLModelChecker
acceptanceVector_L = JDD.SetVectorElement(acceptanceVector_L, draDDRowVars, j, 1.0); acceptanceVector_L = JDD.SetVectorElement(acceptanceVector_L, draDDRowVars, j, 1.0);
} }
} }
// build bdd of accepting states (under H_i) in the product model // build bdd of accepting states (under H_i) in the product model
JDD.Ref(model.getTrans01()); JDD.Ref(model.getTrans01());
JDD.Ref(acceptanceVector_H); JDD.Ref(acceptanceVector_H);
@ -376,8 +602,7 @@ public class LTLModelChecker
candidateStates = JDD.Apply(JDD.TIMES, candidateStates, acceptanceVector_H); candidateStates = JDD.Apply(JDD.TIMES, candidateStates, acceptanceVector_H);
candidateStates = JDD.ThereExists(candidateStates, model.getAllDDColVars()); candidateStates = JDD.ThereExists(candidateStates, model.getAllDDColVars());
candidateStates = JDD.ThereExists(candidateStates, model.getAllDDNondetVars()); candidateStates = JDD.ThereExists(candidateStates, model.getAllDDNondetVars());
JDDNode acceptingStates;
if (fairness) { if (fairness) {
// compute the backward set of S x L_i // compute the backward set of S x L_i
JDD.Ref(candidateStates); JDD.Ref(candidateStates);
@ -385,40 +610,42 @@ public class LTLModelChecker
JDD.Ref(model.getTrans01()); JDD.Ref(model.getTrans01());
JDDNode edges = JDD.ThereExists(model.getTrans01(), model.getAllDDNondetVars()); JDDNode edges = JDD.ThereExists(model.getTrans01(), model.getAllDDNondetVars());
JDDNode filterStates = backwardSet(model, tmp, edges); JDDNode filterStates = backwardSet(model, tmp, edges);
// Filter out states that can't reach a state in L'_i // Filter out states that can't reach a state in L'_i
candidateStates = JDD.And(candidateStates, filterStates); candidateStates = JDD.And(candidateStates, filterStates);
// Find accepting states in S x H_i // Find accepting states in S x H_i
acceptingStates = findFairECs(model, candidateStates);
}
else {
acceptingStates = findFairECs(model, candidateStates);
} else {
// find ECs in acceptingStates that are accepting under L_i // find ECs in acceptingStates that are accepting under L_i
acceptingStates = filteredUnion(findEndComponents(model, candidateStates), acceptanceVector_L); acceptingStates = filteredUnion(findEndComponents(model, candidateStates), acceptanceVector_L);
} }
// Add states to our destination BDD // Add states to our destination BDD
allAcceptingStates = JDD.Or(allAcceptingStates, acceptingStates); allAcceptingStates = JDD.Or(allAcceptingStates, acceptingStates);
} }
return allAcceptingStates; return allAcceptingStates;
} }
/**
/**
* Returns all end components in candidateStates under fairness assumptions * Returns all end components in candidateStates under fairness assumptions
* @param candidateStates set of candidate states S x H_i
* (dereferenced after calling this function)
* @return a referenced BDD with the maximal stable set in c
*
* @param candidateStates
* set of candidate states S x H_i (dereferenced after calling this function)
* @return a referenced BDD with the maximal stable set in c
*/ */
private JDDNode findFairECs(NondetModel model, JDDNode candidateStates) {
private JDDNode findFairECs(NondetModel model, JDDNode candidateStates)
{
JDDNode old = JDD.Constant(0); JDDNode old = JDD.Constant(0);
JDDNode current = candidateStates; JDDNode current = candidateStates;
while (!current.equals(old)) { while (!current.equals(old)) {
JDD.Deref(old); JDD.Deref(old);
JDD.Ref(current); JDD.Ref(current);
old = current; old = current;
JDD.Ref(current); JDD.Ref(current);
JDD.Ref(model.getTrans01()); JDD.Ref(model.getTrans01());
// Select transitions starting in current // Select transitions starting in current
@ -436,11 +663,9 @@ public class LTLModelChecker
JDD.Deref(old); JDD.Deref(old);
return current; return current;
} }
/**
* Return the set of states that reach nodes through edges
* Refs: result
* Derefs: nodes, edges
/**
* Return the set of states that reach nodes through edges Refs: result Derefs: nodes, edges
*/ */
private JDDNode backwardSet(NondetModel model, JDDNode nodes, JDDNode edges) private JDDNode backwardSet(NondetModel model, JDDNode nodes, JDDNode edges)
{ {
@ -458,11 +683,9 @@ public class LTLModelChecker
JDD.Deref(old); JDD.Deref(old);
return current; return current;
} }
/**
* Return the preimage of nodes in edges
* Refs: result
* Derefs: edges, nodes
/**
* Return the preimage of nodes in edges Refs: result Derefs: edges, nodes
*/ */
// FIXME: Refactor this out (duplicated in SCCComputers) // FIXME: Refactor this out (duplicated in SCCComputers)
private JDDNode preimage(NondetModel model, JDDNode nodes, JDDNode edges) private JDDNode preimage(NondetModel model, JDDNode nodes, JDDNode edges)
@ -476,34 +699,37 @@ public class LTLModelChecker
tmp = JDD.ThereExists(tmp, model.getAllDDColVars()); tmp = JDD.ThereExists(tmp, model.getAllDDColVars());
return tmp; return tmp;
} }
/** /**
* Computes maximal accepting end components in states * Computes maximal accepting end components in states
* @param states BDD of a set of states (dereferenced after calling this function)
* @return a vector of referenced BDDs containing all the ECs in states
*
* @param states
* BDD of a set of states (dereferenced after calling this function)
* @return a vector of referenced BDDs containing all the ECs in states
*/ */
private Vector<JDDNode> findEndComponents(NondetModel model, JDDNode states) throws PrismException {
private Vector<JDDNode> findEndComponents(NondetModel model, JDDNode states) throws PrismException
{
boolean initialCandidate = true; boolean initialCandidate = true;
Stack<JDDNode> candidates = new Stack<JDDNode>(); Stack<JDDNode> candidates = new Stack<JDDNode>();
candidates.push(states); candidates.push(states);
Vector<JDDNode> ecs = new Vector<JDDNode>(); Vector<JDDNode> ecs = new Vector<JDDNode>();
SCCComputer sccComputer; SCCComputer sccComputer;
while (!candidates.isEmpty()) { while (!candidates.isEmpty()) {
JDDNode candidate = candidates.pop(); JDDNode candidate = candidates.pop();
// Compute the stable set // Compute the stable set
JDD.Ref(candidate); JDD.Ref(candidate);
JDDNode stableSet = findMaximalStableSet(model, candidate); JDDNode stableSet = findMaximalStableSet(model, candidate);
// Drop empty sets // Drop empty sets
if (stableSet.equals(JDD.ZERO)) { if (stableSet.equals(JDD.ZERO)) {
JDD.Deref(stableSet); JDD.Deref(stableSet);
JDD.Deref(candidate); JDD.Deref(candidate);
continue; continue;
} }
if (!initialCandidate) { if (!initialCandidate) {
// candidate is an SCC, check if it's stable // candidate is an SCC, check if it's stable
if (stableSet.equals(candidate)) { if (stableSet.equals(candidate)) {
@ -511,45 +737,46 @@ public class LTLModelChecker
JDD.Deref(stableSet); JDD.Deref(stableSet);
continue; continue;
} }
}
else {
} else {
initialCandidate = false; initialCandidate = false;
} }
JDD.Deref(candidate); JDD.Deref(candidate);
// Filter bad transitions // Filter bad transitions
JDD.Ref(stableSet); JDD.Ref(stableSet);
JDDNode stableSetTrans = maxStableSetTrans(model, stableSet); JDDNode stableSetTrans = maxStableSetTrans(model, stableSet);
// now find the maximal SCCs in (stableSet, stableSetTrans) // now find the maximal SCCs in (stableSet, stableSetTrans)
Vector<JDDNode> sccs; Vector<JDDNode> sccs;
sccComputer = prism.getSCCComputer(stableSet, stableSetTrans, model.getAllDDRowVars(), model.getAllDDColVars()); sccComputer = prism.getSCCComputer(stableSet, stableSetTrans, model.getAllDDRowVars(), model.getAllDDColVars());
sccComputer.computeBSCCs();
sccComputer.computeSCCs();
JDD.Deref(stableSet); JDD.Deref(stableSet);
JDD.Deref(stableSetTrans); JDD.Deref(stableSetTrans);
sccs = sccComputer.getVectBSCCs();
JDD.Deref(sccComputer.getNotInBSCCs());
sccs = sccComputer.getVectSCCs();
JDD.Deref(sccComputer.getNotInSCCs());
candidates.addAll(sccs); candidates.addAll(sccs);
} }
return ecs; return ecs;
} }
/**
/**
* Returns a stable set of states contained in candidateStates * Returns a stable set of states contained in candidateStates
* @param candidateStates set of candidate states S x H_i
* (dereferenced after calling this function)
* @return a referenced BDD with the maximal stable set in c
*
* @param candidateStates
* set of candidate states S x H_i (dereferenced after calling this function)
* @return a referenced BDD with the maximal stable set in c
*/ */
private JDDNode findMaximalStableSet(NondetModel model, JDDNode candidateStates) {
private JDDNode findMaximalStableSet(NondetModel model, JDDNode candidateStates)
{
JDDNode old = JDD.Constant(0); JDDNode old = JDD.Constant(0);
JDDNode current = candidateStates; JDDNode current = candidateStates;
while (!current.equals(old)) { while (!current.equals(old)) {
JDD.Deref(old); JDD.Deref(old);
JDD.Ref(current); JDD.Ref(current);
old = current; old = current;
JDD.Ref(current); JDD.Ref(current);
JDD.Ref(model.getTrans()); JDD.Ref(model.getTrans());
// Select transitions starting in current // Select transitions starting in current
@ -568,13 +795,16 @@ public class LTLModelChecker
JDD.Deref(old); JDD.Deref(old);
return current; return current;
} }
/** /**
* Returns the transition relation of a stable set * Returns the transition relation of a stable set
* @param b BDD of a stable set (dereferenced after calling this function)
* @return referenced BDD of the transition relation restricted to the stable set
*
* @param b
* BDD of a stable set (dereferenced after calling this function)
* @return referenced BDD of the transition relation restricted to the stable set
*/ */
private JDDNode maxStableSetTrans(NondetModel model, JDDNode b) {
private JDDNode maxStableSetTrans(NondetModel model, JDDNode b)
{
JDD.Ref(b); JDD.Ref(b);
JDD.Ref(model.getTrans()); JDD.Ref(model.getTrans());
@ -596,12 +826,14 @@ public class LTLModelChecker
} }
/** /**
* Returns the union of each set in the vector that has nonempty intersection
* with the filter BDD.
* @param sets Vector with sets which are dereferenced after calling this function
* @param filter filter BDD against which each set is checked for nonempty intersection
* also dereferenced after calling this function
* @return Referenced BDD with the filtered union
* Returns the union of each set in the vector that has nonempty intersection with the filter BDD.
*
* @param sets
* Vector with sets which are dereferenced after calling this function
* @param filter
* filter BDD against which each set is checked for nonempty intersection also dereferenced after calling
* this function
* @return Referenced BDD with the filtered union
*/ */
private JDDNode filteredUnion(Vector<JDDNode> sets, JDDNode filter) private JDDNode filteredUnion(Vector<JDDNode> sets, JDDNode filter)
{ {

19
prism/src/prism/NondetModelChecker.java

@ -400,13 +400,15 @@ public class NondetModelChecker extends NonProbModelChecker
} }
// For LTL model checking routines // For LTL model checking routines
mcLtl = new LTLModelChecker(prism, this);
mcLtl = new LTLModelChecker(prism);
// Model check maximal state formulas // Model check maximal state formulas
labelDDs = new Vector<JDDNode>(); labelDDs = new Vector<JDDNode>();
ltl = mcLtl.checkMaximalStateFormulas(model, expr.deepCopy(), labelDDs);
ltl = mcLtl.checkMaximalStateFormulas(this, model, expr.deepCopy(), labelDDs);
// Convert LTL formula to deterministic Rabin automaton (DRA) // Convert LTL formula to deterministic Rabin automaton (DRA)
// For min probabilities, need to negate the formula
// (But check fairness setting since this may affect min/max)
mainLog.println("\nBuilding deterministic Rabin automaton (for " + (min && !fairness ? "!" : "") + ltl + ")..."); mainLog.println("\nBuilding deterministic Rabin automaton (for " + (min && !fairness ? "!" : "") + ltl + ")...");
l = System.currentTimeMillis(); l = System.currentTimeMillis();
if (min && !fairness) { if (min && !fairness) {
@ -414,22 +416,24 @@ public class NondetModelChecker extends NonProbModelChecker
} else { } else {
dra = LTL2Rabin.ltl2rabin(ltl.convertForJltl2ba()); dra = LTL2Rabin.ltl2rabin(ltl.convertForJltl2ba());
} }
mainLog.println("\nDRA has " + dra.size() + " states.");
mainLog.println("\nDRA has " + dra.size() + " states, " + dra.acceptance().size() + " pairs.");
// dra.print(System.out); // dra.print(System.out);
l = System.currentTimeMillis() - l; l = System.currentTimeMillis() - l;
mainLog.println("\nTime for Rabin translation: " + l / 1000.0 + " seconds."); mainLog.println("\nTime for Rabin translation: " + l / 1000.0 + " seconds.");
// Build product of MDP and automaton // Build product of MDP and automaton
mainLog.println("\nConstructing Model-DRA product...");
modelProduct = mcLtl.constructProductModel(dra, model, labelDDs);
mainLog.println("\nConstructing MDP-DRA product...");
modelProduct = mcLtl.constructProductMDP(dra, model, labelDDs);
mainLog.println(); mainLog.println();
modelProduct.printTransInfo(mainLog, prism.getExtraDDInfo()); modelProduct.printTransInfo(mainLog, prism.getExtraDDInfo());
// prism.exportStatesToFile(modelProduct, Prism.EXPORT_PLAIN, null); // prism.exportStatesToFile(modelProduct, Prism.EXPORT_PLAIN, null);
// prism.exportTransToFile(modelProduct, true, Prism.EXPORT_PLAIN, null); // prism.exportTransToFile(modelProduct, true, Prism.EXPORT_PLAIN, null);
// Find accepting maximum end components
mainLog.println("\nFinding accepting end components..."); mainLog.println("\nFinding accepting end components...");
JDDNode acc = mcLtl.findAcceptingStates(dra, modelProduct, fairness); JDDNode acc = mcLtl.findAcceptingStates(dra, modelProduct, fairness);
// Compute reachability probabilities
mainLog.println("\nComputing reachability probabilities..."); mainLog.println("\nComputing reachability probabilities...");
mcProduct = new NondetModelChecker(prism, modelProduct, null); mcProduct = new NondetModelChecker(prism, modelProduct, null);
probsProduct = mcProduct.checkProbUntil(modelProduct.getReach(), acc, qual, min && fairness); probsProduct = mcProduct.checkProbUntil(modelProduct.getReach(), acc, qual, min && fairness);
@ -441,9 +445,10 @@ public class NondetModelChecker extends NonProbModelChecker
// Convert probability vector to original model // Convert probability vector to original model
// First, filter over DRA start states // First, filter over DRA start states
startMask = mcLtl.buildStartMask(dra, labelDDs);
// (which we can get from initial states of product model,
// because of the way it is constructed)
startMask = modelProduct.getStart();
probsProduct.filter(startMask); probsProduct.filter(startMask);
JDD.Deref(startMask);
// Then sum over DD vars for the DRA state // Then sum over DD vars for the DRA state
draDDRowVars = new JDDVars(); draDDRowVars = new JDDVars();
draDDRowVars.addVars(modelProduct.getAllDDRowVars()); draDDRowVars.addVars(modelProduct.getAllDDRowVars());

153
prism/src/prism/ProbModelChecker.java

@ -29,19 +29,22 @@ package prism;
import java.util.Vector; import java.util.Vector;
import jdd.*; import jdd.*;
import jltl2dstar.DRA;
import jltl2dstar.LTL2Rabin;
import dv.*; import dv.*;
import mtbdd.*; import mtbdd.*;
import sparse.*; import sparse.*;
import hybrid.*; import hybrid.*;
import parser.ast.*; import parser.ast.*;
import parser.visitor.ASTTraverse;
/* /*
* Model checker for DTMCs. * Model checker for DTMCs.
*/ */
public class ProbModelChecker extends NonProbModelChecker public class ProbModelChecker extends NonProbModelChecker
{ {
// SCC computer
protected SCCComputer sccComputer;
// Model (DTMC or CTMC)
protected ProbModel model;
// Options (in addition to those inherited from StateModelChecker): // Options (in addition to those inherited from StateModelChecker):
@ -56,9 +59,10 @@ public class ProbModelChecker extends NonProbModelChecker
{ {
// Initialise // Initialise
super(prism, m, pf); super(prism, m, pf);
// Create SCCComputer object
sccComputer = prism.getSCCComputer(m);
if (!(m instanceof ProbModel)) {
throw new PrismException("Wrong model type passed to ProbModelChecker.");
}
model = (ProbModel) m;
// Inherit some options from parent Prism object. // Inherit some options from parent Prism object.
// Store locally and/or pass onto engines. // Store locally and/or pass onto engines.
@ -96,6 +100,13 @@ public class ProbModelChecker extends NonProbModelChecker
} }
} }
// Override-able "Constructor"
public ProbModelChecker createNewModelChecker(Prism prism, Model m, PropertiesFile pf) throws PrismException
{
return new ProbModelChecker(prism, m, pf);
}
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Check a property, i.e. an expression // Check a property, i.e. an expression
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
@ -350,6 +361,7 @@ public class ProbModelChecker extends NonProbModelChecker
// compute bottom strongly connected components (bsccs) // compute bottom strongly connected components (bsccs)
if (bsccComp) { if (bsccComp) {
SCCComputer sccComputer = prism.getSCCComputer(model);
sccComputer.computeBSCCs(); sccComputer.computeBSCCs();
vectBSCCs = sccComputer.getVectBSCCs(); vectBSCCs = sccComputer.getVectBSCCs();
notInBSCCs = sccComputer.getNotInBSCCs(); notInBSCCs = sccComputer.getNotInBSCCs();
@ -512,7 +524,8 @@ public class ProbModelChecker extends NonProbModelChecker
if (expr.isSimplePathFormula()) { if (expr.isSimplePathFormula()) {
return checkProbPathFormulaSimple(expr, qual); return checkProbPathFormulaSimple(expr, qual);
} else { } else {
throw new PrismException("LTL-style path formulas are not yet supported");
return checkProbPathFormulaLTL(expr, qual);
//throw new PrismException("LTL-style path formulas are not yet supported");
} }
} }
@ -562,6 +575,97 @@ public class ProbModelChecker extends NonProbModelChecker
return probs; return probs;
} }
// LTL-like path formula for P operator
protected StateProbs checkProbPathFormulaLTL(Expression expr, boolean qual) throws PrismException
{
LTLModelChecker mcLtl;
StateProbs probsProduct = null, probs = null;
Expression ltl;
Vector<JDDNode> labelDDs;
DRA dra;
ProbModel modelProduct;
ProbModelChecker mcProduct;
JDDNode startMask;
JDDVars draDDRowVars;
int i;
long l;
// Can't do LTL with time-bounded variants of the temporal operators
try {
expr.accept(new ASTTraverse()
{
public void visitPre(ExpressionTemporal e) throws PrismLangException
{
if (e.getLowerBound() != null)
throw new PrismLangException(e.getOperatorSymbol());
if (e.getUpperBound() != null)
throw new PrismLangException(e.getOperatorSymbol());
}
});
} catch (PrismLangException e) {
String s = "Temporal operators (like " + e.getMessage() + ")";
s += " cannot have time bounds for LTL properties";
throw new PrismException(s);
}
// For LTL model checking routines
mcLtl = new LTLModelChecker(prism);
// Model check maximal state formulas
labelDDs = new Vector<JDDNode>();
ltl = mcLtl.checkMaximalStateFormulas(this, model, expr.deepCopy(), labelDDs);
// Convert LTL formula to deterministic Rabin automaton (DRA)
mainLog.println("\nBuilding deterministic Rabin automaton (for " + ltl + ")...");
l = System.currentTimeMillis();
dra = LTL2Rabin.ltl2rabin(ltl.convertForJltl2ba());
mainLog.println("\nDRA has " + dra.size() + " states, " + dra.acceptance().size() + " pairs.");
// dra.print(System.out);
l = System.currentTimeMillis() - l;
mainLog.println("\nTime for Rabin translation: " + l / 1000.0 + " seconds.");
// Build product of Markov chain and automaton
// (note: might be a CTMC - StochModelChecker extends this class)
mainLog.println("\nConstructing MC-DRA product...");
modelProduct = mcLtl.constructProductMC(dra, model, labelDDs);
mainLog.println();
modelProduct.printTransInfo(mainLog, prism.getExtraDDInfo());
// prism.exportStatesToFile(modelProduct, Prism.EXPORT_PLAIN, null);
// prism.exportTransToFile(modelProduct, true, Prism.EXPORT_PLAIN, null);
// Find accepting maximum end BSCC
mainLog.println("\nFinding accepting BSCCs...");
JDDNode acc = mcLtl.findAcceptingBSCCs(dra, modelProduct);
// Compute reachability probabilities
mainLog.println("\nComputing reachability probabilities...");
mcProduct = createNewModelChecker(prism, modelProduct, null);
probsProduct = mcProduct.checkProbUntil(modelProduct.getReach(), acc, qual);
// Convert probability vector to original model
// First, filter over DRA start states
// (which we can get from initial states of product model,
// because of the way it is constructed)
startMask = modelProduct.getStart();
probsProduct.filter(startMask);
// Then sum over DD vars for the DRA state
draDDRowVars = new JDDVars();
draDDRowVars.addVars(modelProduct.getAllDDRowVars());
draDDRowVars.removeVars(allDDRowVars);
probs = probsProduct.sumOverDDVars(draDDRowVars, model);
// Deref, clean up
probsProduct.clear();
modelProduct.clear();
for (i = 0; i < labelDDs.size(); i++) {
JDD.Deref(labelDDs.get(i));
}
JDD.Deref(acc);
return probs;
}
// next // next
protected StateProbs checkProbNext(ExpressionTemporal expr) throws PrismException protected StateProbs checkProbNext(ExpressionTemporal expr) throws PrismException
@ -640,6 +744,8 @@ public class ProbModelChecker extends NonProbModelChecker
// until (unbounded) // until (unbounded)
// this method is split into two steps so that the LTL model checker can use the second part directly
protected StateProbs checkProbUntil(ExpressionTemporal expr, boolean qual) throws PrismException protected StateProbs checkProbUntil(ExpressionTemporal expr, boolean qual) throws PrismException
{ {
JDDNode b1, b2; JDDNode b1, b2;
@ -660,6 +766,27 @@ public class ProbModelChecker extends NonProbModelChecker
// mainLog.print(" states, b2 = " + JDD.GetNumMintermsString(b2, // mainLog.print(" states, b2 = " + JDD.GetNumMintermsString(b2,
// allDDRowVars.n()) + " states\n"); // allDDRowVars.n()) + " states\n");
try {
probs = checkProbUntil(b1, b2, qual);
} catch (PrismException e) {
JDD.Deref(b1);
JDD.Deref(b2);
throw e;
}
// derefs
JDD.Deref(b1);
JDD.Deref(b2);
return probs;
}
// until (unbounded): b1/b2 are bdds for until operands
protected StateProbs checkProbUntil(JDDNode b1, JDDNode b2, boolean qual) throws PrismException
{
StateProbs probs = null;
// compute probabilities // compute probabilities
// if requested (i.e. when 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),
@ -671,19 +798,9 @@ public class ProbModelChecker extends NonProbModelChecker
} }
// otherwise actually compute probabilities // otherwise actually compute probabilities
else { else {
try {
probs = computeUntilProbs(trans, trans01, b1, b2);
} catch (PrismException e) {
JDD.Deref(b1);
JDD.Deref(b2);
throw e;
}
probs = computeUntilProbs(trans, trans01, b1, b2);
} }
// derefs
JDD.Deref(b1);
JDD.Deref(b2);
return probs; return probs;
} }
@ -795,6 +912,7 @@ public class ProbModelChecker extends NonProbModelChecker
// compute bottom strongly connected components (bsccs) // compute bottom strongly connected components (bsccs)
if (bsccComp) { if (bsccComp) {
SCCComputer sccComputer = prism.getSCCComputer(model);
sccComputer.computeBSCCs(); sccComputer.computeBSCCs();
vectBSCCs = sccComputer.getVectBSCCs(); vectBSCCs = sccComputer.getVectBSCCs();
notInBSCCs = sccComputer.getNotInBSCCs(); notInBSCCs = sccComputer.getNotInBSCCs();
@ -940,6 +1058,7 @@ public class ProbModelChecker extends NonProbModelChecker
// compute bottom strongly connected components (bsccs) // compute bottom strongly connected components (bsccs)
if (bsccComp) { if (bsccComp) {
SCCComputer sccComputer = prism.getSCCComputer(model);
sccComputer.computeBSCCs(); sccComputer.computeBSCCs();
vectBSCCs = sccComputer.getVectBSCCs(); vectBSCCs = sccComputer.getVectBSCCs();
notInBSCCs = sccComputer.getNotInBSCCs(); notInBSCCs = sccComputer.getNotInBSCCs();

7
prism/src/prism/StochModelChecker.java

@ -63,6 +63,13 @@ public class StochModelChecker extends ProbModelChecker
super(prism, m, pf); super(prism, m, pf);
} }
// Override-able "Constructor"
public ProbModelChecker createNewModelChecker(Prism prism, Model m, PropertiesFile pf) throws PrismException
{
return new StochModelChecker(prism, m, pf);
}
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Check method for each operator // Check method for each operator
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------

Loading…
Cancel
Save