Browse Source

First version of explicit expression evaluation stuff (all but functions).

git-svn-id: https://www.prismmodelchecker.org/svn/prism/prism/trunk@722 bbc10eb1-c90d-0410-af57-cb519fbb1720
master
Dave Parker 19 years ago
parent
commit
feacf0c238
  1. 16
      prism/include/DoubleVector.h
  2. 38
      prism/src/dv/DoubleVector.cc
  3. 19
      prism/src/dv/DoubleVector.java
  4. 266
      prism/src/prism/StateModelChecker.java
  5. 2
      prism/src/prism/StateProbs.java
  6. 22
      prism/src/prism/StateProbsDV.java
  7. 20
      prism/src/prism/StateProbsMTBDD.java

16
prism/include/DoubleVector.h

@ -39,6 +39,14 @@ JNIEXPORT jlong JNICALL Java_dv_DoubleVector_DV_1ConvertMTBDD
JNIEXPORT jdouble JNICALL Java_dv_DoubleVector_DV_1GetElement JNIEXPORT jdouble JNICALL Java_dv_DoubleVector_DV_1GetElement
(JNIEnv *, jobject, jlong, jint, jint); (JNIEnv *, jobject, jlong, jint, jint);
/*
* Class: dv_DoubleVector
* Method: DV_SetElement
* Signature: (JIID)V
*/
JNIEXPORT void JNICALL Java_dv_DoubleVector_DV_1SetElement
(JNIEnv *, jobject, jlong, jint, jint, jdouble);
/* /*
* Class: dv_DoubleVector * Class: dv_DoubleVector
* Method: DV_RoundOff * Method: DV_RoundOff
@ -175,6 +183,14 @@ JNIEXPORT jlong JNICALL Java_dv_DoubleVector_DV_1BDDLessThan
JNIEXPORT jlong JNICALL Java_dv_DoubleVector_DV_1BDDInterval JNIEXPORT jlong JNICALL Java_dv_DoubleVector_DV_1BDDInterval
(JNIEnv *, jobject, jlong, jdouble, jdouble, jlong, jint, jlong); (JNIEnv *, jobject, jlong, jdouble, jdouble, jlong, jint, jlong);
/*
* Class: dv_DoubleVector
* Method: DV_ConvertToMTBDD
* Signature: (JJIJ)J
*/
JNIEXPORT jlong JNICALL Java_dv_DoubleVector_DV_1ConvertToMTBDD
(JNIEnv *, jobject, jlong, jlong, jint, jlong);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

38
prism/src/dv/DoubleVector.cc

