Browse Source

Added cumulative reward model checking for DTMCs (all 3 engines).

git-svn-id: https://www.prismmodelchecker.org/svn/prism/prism/trunk@278 bbc10eb1-c90d-0410-af57-cb519fbb1720
master
Dave Parker 20 years ago
parent
commit
3dac129c9b
  1. 8
      prism/include/PrismHybrid.h
  2. 8
      prism/include/PrismMTBDD.h
  3. 8
      prism/include/PrismSparse.h
  4. 306
      prism/src/hybrid/PH_ProbCumulReward.cc
  5. 9
      prism/src/hybrid/PrismHybrid.java
  6. 127
      prism/src/mtbdd/PM_ProbCumulReward.cc
  7. 9
      prism/src/mtbdd/PrismMTBDD.java
  8. 22
      prism/src/parser/PrismParser.java
  9. 6
      prism/src/prism/NondetModelChecker.java
  10. 76
      prism/src/prism/ProbModelChecker.java
  11. 236
      prism/src/sparse/PS_ProbCumulReward.cc
  12. 9
      prism/src/sparse/PrismSparse.java

8
prism/include/PrismHybrid.h

@ -159,6 +159,14 @@ JNIEXPORT jlong JNICALL Java_hybrid_PrismHybrid_PH_1ProbBoundedUntil
JNIEXPORT jlong JNICALL Java_hybrid_PrismHybrid_PH_1ProbUntil JNIEXPORT jlong JNICALL Java_hybrid_PrismHybrid_PH_1ProbUntil
(JNIEnv *, jclass, jlong, jlong, jlong, jint, jlong, jint, jlong, jlong); (JNIEnv *, jclass, jlong, jlong, jlong, jint, jlong, jint, jlong, jlong);
/*
* Class: hybrid_PrismHybrid
* Method: PH_ProbCumulReward
* Signature: (JJJJJIJII)J
*/
JNIEXPORT jlong JNICALL Java_hybrid_PrismHybrid_PH_1ProbCumulReward
(JNIEnv *, jclass, jlong, jlong, jlong, jlong, jlong, jint, jlong, jint, jint);
/* /*
* Class: hybrid_PrismHybrid * Class: hybrid_PrismHybrid
* Method: PH_ProbReachReward * Method: PH_ProbReachReward

8
prism/include/PrismMTBDD.h

@ -167,6 +167,14 @@ JNIEXPORT jlong JNICALL Java_mtbdd_PrismMTBDD_PM_1ProbBoundedUntil
JNIEXPORT jlong JNICALL Java_mtbdd_PrismMTBDD_PM_1ProbUntil JNIEXPORT jlong JNICALL Java_mtbdd_PrismMTBDD_PM_1ProbUntil
(JNIEnv *, jclass, jlong, jlong, jlong, jint, jlong, jint, jlong, jlong); (JNIEnv *, jclass, jlong, jlong, jlong, jint, jlong, jint, jlong, jlong);
/*
* Class: mtbdd_PrismMTBDD
* Method: PM_ProbCumulReward
* Signature: (JJJJJIJII)J
*/
JNIEXPORT jlong JNICALL Java_mtbdd_PrismMTBDD_PM_1ProbCumulReward
(JNIEnv *, jclass, jlong, jlong, jlong, jlong, jlong, jint, jlong, jint, jint);
/* /*
* Class: mtbdd_PrismMTBDD * Class: mtbdd_PrismMTBDD
* Method: PM_ProbReachReward * Method: PM_ProbReachReward

8
prism/include/PrismSparse.h

@ -119,6 +119,14 @@ JNIEXPORT jlong JNICALL Java_sparse_PrismSparse_PS_1ProbBoundedUntil
JNIEXPORT jlong JNICALL Java_sparse_PrismSparse_PS_1ProbUntil JNIEXPORT jlong JNICALL Java_sparse_PrismSparse_PS_1ProbUntil
(JNIEnv *, jclass, jlong, jlong, jlong, jint, jlong, jint, jlong, jlong); (JNIEnv *, jclass, jlong, jlong, jlong, jint, jlong, jint, jlong, jlong);
/*
* Class: sparse_PrismSparse
* Method: PS_ProbCumulReward
* Signature: (JJJJJIJII)J
*/
JNIEXPORT jlong JNICALL Java_sparse_PrismSparse_PS_1ProbCumulReward
(JNIEnv *, jclass, jlong, jlong, jlong, jlong, jlong, jint, jlong, jint, jint);
/* /*
* Class: sparse_PrismSparse * Class: sparse_PrismSparse
* Method: PS_ProbReachReward * Method: PS_ProbReachReward

306
prism/src/hybrid/PH_ProbCumulReward.cc

@ -0,0 +1,306 @@
//==============================================================================
//
// Copyright (c) 2002-
// Authors:
// * Dave Parker <dxp@cs.bham.uc.uk> (University of Birmingham)
//
//------------------------------------------------------------------------------
//
// This file is part of PRISM.
//
// PRISM is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// PRISM is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with PRISM; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//==============================================================================
// includes
#include "PrismHybrid.h"
#include <math.h>
#include <util.h>
#include <cudd.h>
#include <dd.h>
#include <odd.h>
#include <dv.h>
#include "sparse.h"
#include "hybrid.h"
#include "PrismHybridGlob.h"
#include "jnipointer.h"
// local prototypes
static void mult_rec(HDDNode *hdd, int level, int row_offset, int col_offset);
static void mult_rm(RMSparseMatrix *rmsm, int row_offset, int col_offset);
static void mult_cmsr(CMSRSparseMatrix *cmsrsm, int row_offset, int col_offset);
// globals (used by local functions)
static HDDNode *zero;
static int num_levels;
static bool compact_sm;
static double *sm_dist;
static int sm_dist_shift;
static int sm_dist_mask;
static double *soln, *soln2;
//------------------------------------------------------------------------------
JNIEXPORT jlong __pointer JNICALL Java_hybrid_PrismHybrid_PH_1ProbCumulReward
(
JNIEnv *env,
jclass cls,
jlong __pointer t, // trans matrix
jlong __pointer sr, // state rewards
jlong __pointer trr,// transition rewards
jlong __pointer od, // odd
jlong __pointer rv, // row vars
jint num_rvars,
jlong __pointer cv, // col vars
jint num_cvars,
jint bound // time bound
)
{
// cast function parameters
DdNode *trans = jlong_to_DdNode(t); // trans matrix
DdNode *state_rewards = jlong_to_DdNode(sr); // state rewards
DdNode *trans_rewards = jlong_to_DdNode(trr); // transition rewards
ODDNode *odd = jlong_to_ODDNode(od); // reachable states
DdNode **rvars = jlong_to_DdNode_array(rv); // row vars
DdNode **cvars = jlong_to_DdNode_array(cv); // col vars
// model stats
int n;
long nnz;
// flags
bool compact_r;
// matrix mtbdd
HDDMatrix *hddm;
HDDNode *hdd;
// vectors
double *rew_vec, *tmpsoln;
DistVector *rew_dist;
// timing stuff
long start1, start2, start3, stop;
double time_taken, time_for_setup, time_for_iters;
// misc
int i, j, iters;
double kb, kbt;
// start clocks
start1 = start2 = util_cpu_time();
// get number of states
n = odd->eoff + odd->toff;
// build hdd for matrix
PH_PrintToMainLog(env, "\nBuilding hybrid MTBDD matrix... ");
hddm = build_hdd_matrix(trans, rvars, cvars, num_rvars, odd, true);
hdd = hddm->top;
zero = hddm->zero;
num_levels = hddm->num_levels;
kb = hddm->mem_nodes;
kbt = kb;
PH_PrintToMainLog(env, "[levels=%d, nodes=%d] [%.1f KB]\n", hddm->num_levels, hddm->num_nodes, kb);
// add sparse matrices
PH_PrintToMainLog(env, "Adding explicit sparse matrices... ");
add_sparse_matrices(hddm, compact, false);
compact_sm = hddm->compact_sm;
if (compact_sm) {
sm_dist = hddm->dist;
sm_dist_shift = hddm->dist_shift;
sm_dist_mask = hddm->dist_mask;
}
kb = hddm->mem_sm;
kbt += kb;
PH_PrintToMainLog(env, "[levels=%d, num=%d%s] [%.1f KB]\n", hddm->l_sm, hddm->num_sm, compact_sm?", compact":"", kb);
// multiply transition rewards by transition probs and sum rows
// (note also filters out unwanted states at the same time)
Cudd_Ref(trans);
trans_rewards = DD_Apply(ddman, APPLY_TIMES, trans_rewards, trans);
trans_rewards = DD_SumAbstract(ddman, trans_rewards, cvars, num_cvars);
// combine state and transition rewards and put in a vector
Cudd_Ref(trans_rewards);
state_rewards = DD_Apply(ddman, APPLY_PLUS, state_rewards, trans_rewards);
// get vector of rewards
PH_PrintToMainLog(env, "Creating vector for rewards... ");
rew_vec = mtbdd_to_double_vector(ddman, state_rewards, rvars, num_rvars, odd);
// try and convert to compact form if required
compact_r = false;
if (compact) {
if (rew_dist = double_vector_to_dist(rew_vec, n)) {
compact_r = true;
free(rew_vec);
}
}
kb = (!compact_r) ? n*8.0/1024.0 : (rew_dist->num_dist*8.0+n*2.0)/1024.0;
kbt += kb;
if (!compact_r) PH_PrintToMainLog(env, "[%.1f KB]\n", kb);
else PH_PrintToMainLog(env, "[dist=%d, compact] [%.1f KB]\n", rew_dist->num_dist, kb);
// create solution/iteration vectors
PH_PrintToMainLog(env, "Allocating iteration vectors... ");
soln = new double[n];
soln2 = new double[n];
kb = n*8.0/1024.0;
kbt += 2*kb;
PH_PrintToMainLog(env, "[2 x %.1f KB]\n", kb);
// print total memory usage
PH_PrintToMainLog(env, "TOTAL: [%.1f KB]\n", kbt);
// initial solution is zero
for (i = 0; i < n; i++) {
soln[i] = 0;
}
// get setup time
stop = util_cpu_time();
time_for_setup = (double)(stop - start2)/1000;
start2 = stop;
// start iterations
PH_PrintToMainLog(env, "\nStarting iterations...\n");
// note that we ignore max_iters as we know how any iterations _should_ be performed
for (iters = 0; iters < bound; iters++) {
// PH_PrintToMainLog(env, "Iteration %d: ", iters);
// start3 = util_cpu_time();
// initialise vector
for (i = 0; i < n; i++) {
soln2[i] = (!compact_r) ? rew_vec[i] : rew_dist->dist[rew_dist->ptrs[i]];
}
// do matrix vector multiply bit
mult_rec(hdd, 0, 0, 0);
// prepare for next iteration
tmpsoln = soln;
soln = soln2;
soln2 = tmpsoln;
// PH_PrintToMainLog(env, "%.2f %.2f sec\n", ((double)(util_cpu_time() - start3)/1000), ((double)(util_cpu_time() - start2)/1000)/iters);
}
// stop clocks
stop = util_cpu_time();
time_for_iters = (double)(stop - start2)/1000;
time_taken = (double)(stop - start1)/1000;
// print iterations/timing info
PH_PrintToMainLog(env, "\nIterative method: %d iterations in %.2f seconds (average %.6f, setup %.2f)\n", iters, time_taken, time_for_iters/iters, time_for_setup);
// free memory
free_hdd_matrix(hddm);
if (compact_r) free_dist_vector(rew_dist); else free(rew_vec);
delete soln2;
return ptr_to_jlong(soln);
}
//------------------------------------------------------------------------------
static void mult_rec(HDDNode *hdd, int level, int row_offset, int col_offset)
{
HDDNode *e, *t;
// if it's the zero node
if (hdd == zero) {
return;
}
// or if we've reached a submatrix
// (check for non-null ptr but, equivalently, we could just check if level==l_sm)
else if (hdd->sm.ptr) {
if (!compact_sm) {
mult_rm((RMSparseMatrix *)hdd->sm.ptr, row_offset, col_offset);
} else {
mult_cmsr((CMSRSparseMatrix *)hdd->sm.ptr, row_offset, col_offset);
}
return;
}
// or if we've reached the bottom
else if (level == num_levels) {
//printf("(%d,%d)=%f\n", row_offset, col_offset, hdd->type.val);
soln2[row_offset] += soln[col_offset] * hdd->type.val;
return;
}
// otherwise recurse
e = hdd->type.kids.e;
if (e != zero) {
mult_rec(e->type.kids.e, level+1, row_offset, col_offset);
mult_rec(e->type.kids.t, level+1, row_offset, col_offset+e->off.val);
}
t = hdd->type.kids.t;
if (t != zero) {
mult_rec(t->type.kids.e, level+1, row_offset+hdd->off.val, col_offset);
mult_rec(t->type.kids.t, level+1, row_offset+hdd->off.val, col_offset+t->off.val);
}
}
//-----------------------------------------------------------------------------------
static void mult_rm(RMSparseMatrix *rmsm, int row_offset, int col_offset)
{
int i2, j2, l2, h2;
int sm_n = rmsm->n;
int sm_nnz = rmsm->nnz;
double *sm_non_zeros = rmsm->non_zeros;
unsigned char *sm_row_counts = rmsm->row_counts;
int *sm_row_starts = (int *)rmsm->row_counts;
bool sm_use_counts = rmsm->use_counts;
unsigned int *sm_cols = rmsm->cols;
// loop through rows of submatrix
l2 = sm_nnz; h2 = 0;
for (i2 = 0; i2 < sm_n; i2++) {
// loop through entries in this row
if (!sm_use_counts) { l2 = sm_row_starts[i2]; h2 = sm_row_starts[i2+1]; }
else { l2 = h2; h2 += sm_row_counts[i2]; }
for (j2 = l2; j2 < h2; j2++) {
soln2[row_offset + i2] += soln[col_offset + sm_cols[j2]] * sm_non_zeros[j2];
//printf("(%d,%d)=%f\n", row_offset + i2, col_offset + sm_cols[j2], sm_non_zeros[j2]);
}
}
}
//-----------------------------------------------------------------------------------
static void mult_cmsr(CMSRSparseMatrix *cmsrsm, int row_offset, int col_offset)
{
int i2, j2, l2, h2;
int sm_n = cmsrsm->n;
int sm_nnz = cmsrsm->nnz;
unsigned char *sm_row_counts = cmsrsm->row_counts;
int *sm_row_starts = (int *)cmsrsm->row_counts;
bool sm_use_counts = cmsrsm->use_counts;
unsigned int *sm_cols = cmsrsm->cols;
// loop through rows of submatrix
l2 = sm_nnz; h2 = 0;
for (i2 = 0; i2 < sm_n; i2++) {
// loop through entries in this row
if (!sm_use_counts) { l2 = sm_row_starts[i2]; h2 = sm_row_starts[i2+1]; }
else { l2 = h2; h2 += sm_row_counts[i2]; }
for (j2 = l2; j2 < h2; j2++) {
soln2[row_offset + i2] += soln[col_offset + (int)(sm_cols[j2] >> sm_dist_shift)] * sm_dist[(int)(sm_cols[j2] & sm_dist_mask)];
//printf("(%d,%d)=%f\n", row_offset + i2, col_offset + (int)(sm_cols[j2] >> sm_dist_shift), sm_dist[(int)(sm_cols[j2] & sm_dist_mask)]);
}
}
}
//------------------------------------------------------------------------------

9
prism/src/hybrid/PrismHybrid.java

@ -245,6 +245,15 @@ public class PrismHybrid
return new DoubleVector(ptr, (int)(odd.getEOff() + odd.getTOff())); return new DoubleVector(ptr, (int)(odd.getEOff() + odd.getTOff()));
} }
// pctl cumulative reward (probabilistic/dtmc)
private static native long PH_ProbCumulReward(long trans, long sr, long trr, long odd, long rv, int nrv, long cv, int ncv, int bound);
public static DoubleVector ProbCumulReward(JDDNode trans, JDDNode sr, JDDNode trr, ODDNode odd, JDDVars rows, JDDVars cols, int bound) throws PrismException
{
long ptr = PH_ProbCumulReward(trans.ptr(), sr.ptr(), trr.ptr(), odd.ptr(), rows.array(), rows.n(), cols.array(), cols.n(), bound);
if (ptr == 0) throw new PrismException(getErrorMessage());
return new DoubleVector(ptr, (int)(odd.getEOff() + odd.getTOff()));
}
// pctl reach reward (probabilistic/dtmc) // pctl reach reward (probabilistic/dtmc)
private static native long PH_ProbReachReward(long trans, long sr, long trr, long odd, long rv, int nrv, long cv, int ncv, long goal, long inf, long maybe); private static native long PH_ProbReachReward(long trans, long sr, long trr, long odd, long rv, int nrv, long cv, int ncv, long goal, long inf, long maybe);
public static DoubleVector ProbReachReward(JDDNode trans, JDDNode sr, JDDNode trr, ODDNode odd, JDDVars rows, JDDVars cols, JDDNode goal, JDDNode inf, JDDNode maybe) throws PrismException public static DoubleVector ProbReachReward(JDDNode trans, JDDNode sr, JDDNode trr, ODDNode odd, JDDVars rows, JDDVars cols, JDDNode goal, JDDNode inf, JDDNode maybe) throws PrismException

127
prism/src/mtbdd/PM_ProbCumulReward.cc

@ -0,0 +1,127 @@
//==============================================================================
//
// Copyright (c) 2002-
// Authors:
// * Dave Parker <dxp@cs.bham.uc.uk> (University of Birmingham)
//
//------------------------------------------------------------------------------
//
// This file is part of PRISM.
//
// PRISM is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// PRISM is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with PRISM; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//==============================================================================
// includes
#include "PrismMTBDD.h"
#include <math.h>
#include <util.h>
#include <cudd.h>
#include <dd.h>
#include <odd.h>
#include "PrismMTBDDGlob.h"
#include "jnipointer.h"
//------------------------------------------------------------------------------
JNIEXPORT jlong __pointer JNICALL Java_mtbdd_PrismMTBDD_PM_1ProbCumulReward
(
JNIEnv *env,
jclass cls,
jlong __pointer t, // trans matrix
jlong __pointer sr, // state rewards
jlong __pointer trr, // transition rewards
jlong __pointer od, // odd
jlong __pointer rv, // row vars
jint num_rvars,
jlong __pointer cv, // col vars
jint num_cvars,
jint bound // time bound
)
{
// cast function parameters
DdNode *trans = jlong_to_DdNode(t); // trans matrix
DdNode *state_rewards = jlong_to_DdNode(sr); // state rewards
DdNode *trans_rewards = jlong_to_DdNode(trr); // transition rewards
ODDNode *odd = jlong_to_ODDNode(od); // odd
DdNode **rvars = jlong_to_DdNode_array(rv); // row vars
DdNode **cvars = jlong_to_DdNode_array(cv); // col vars
// mtbdds
DdNode *sol, *tmp;
// timing stuff
long start1, start2, start3, stop;
double time_taken, time_for_setup, time_for_iters;
// misc
int iters, i;
// start clocks
start1 = start2 = util_cpu_time();
// multiply transition rewards by transition probs and sum rows
// (note also filters out unwanted states at the same time)
Cudd_Ref(trans);
trans_rewards = DD_Apply(ddman, APPLY_TIMES, trans_rewards, trans);
trans_rewards = DD_SumAbstract(ddman, trans_rewards, cvars, num_cvars);
// combine state and transition rewards and put in a vector
Cudd_Ref(trans_rewards);
state_rewards = DD_Apply(ddman, APPLY_PLUS, state_rewards, trans_rewards);
// initial solution is zero
sol = DD_Constant(ddman, 0);
// get setup time
stop = util_cpu_time();
time_for_setup = (double)(stop - start2)/1000;
start2 = stop;
// start iterations
PM_PrintToMainLog(env, "\nStarting iterations...\n");
// note that we ignore max_iters as we know how any iterations _should_ be performed
for (iters = 0; iters < bound; iters++) {
// PM_PrintToMainLog(env, "Iteration %d: ", iters);
// start3 = util_cpu_time();
// matrix-vector multiply
Cudd_Ref(sol);
tmp = DD_PermuteVariables(ddman, sol, rvars, cvars, num_rvars);
Cudd_Ref(trans);
tmp = DD_MatrixMultiply(ddman, trans, tmp, cvars, num_cvars, MM_BOULDER);
// add in (combined state and transition) rewards
Cudd_Ref(state_rewards);
tmp = DD_Apply(ddman, APPLY_PLUS, tmp, state_rewards);
// prepare for next iteration
Cudd_RecursiveDeref(ddman, sol);
sol = tmp;
// PM_PrintToMainLog(env, "%.2f %.2f sec\n", ((double)(util_cpu_time() - start3)/1000), ((double)(util_cpu_time() - start2)/1000)/iters);
}
// stop clocks
stop = util_cpu_time();
time_for_iters = (double)(stop - start2)/1000;
time_taken = (double)(stop - start1)/1000;
// print iterations/timing info
PM_PrintToMainLog(env, "\nIterative method: %d iterations in %.2f seconds (average %.6f, setup %.2f)\n", iters, time_taken, time_for_iters/iters, time_for_setup);
return ptr_to_jlong(sol);
}
//------------------------------------------------------------------------------

9
prism/src/mtbdd/PrismMTBDD.java

@ -262,6 +262,15 @@ public class PrismMTBDD
return new JDDNode(ptr); return new JDDNode(ptr);
} }
// pctl cumulative reward (probabilistic/dtmc)
private static native long PM_ProbCumulReward(long trans, long sr, long trr, long odd, long rv, int nrv, long cv, int ncv, int bound);
public static JDDNode ProbCumulReward(JDDNode trans, JDDNode sr, JDDNode trr, ODDNode odd, JDDVars rows, JDDVars cols, int bound) throws PrismException
{
long ptr = PM_ProbCumulReward(trans.ptr(), sr.ptr(), trr.ptr(), odd.ptr(), rows.array(), rows.n(), cols.array(), cols.n(), bound);
if (ptr == 0) throw new PrismException(getErrorMessage());
return new JDDNode(ptr);
}
// pctl reach reward (probabilistic/dtmc) // pctl reach reward (probabilistic/dtmc)
private static native long PM_ProbReachReward(long trans, long sr, long trr, long odd, long rv, int nrv, long cv, int ncv, long goal, long inf, long maybe); private static native long PM_ProbReachReward(long trans, long sr, long trr, long odd, long rv, int nrv, long cv, int ncv, long goal, long inf, long maybe);
public static JDDNode ProbReachReward(JDDNode trans, JDDNode sr, JDDNode trr, ODDNode odd, JDDVars rows, JDDVars cols, JDDNode goal, JDDNode inf, JDDNode maybe) throws PrismException public static JDDNode ProbReachReward(JDDNode trans, JDDNode sr, JDDNode trr, ODDNode odd, JDDVars rows, JDDVars cols, JDDNode goal, JDDNode inf, JDDNode maybe) throws PrismException

22
prism/src/parser/PrismParser.java

@ -3913,17 +3913,6 @@ public class PrismParser implements PrismParserConstants {
finally { jj_save(184, xla); } finally { jj_save(184, xla); }
} }
static final private boolean jj_3_34() {
if (jj_3R_38()) return true;
return false;
}
static final private boolean jj_3_139() {
if (jj_scan_token(COLON)) return true;
if (jj_3R_35()) return true;
return false;
}
static final private boolean jj_3R_72() { static final private boolean jj_3R_72() {
if (jj_3R_92()) return true; if (jj_3R_92()) return true;
Token xsp; Token xsp;
@ -5935,6 +5924,17 @@ public class PrismParser implements PrismParserConstants {
return false; return false;
} }
static final private boolean jj_3_34() {
if (jj_3R_38()) return true;
return false;
}
static final private boolean jj_3_139() {
if (jj_scan_token(COLON)) return true;
if (jj_3R_35()) return true;
return false;
}
static private boolean jj_initialized_once = false; static private boolean jj_initialized_once = false;
static public PrismParserTokenManager token_source; static public PrismParserTokenManager token_source;
static SimpleCharStream jj_input_stream; static SimpleCharStream jj_input_stream;

6
prism/src/prism/NondetModelChecker.java

@ -1554,16 +1554,10 @@ public class NondetModelChecker implements ModelChecker
} }
} }
catch (PrismException e) { catch (PrismException e) {
JDD.Deref(inf);
JDD.Deref(maybe);
throw e; throw e;
} }
} }
// derefs
JDD.Deref(inf);
JDD.Deref(maybe);
return rewards; return rewards;
} }
} }

76
prism/src/prism/ProbModelChecker.java

@ -725,7 +725,9 @@ public class ProbModelChecker implements ModelChecker
// compute rewards // compute rewards
f = pctl.getOperand(); f = pctl.getOperand();
try { try {
if (f instanceof PCTLRewardReach)
if (f instanceof PCTLRewardCumul)
rewards = checkPCTLRewardCumul((PCTLRewardCumul)f, stateRewards, transRewards);
else if (f instanceof PCTLRewardReach)
rewards = checkPCTLRewardReach((PCTLRewardReach)f, stateRewards, transRewards); rewards = checkPCTLRewardReach((PCTLRewardReach)f, stateRewards, transRewards);
else else
throw new PrismException("Unrecognised operator in R[] formula"); throw new PrismException("Unrecognised operator in R[] formula");
@ -1020,6 +1022,45 @@ public class ProbModelChecker implements ModelChecker
return probs; return probs;
} }
// cumulative reward
private StateProbs checkPCTLRewardCumul(PCTLRewardCumul pctl, JDDNode stateRewards, JDDNode transRewards) throws PrismException
{
int time; // time
Expression expr;
StateProbs rewards = null;
// get info from inst reward
expr = pctl.getBound();
if (expr != null) {
time = expr.evaluateInt(constantValues, null);
if (time < 0) {
throw new PrismException("Invalid time bound " + time + " in cumulative reward formula");
}
}
else {
throw new PrismException("No time bound specified in cumulative reward formula");
}
// compute rewards
// a trivial case: "<=0"
if (time == 0) {
rewards = new StateProbsMTBDD(JDD.Constant(0), model);
}
else {
// compute rewards
try {
rewards = computeCumulRewards(trans, trans01, stateRewards, transRewards, time);
}
catch (PrismException e) {
throw e;
}
}
return rewards;
}
// reach reward // reach reward
private StateProbs checkPCTLRewardReach(PCTLRewardReach pctl, JDDNode stateRewards, JDDNode transRewards) throws PrismException private StateProbs checkPCTLRewardReach(PCTLRewardReach pctl, JDDNode stateRewards, JDDNode transRewards) throws PrismException
@ -1365,6 +1406,39 @@ public class ProbModelChecker implements ModelChecker
return probs; return probs;
} }
// compute cumulative rewards
private StateProbs computeCumulRewards(JDDNode tr, JDDNode tr01, JDDNode sr, JDDNode trr, int time) throws PrismException
{
JDDNode rewardsMTBDD;
DoubleVector rewardsDV;
StateProbs rewards = null;
// compute rewards
try {
switch (engine) {
case Prism.MTBDD:
rewardsMTBDD = PrismMTBDD.ProbCumulReward(tr, sr, trr, odd, allDDRowVars, allDDColVars, time);
rewards = new StateProbsMTBDD(rewardsMTBDD, model);
break;
case Prism.SPARSE:
rewardsDV = PrismSparse.ProbCumulReward(tr, sr, trr, odd, allDDRowVars, allDDColVars, time);
rewards = new StateProbsDV(rewardsDV, model);
break;
case Prism.HYBRID:
rewardsDV = PrismHybrid.ProbCumulReward(tr, sr, trr, odd, allDDRowVars, allDDColVars, time);
rewards = new StateProbsDV(rewardsDV, model);
break;
default: throw new PrismException("Engine does not support this numerical method");
}
}
catch (PrismException e) {
throw e;
}
return rewards;
}
// compute rewards for reach reward // compute rewards for reach reward
private StateProbs computeReachRewards(JDDNode tr, JDDNode tr01, JDDNode sr, JDDNode trr, JDDNode b) throws PrismException private StateProbs computeReachRewards(JDDNode tr, JDDNode tr01, JDDNode sr, JDDNode trr, JDDNode b) throws PrismException

236
prism/src/sparse/PS_ProbCumulReward.cc

@ -0,0 +1,236 @@
//==============================================================================
//
// Copyright (c) 2002-
// Authors:
// * Dave Parker <dxp@cs.bham.uc.uk> (University of Birmingham)
//
//------------------------------------------------------------------------------
//
// This file is part of PRISM.
//
// PRISM is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// PRISM is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with PRISM; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//==============================================================================
// includes
#include "PrismSparse.h"
#include <math.h>
#include <util.h>
#include <cudd.h>
#include <dd.h>
#include <odd.h>
#include <dv.h>
#include "sparse.h"
#include "PrismSparseGlob.h"
#include "jnipointer.h"
//------------------------------------------------------------------------------
JNIEXPORT jlong __pointer JNICALL Java_sparse_PrismSparse_PS_1ProbCumulReward
(
JNIEnv *env,
jclass cls,
jlong __pointer t, // trans matrix
jlong __pointer sr, // state rewards
jlong __pointer trr,// transition rewards
jlong __pointer od, // odd
jlong __pointer rv, // row vars
jint num_rvars,
jlong __pointer cv, // col vars
jint num_cvars,
jint bound // time bound
)
{
// cast function parameters
DdNode *trans = jlong_to_DdNode(t); // trans matrix
DdNode *state_rewards = jlong_to_DdNode(sr); // state rewards
DdNode *trans_rewards = jlong_to_DdNode(trr); // transition rewards
ODDNode *odd = jlong_to_ODDNode(od); // reachable states
DdNode **rvars = jlong_to_DdNode_array(rv); // row vars
DdNode **cvars = jlong_to_DdNode_array(cv); // col vars
// model stats
int n;
long nnz;
// flags
bool compact_tr, compact_r;
// sparse matrix
RMSparseMatrix *rmsm;
CMSRSparseMatrix *cmsrsm;
// vectors
double *rew_vec, *soln, *soln2, *tmpsoln;
DistVector *rew_dist;
// timing stuff
long start1, start2, start3, stop;
double time_taken, time_for_setup, time_for_iters;
// misc
int i, j, l, h, iters;
double d, kb, kbt;
// start clocks
start1 = start2 = util_cpu_time();
// get number of states
n = odd->eoff + odd->toff;
// build sparse matrix
PS_PrintToMainLog(env, "\nBuilding sparse matrix... ");
// if requested, try and build a "compact" version
compact_tr = true;
cmsrsm = NULL;
if (compact) cmsrsm = build_cmsr_sparse_matrix(ddman, trans, rvars, cvars, num_rvars, odd);
if (cmsrsm != NULL) {
nnz = cmsrsm->nnz;
kb = cmsrsm->mem;
}
// if not or if it wasn't possible, built a normal one
else {
compact_tr = false;
rmsm = build_rm_sparse_matrix(ddman, trans, rvars, cvars, num_rvars, odd);
nnz = rmsm->nnz;
kb = rmsm->mem;
}
// print some info
PS_PrintToMainLog(env, "[n=%d, nnz=%d%s] ", n, nnz, compact_tr?", compact":"");
kbt = kb;
PS_PrintToMainLog(env, "[%.1f KB]\n", kb);
// multiply transition rewards by transition probs and sum rows
// (note also filters out unwanted states at the same time)
Cudd_Ref(trans);
trans_rewards = DD_Apply(ddman, APPLY_TIMES, trans_rewards, trans);
trans_rewards = DD_SumAbstract(ddman, trans_rewards, cvars, num_cvars);
// combine state and transition rewards and put in a vector
Cudd_Ref(trans_rewards);
state_rewards = DD_Apply(ddman, APPLY_PLUS, state_rewards, trans_rewards);
// get vector of rewards
PS_PrintToMainLog(env, "Creating vector for rewards... ");
rew_vec = mtbdd_to_double_vector(ddman, state_rewards, rvars, num_rvars, odd);
// try and convert to compact form if required
compact_r = false;
if (compact) {
if (rew_dist = double_vector_to_dist(rew_vec, n)) {
compact_r = true;
free(rew_vec);
}
}
kb = (!compact_r) ? n*8.0/1024.0 : (rew_dist->num_dist*8.0+n*2.0)/1024.0;
kbt += kb;
if (!compact_r) PS_PrintToMainLog(env, "[%.1f KB]\n", kb);
else PS_PrintToMainLog(env, "[dist=%d, compact] [%.1f KB]\n", rew_dist->num_dist, kb);
// create solution/iteration vectors
PS_PrintToMainLog(env, "Allocating iteration vectors... ");
soln = new double[n];
soln2 = new double[n];
kb = n*8.0/1024.0;
kbt += 2*kb;
PS_PrintToMainLog(env, "[2 x %.1f KB]\n", kb);
// print total memory usage
PS_PrintToMainLog(env, "TOTAL: [%.1f KB]\n", kbt);
// initial solution is zero
for (i = 0; i < n; i++) {
soln[i] = 0;
}
// get setup time
stop = util_cpu_time();
time_for_setup = (double)(stop - start2)/1000;
start2 = stop;
// start iterations
PS_PrintToMainLog(env, "\nStarting iterations...\n");
// note that we ignore max_iters as we know how any iterations _should_ be performed
for (iters = 0; iters < bound; iters++) {
// PS_PrintToMainLog(env, "Iteration %d: ", iters);
// start3 = util_cpu_time();
// store local copies of stuff
double *non_zeros;
unsigned char *row_counts;
int *row_starts;
bool use_counts;
unsigned int *cols;
double *dist;
int dist_shift;
int dist_mask;
if (!compact_tr) {
non_zeros = rmsm->non_zeros;
row_counts = rmsm->row_counts;
row_starts = (int *)rmsm->row_counts;
use_counts = rmsm->use_counts;
cols = rmsm->cols;
} else {
row_counts = cmsrsm->row_counts;
row_starts = (int *)cmsrsm->row_counts;
use_counts = cmsrsm->use_counts;
cols = cmsrsm->cols;
dist = cmsrsm->dist;
dist_shift = cmsrsm->dist_shift;
dist_mask = cmsrsm->dist_mask;
}
// matrix multiply
h = 0;
for (i = 0; i < n; i++) {
d = (!compact_r) ? rew_vec[i] : rew_dist->dist[rew_dist->ptrs[i]];
if (!use_counts) { l = row_starts[i]; h = row_starts[i+1]; }
else { l = h; h += row_counts[i]; }
// "row major" version
if (!compact_tr) {
for (j = l; j < h; j++) {
d += non_zeros[j] * soln[cols[j]];
}
// "compact msr" version
} else {
for (j = l; j < h; j++) {
d += dist[(int)(cols[j] & dist_mask)] * soln[(int)(cols[j] >> dist_shift)];
}
}
// set vector element
soln2[i] = d;
}
// prepare for next iteration
tmpsoln = soln;
soln = soln2;
soln2 = tmpsoln;
// PS_PrintToMainLog(env, "%.2f %.2f sec\n", ((double)(util_cpu_time() - start3)/1000), ((double)(util_cpu_time() - start2)/1000)/iters);
}
// stop clocks
stop = util_cpu_time();
time_for_iters = (double)(stop - start2)/1000;
time_taken = (double)(stop - start1)/1000;
// print iterations/timing info
PS_PrintToMainLog(env, "\nIterative method: %d iterations in %.2f seconds (average %.6f, setup %.2f)\n", iters, time_taken, time_for_iters/iters, time_for_setup);
// free memory
if (compact_tr) free_cmsr_sparse_matrix(cmsrsm); else free_rm_sparse_matrix(rmsm);
if (compact_r) free_dist_vector(rew_dist); else free(rew_vec);
delete soln2;
return ptr_to_jlong(soln);
}
//------------------------------------------------------------------------------

9
prism/src/sparse/PrismSparse.java

@ -205,6 +205,15 @@ public class PrismSparse
return new DoubleVector(ptr, (int)(odd.getEOff() + odd.getTOff())); return new DoubleVector(ptr, (int)(odd.getEOff() + odd.getTOff()));
} }
// pctl cumulative reward (probabilistic/dtmc)
private static native long PS_ProbCumulReward(long trans, long sr, long trr, long odd, long rv, int nrv, long cv, int ncv, int bound);
public static DoubleVector ProbCumulReward(JDDNode trans, JDDNode sr, JDDNode trr, ODDNode odd, JDDVars rows, JDDVars cols, int bound) throws PrismException
{
long ptr = PS_ProbCumulReward(trans.ptr(), sr.ptr(), trr.ptr(), odd.ptr(), rows.array(), rows.n(), cols.array(), cols.n(), bound);
if (ptr == 0) throw new PrismException(getErrorMessage());
return new DoubleVector(ptr, (int)(odd.getEOff() + odd.getTOff()));
}
// pctl reach reward (probabilistic/dtmc) // pctl reach reward (probabilistic/dtmc)
private static native long PS_ProbReachReward(long trans, long sr, long trr, long odd, long rv, int nrv, long cv, int ncv, long goal, long inf, long maybe); private static native long PS_ProbReachReward(long trans, long sr, long trr, long odd, long rv, int nrv, long cv, int ncv, long goal, long inf, long maybe);
public static DoubleVector ProbReachReward(JDDNode trans, JDDNode sr, JDDNode trr, ODDNode odd, JDDVars rows, JDDVars cols, JDDNode goal, JDDNode inf, JDDNode maybe) throws PrismException public static DoubleVector ProbReachReward(JDDNode trans, JDDNode sr, JDDNode trr, ODDNode odd, JDDVars rows, JDDVars cols, JDDNode goal, JDDNode inf, JDDNode maybe) throws PrismException

Loading…
Cancel
Save