|
|
@ -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) |
|
|
{ |
|
|
{ |
|
|
|