@ -110,6 +110,22 @@ jint i
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
JNIEXPORT void JNICALL Java_dv_DoubleVector_DV_1SetElement
(
JNIEnv *env,
jobject obj,
jlong __pointer v,
jint n,
jint i,
jdouble d
)
{
double *vector = jlong_to_double(v);
vector[i] = d;
}
//------------------------------------------------------------------------------
JNIEXPORT void JNICALL Java_dv_DoubleVector_DV_1RoundOff JNIEXPORT void JNICALL Java_dv_DoubleVector_DV_1RoundOff
( (
JNIEnv *env, JNIEnv *env,
@ -482,3 +498,25 @@ jlong __pointer odd
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
JNIEXPORT jlong __pointer JNICALL Java_dv_DoubleVector_DV_1ConvertToMTBDD
(
JNIEnv *env,
jobject obj,
jlong __pointer vector,
jlong __pointer vars,
jint num_vars,
jlong __pointer odd
)
{
return ptr_to_jlong(
double_vector_to_mtbdd(
ddman,
jlong_to_double(vector),
jlong_to_DdNode_array(vars), num_vars,
jlong_to_ODDNode(odd)
)
);
}
//------------------------------------------------------------------------------

19
prism/src/dv/DoubleVector.java

@ -110,6 +110,13 @@ public class DoubleVector
return DV_GetElement(v, n, i); return DV_GetElement(v, n, i);
} }
// set element
private native void DV_SetElement(long v, int n, int i, double d);
public void setElement(int i, double d)
{
DV_SetElement(v, n, i, d);
}
// round off // round off
private native void DV_RoundOff(long v, int n, int places); private native void DV_RoundOff(long v, int n, int places);
public void roundOff(int places) public void roundOff(int places)
@ -241,6 +248,18 @@ public class DoubleVector
return sol; return sol;
} }
private native long DV_ConvertToMTBDD(long v, long vars, int num_vars, long odd);
public JDDNode convertToMTBDD(JDDVars vars, ODDNode odd)
{
JDDNode sol;
sol = new JDDNode(
DV_ConvertToMTBDD(v, vars.array(), vars.n(), odd.ptr())
);
return sol;
}
// print (all, including nonzeros) // print (all, including nonzeros)
public void print(PrismLog log) public void print(PrismLog log)
{ {

266
prism/src/prism/StateModelChecker.java

@ -26,6 +26,7 @@
package prism; package prism;
import dv.DoubleVector;
import jdd.*; import jdd.*;
import odd.*; import odd.*;
import parser.*; import parser.*;
@ -328,22 +329,55 @@ public class StateModelChecker implements ModelChecker
private StateProbs checkExpressionITE(ExpressionITE expr) throws PrismException private StateProbs checkExpressionITE(ExpressionITE expr) throws PrismException
{ {
StateProbs res1 = null, res2 = null, res3 = null;
JDDNode dd, dd1, dd2, dd3; JDDNode dd, dd1, dd2, dd3;
dd1 = checkExpressionDD(expr.getOperand1());
dd2 = checkExpressionDD(expr.getOperand2());
dd3 = checkExpressionDD(expr.getOperand3());
dd = JDD.ITE(dd1, dd2, dd3);
return new StateProbsMTBDD(dd, model);
DoubleVector dv2, dv3;
// Check operands recursively
try {
res1 = checkExpression(expr.getOperand1());
res2 = checkExpression(expr.getOperand2());
res3 = checkExpression(expr.getOperand3());
}
catch (PrismException e) {
if (res1 != null) res1.clear();
if (res2 != null) res2.clear();
if (res3 != null) res3.clear();
throw e;
}
// Operand 1 is boolean so should be symbolic
dd1 = res1.convertToStateProbsMTBDD().getJDDNode();
// If both operands 2/3 are symbolic, result will be symbolic
if (res2 instanceof StateProbsMTBDD && res3 instanceof StateProbsMTBDD) {
dd2 = ((StateProbsMTBDD)res2).getJDDNode();
dd3 = ((StateProbsMTBDD)res3).getJDDNode();
dd = JDD.ITE(dd1, dd2, dd3);
return new StateProbsMTBDD(dd, model);
}
// Otherwise result will be explicit
else {
dv2 = res2.convertToStateProbsDV().getDoubleVector();
dv2.filter(dd1, allDDRowVars, odd);
dv3 = res3.convertToStateProbsDV().getDoubleVector();
dd1 = JDD.Not(dd1);
dv3.filter(dd1, allDDRowVars, odd);
dv2.add(dv3);
dv3.clear();
JDD.Deref(dd1);
return new StateProbsDV(dv2, model);
}
} }
// Check a binary operator // Check a binary operator
private StateProbs checkExpressionBinaryOp(ExpressionBinaryOp expr) throws PrismException private StateProbs checkExpressionBinaryOp(ExpressionBinaryOp expr) throws PrismException
{ {
JDDNode dd, tmp1, tmp2;
int op = expr.getOperator();
StateProbs res1 = null, res2 = null;
JDDNode dd, dd1, dd2;
DoubleVector dv1, dv2;
int i, n, op = expr.getOperator();
// Optimisations are possible for relational operators // Optimisations are possible for relational operators
// (note dubious use of knowledge that op IDs are consecutive) // (note dubious use of knowledge that op IDs are consecutive)
@ -351,53 +385,92 @@ public class StateModelChecker implements ModelChecker
return checkExpressionRelOp(op, expr.getOperand1(), expr.getOperand2()); return checkExpressionRelOp(op, expr.getOperand1(), expr.getOperand2());
} }
// Check operands
tmp1 = checkExpressionDD(expr.getOperand1());
// Check operands recursively
try { try {
tmp2 = checkExpressionDD(expr.getOperand2());
} catch (PrismException e) {
JDD.Deref(tmp1);
res1 = checkExpression(expr.getOperand1());
res2 = checkExpression(expr.getOperand2());
}
catch (PrismException e) {
if (res1 != null) res1.clear();
if (res2 != null) res2.clear();
throw e; throw e;
} }
// Apply operation
switch (op) {
case ExpressionBinaryOp.IMPLIES:
dd = JDD.Or(JDD.Not(tmp1), tmp2);
break;
case ExpressionBinaryOp.OR:
dd = JDD.Or(tmp1, tmp2);
break;
case ExpressionBinaryOp.AND:
dd = JDD.And(tmp1, tmp2);
break;
case ExpressionBinaryOp.PLUS:
dd = JDD.Apply(JDD.PLUS, tmp1, tmp2);
break;
case ExpressionBinaryOp.MINUS:
dd = JDD.Apply(JDD.MINUS, tmp1, tmp2);
break;
case ExpressionBinaryOp.TIMES:
dd = JDD.Apply(JDD.TIMES, tmp1, tmp2);
break;
case ExpressionBinaryOp.DIVIDE:
dd = JDD.Apply(JDD.DIVIDE, tmp1, tmp2);
break;
default:
throw new PrismException("Unknown binary operator");
// If both operands are symbolic, result will be symbolic
if (res1 instanceof StateProbsMTBDD && res2 instanceof StateProbsMTBDD) {
dd1 = ((StateProbsMTBDD)res1).getJDDNode();
dd2 = ((StateProbsMTBDD)res2).getJDDNode();
// Apply operation
switch (op) {
case ExpressionBinaryOp.IMPLIES:
dd = JDD.Or(JDD.Not(dd1), dd2);
break;
case ExpressionBinaryOp.OR:
dd = JDD.Or(dd1, dd2);
break;
case ExpressionBinaryOp.AND:
dd = JDD.And(dd1, dd2);
break;
case ExpressionBinaryOp.PLUS:
dd = JDD.Apply(JDD.PLUS, dd1, dd2);
break;
case ExpressionBinaryOp.MINUS:
dd = JDD.Apply(JDD.MINUS, dd1, dd2);
break;
case ExpressionBinaryOp.TIMES:
dd = JDD.Apply(JDD.TIMES, dd1, dd2);
break;
case ExpressionBinaryOp.DIVIDE:
dd = JDD.Apply(JDD.DIVIDE, dd1, dd2);
break;
default:
throw new PrismException("Unknown binary operator");
}
return new StateProbsMTBDD(dd, model);
}
// Otherwise result will be explicit
else {
dv1 = res1.convertToStateProbsDV().getDoubleVector();
dv2 = res2.convertToStateProbsDV().getDoubleVector();
n = dv1.getSize();
// Apply operation
switch (op) {
case ExpressionBinaryOp.IMPLIES:
case ExpressionBinaryOp.OR:
case ExpressionBinaryOp.AND:
throw new PrismException("Internal error: Explicit evaluation of Boolean");
//for (i = 0; i < n; i++) dv1.setElement(i, (!(dv1.getElement(i)>0) || (dv2.getElement(i)>0)) ? 1.0 : 0.0);
//for (i = 0; i < n; i++) dv1.setElement(i, ((dv1.getElement(i)>0) || (dv2.getElement(i)>0)) ? 1.0 : 0.0);
//for (i = 0; i < n; i++) dv1.setElement(i, ((dv1.getElement(i)>0) && (dv2.getElement(i)>0)) ? 1.0 : 0.0);
case ExpressionBinaryOp.PLUS:
for (i = 0; i < n; i++) dv1.setElement(i, dv1.getElement(i) + dv2.getElement(i));
break;
case ExpressionBinaryOp.MINUS:
for (i = 0; i < n; i++) dv1.setElement(i, dv1.getElement(i) - dv2.getElement(i));
break;
case ExpressionBinaryOp.TIMES:
for (i = 0; i < n; i++) dv1.setElement(i, dv1.getElement(i) * dv2.getElement(i));
break;
case ExpressionBinaryOp.DIVIDE:
for (i = 0; i < n; i++) dv1.setElement(i, dv1.getElement(i) / dv2.getElement(i));
break;
default:
throw new PrismException("Unknown binary operator");
}
dv2.clear();
return new StateProbsDV(dv1, model);
} }
return new StateProbsMTBDD(dd, model);
} }
// Check a relational operator (=, !=, >, >=, < <=) // Check a relational operator (=, !=, >, >=, < <=)
private StateProbs checkExpressionRelOp(int op, Expression expr1, Expression expr2) throws PrismException private StateProbs checkExpressionRelOp(int op, Expression expr1, Expression expr2) throws PrismException
{ {
JDDNode dd, tmp1, tmp2;
StateProbs res1 = null, res2 = null;
JDDNode dd, dd1, dd2;
String s; String s;
// check for some easy (and common) special cases before resorting to
// Check for some easy (and common) special cases before resorting to
// the general case // the general case
// var relop int // var relop int
@ -501,32 +574,43 @@ public class StateModelChecker implements ModelChecker
return new StateProbsMTBDD(dd, model); return new StateProbsMTBDD(dd, model);
} }
// general case
tmp1 = checkExpressionDD(expr1);
tmp2 = checkExpressionDD(expr2);
// General case.
// Since the result is a Boolean and thus returned as an MTBDD, we
// just convert both operands to MTBDDs first. Optimisations would be possible here.
// Check operands recursively
try {
res1 = checkExpression(expr1);
res2 = checkExpression(expr2);
}
catch (PrismException e) {
if (res1 != null) res1.clear();
if (res2 != null) res2.clear();
throw e;
}
dd1 = res1.convertToStateProbsMTBDD().getJDDNode();
dd2 = res2.convertToStateProbsMTBDD().getJDDNode();
switch (op) { switch (op) {
case ExpressionBinaryOp.EQ: case ExpressionBinaryOp.EQ:
dd = JDD.Apply(JDD.EQUALS, tmp1, tmp2);
dd = JDD.Apply(JDD.EQUALS, dd1, dd2);
break; break;
case ExpressionBinaryOp.NE: case ExpressionBinaryOp.NE:
dd = JDD.Apply(JDD.NOTEQUALS, tmp1, tmp2);
dd = JDD.Apply(JDD.NOTEQUALS, dd1, dd2);
break; break;
case ExpressionBinaryOp.GT: case ExpressionBinaryOp.GT:
dd = JDD.Apply(JDD.GREATERTHAN, tmp1, tmp2);
dd = JDD.Apply(JDD.GREATERTHAN, dd1, dd2);
break; break;
case ExpressionBinaryOp.GE: case ExpressionBinaryOp.GE:
dd = JDD.Apply(JDD.GREATERTHANEQUALS, tmp1, tmp2);
dd = JDD.Apply(JDD.GREATERTHANEQUALS, dd1, dd2);
break; break;
case ExpressionBinaryOp.LT: case ExpressionBinaryOp.LT:
dd = JDD.Apply(JDD.LESSTHAN, tmp1, tmp2);
dd = JDD.Apply(JDD.LESSTHAN, dd1, dd2);
break; break;
case ExpressionBinaryOp.LE: case ExpressionBinaryOp.LE:
dd = JDD.Apply(JDD.LESSTHANEQUALS, tmp1, tmp2);
dd = JDD.Apply(JDD.LESSTHANEQUALS, dd1, dd2);
break; break;
default: default:
throw new PrismException("Unknown relational operator"); throw new PrismException("Unknown relational operator");
} }
return new StateProbsMTBDD(dd, model); return new StateProbsMTBDD(dd, model);
} }
@ -534,28 +618,56 @@ public class StateModelChecker implements ModelChecker
private StateProbs checkExpressionUnaryOp(ExpressionUnaryOp expr) throws PrismException private StateProbs checkExpressionUnaryOp(ExpressionUnaryOp expr) throws PrismException
{ {
JDDNode dd, tmp;
int op = expr.getOperator();
// Check operand
tmp = checkExpressionDD(expr.getOperand());
StateProbs res1 = null;
JDDNode dd, dd1;
DoubleVector dv1;
int i, n, op = expr.getOperator();
// Apply operation
switch (op) {
case ExpressionUnaryOp.NOT:
dd = JDD.Not(tmp);
break;
case ExpressionUnaryOp.MINUS:
dd = JDD.Apply(JDD.MINUS, JDD.Constant(0), tmp);
break;
case ExpressionUnaryOp.PARENTH:
dd = tmp;
break;
default:
throw new PrismException("Unknown unary operator");
// Check operand recursively
try {
res1 = checkExpression(expr.getOperand());
}
catch (PrismException e) {
if (res1 != null) res1.clear();
throw e;
}
// Parentheses are easy - nothing to do:
if (op == ExpressionUnaryOp.PARENTH) return res1;
// If operand is symbolic, result will be symbolic
if (res1 instanceof StateProbsMTBDD) {
dd1 = ((StateProbsMTBDD)res1).getJDDNode();
// Apply operation
switch (op) {
case ExpressionUnaryOp.NOT:
dd = JDD.Not(dd1);
break;
case ExpressionUnaryOp.MINUS:
dd = JDD.Apply(JDD.MINUS, JDD.Constant(0), dd1);
break;
default:
throw new PrismException("Unknown unary operator");
}
return new StateProbsMTBDD(dd, model);
}
// Otherwise result will be explicit
else {
dv1 = res1.convertToStateProbsDV().getDoubleVector();
n = dv1.getSize();
// Apply operation
switch (op) {
case ExpressionUnaryOp.NOT:
throw new PrismException("Internal error: Explicit evaluation of Boolean");
//for (i = 0; i < n; i++) dv1.setElement(i, (dv1.getElement(i)>0) ? 0.0 : 1.0);
case ExpressionUnaryOp.MINUS:
for (i = 0; i < n; i++) dv1.setElement(i, -dv1.getElement(i));
break;
default:
throw new PrismException("Unknown unary operator");
}
return new StateProbsDV(dv1, model);
} }
return new StateProbsMTBDD(dd, model);
} }
// Check a 'function' // Check a 'function'
@ -761,9 +873,11 @@ public class StateModelChecker implements ModelChecker
if (expr.getName().equals("deadlock")) { if (expr.getName().equals("deadlock")) {
dd = model.getFixedDeadlocks(); dd = model.getFixedDeadlocks();
JDD.Ref(dd); JDD.Ref(dd);
return new StateProbsMTBDD(dd, model);
} else if (expr.getName().equals("init")) { } else if (expr.getName().equals("init")) {
dd = start; dd = start;
JDD.Ref(dd); JDD.Ref(dd);
return new StateProbsMTBDD(dd, model);
} else { } else {
// get expression associated with label // get expression associated with label
ll = propertiesFile.getCombinedLabelList(); ll = propertiesFile.getCombinedLabelList();
@ -771,10 +885,8 @@ public class StateModelChecker implements ModelChecker
if (i == -1) if (i == -1)
throw new PrismException("Unknown label \"" + expr.getName() + "\" in property"); throw new PrismException("Unknown label \"" + expr.getName() + "\" in property");
// check recursively // check recursively
dd = checkExpressionDD(ll.getLabel(i));
return checkExpression(ll.getLabel(i));
} }
return new StateProbsMTBDD(dd, model);
} }
} }

2
prism/src/prism/StateProbs.java

@ -32,6 +32,8 @@ import jdd.JDDNode;
public interface StateProbs public interface StateProbs
{ {
StateProbsDV convertToStateProbsDV();
StateProbsMTBDD convertToStateProbsMTBDD();
void roundOff(int places); void roundOff(int places);
void subtractFromOne(); void subtractFromOne();
void add(StateProbs sp); void add(StateProbs sp);

22
prism/src/prism/StateProbsDV.java

@ -40,6 +40,7 @@ public class StateProbsDV implements StateProbs
DoubleVector probs; DoubleVector probs;
// info from model // info from model
Model model;
JDDVars vars; JDDVars vars;
int numVars; int numVars;
ODDNode odd; ODDNode odd;
@ -57,7 +58,7 @@ public class StateProbsDV implements StateProbs
// CONSTRUCTORS // CONSTRUCTORS
public StateProbsDV(DoubleVector p, Model model)
public StateProbsDV(DoubleVector p, Model m)
{ {
int i; int i;
@ -65,6 +66,7 @@ public class StateProbsDV implements StateProbs
probs = p; probs = p;
// get info from model // get info from model
model = m;
vars = model.getAllDDRowVars(); vars = model.getAllDDRowVars();
numVars = vars.n(); numVars = vars.n();
odd = model.getODD(); odd = model.getODD();
@ -83,7 +85,23 @@ public class StateProbsDV implements StateProbs
// construct double vector from an mtbdd // construct double vector from an mtbdd
this(new DoubleVector(dd, model.getAllDDRowVars(), model.getODD()), model); this(new DoubleVector(dd, model.getAllDDRowVars(), model.getODD()), model);
} }
// CONVERSION METHODS
// convert to StateProbsDV (nothing to do)
public StateProbsDV convertToStateProbsDV()
{
return this;
}
// convert to StateProbsMTBDD, destroy (clear) old vector
public StateProbsMTBDD convertToStateProbsMTBDD()
{
StateProbsMTBDD res = new StateProbsMTBDD(probs.convertToMTBDD(vars, odd), model);
clear();
return res;
}
// METHODS TO MODIFY VECTOR // METHODS TO MODIFY VECTOR
// round // round

20
prism/src/prism/StateProbsMTBDD.java

@ -39,6 +39,7 @@ public class StateProbsMTBDD implements StateProbs
JDDNode probs; JDDNode probs;
// info from model // info from model
Model model;
JDDVars vars; JDDVars vars;
JDDNode reach; JDDNode reach;
int numDDRowVars; int numDDRowVars;
@ -57,7 +58,7 @@ public class StateProbsMTBDD implements StateProbs
// CONSTRUCTOR // CONSTRUCTOR
public StateProbsMTBDD(JDDNode p, Model model)
public StateProbsMTBDD(JDDNode p, Model m)
{ {
int i; int i;
@ -65,6 +66,7 @@ public class StateProbsMTBDD implements StateProbs
probs = p; probs = p;
// get info from model // get info from model
model = m;
vars = model.getAllDDRowVars(); vars = model.getAllDDRowVars();
reach = model.getReach(); reach = model.getReach();
numDDRowVars = model.getNumDDRowVars(); numDDRowVars = model.getNumDDRowVars();
@ -80,6 +82,22 @@ public class StateProbsMTBDD implements StateProbs
varValues = new int[varList.getNumVars()]; varValues = new int[varList.getNumVars()];
} }
// CONVERSION METHODS
// convert to StateProbsDV, destroy (clear) old vector
public StateProbsDV convertToStateProbsDV()
{
StateProbsDV res = new StateProbsDV(probs, model);
clear();
return res;
}
// convert to StateProbsMTBDD (nothing to do)
public StateProbsMTBDD convertToStateProbsMTBDD()
{
return this;
}
// METHODS TO MODIFY VECTOR // METHODS TO MODIFY VECTOR
// round // round

Loading…
Cancel
Save