You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

889 lines
28 KiB

//==============================================================================
//
// Copyright (c) 2002-
// Authors:
// * Dave Parker <david.parker@comlab.ox.ac.uk> (University of Oxford, formerly 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
//
//==============================================================================
package prism;
import java.io.*;
import java.util.Vector;
import java.util.HashMap;
import jdd.*;
import parser.*;
import parser.ast.*;
// class to translate an explicit prism model description into an MTBDD model
public class Explicit2MTBDD
{
// prism
private Prism prism;
// logs
private PrismLog mainLog; // main log
private PrismLog techLog; // tech log
// files to read in from
private File statesFile;
private File transFile;
// initial state info
private String initString;
private HashMap<String,Object> initVals;
// ModulesFile object, essentially just to store variable info
private ModulesFile modulesFile;
// model info
// type
private int type; // model type (prob./nondet./stoch.)
// vars info
private int numVars; // total number of variables
private String varNames[]; // names of vars
private int varMins[]; // min values of vars
private int varMaxs[]; // max values of vars
private int varRanges[]; // ranges of vars
private int varTypes[]; // types of vars
private VarList varList; // VarList object to store all var info
// explicit storage of states
private int numStates = 0;
private int statesArray[][] = null;
// mtbdd stuff
// dds/dd vars - whole system
private JDDNode trans; // transition matrix dd
private JDDNode range; // dd giving range for system
private JDDNode start; // dd for start state
private JDDNode stateRewards; // dd of state rewards
private JDDNode transRewards; // dd of transition rewards
private JDDVars allDDRowVars; // all dd vars (rows)
private JDDVars allDDColVars; // all dd vars (cols)
private JDDVars allDDSynchVars; // all dd vars (synchronising actions)
private JDDVars allDDSchedVars; // all dd vars (scheduling)
private JDDVars allDDChoiceVars; // all dd vars (internal non-det.)
private JDDVars allDDNondetVars; // all dd vars (all non-det.)
// dds/dd vars - modules
private JDDVars[] moduleDDRowVars; // dd vars for each module (rows)
private JDDVars[] moduleDDColVars; // dd vars for each module (cols)
private JDDNode[] moduleRangeDDs; // dd giving range for each module
private JDDNode[] moduleIdentities; // identity matrix for each module
// dds/dd vars - variables
private JDDVars[] varDDRowVars; // dd vars (row/col) for each module variable
private JDDVars[] varDDColVars;
private JDDNode[] varRangeDDs; // dd giving range for each module variable
private JDDNode[] varColRangeDDs; // dd giving range for each module variable (in col vars)
private JDDNode[] varIdentities; // identity matrix for each module variable
// dds/dd vars - nondeterminism
private JDDNode[] ddSynchVars; // individual dd vars for synchronising actions
private JDDNode[] ddSchedVars; // individual dd vars for scheduling non-det.
private JDDNode[] ddChoiceVars; // individual dd vars for local non-det.
// names for all dd vars used
private Vector<String> ddVarNames;
private int maxNumChoices = 0;
// constructor
public Explicit2MTBDD(Prism prism, File sf, File tf, int t, String is)
{
this.prism = prism;
mainLog = prism.getMainLog();
techLog = prism.getTechLog();
statesFile = sf;
transFile = tf;
// set type at this point
// if no preference stated, assume default of mdp
switch (t) {
case ModulesFile.PROBABILISTIC:
case ModulesFile.NONDETERMINISTIC:
case ModulesFile.STOCHASTIC:
type = t; break;
default:
type = ModulesFile.NONDETERMINISTIC; break;
}
initString = is;
}
// build state space
public ModulesFile buildStates() throws PrismException
{
// parse any info about initial state
parseInitString();
// generate info about variables...
// ...either reading from state list file
if (statesFile != null) {
createVarInfoFromStatesFile();
// in this case, also create explicit table of states
readStatesFromFile();
}
// ...or just creating it from scratch in the trivial case (need transitions file)
else {
createVarInfoFromTransFile();
}
return modulesFile;
}
// parse info about initial state
public void parseInitString() throws PrismException
{
String ss[], ss2[];
int i, j;
// create hash map to store var name -> var value mapping
initVals = new HashMap<String,Object>();
// parse string
if (initString == null) return;
ss = initString.split(",");
for (i = 0; i < ss.length; i++) {
ss2 = ss[i].split("=");
if (ss2.length != 2) throw new PrismException("Badly formatted initial states string");
if (!ss2[0].matches("[A-Za-z_][A-Za-z_0-9]*")) throw new PrismException("Badly formatted variable name in initial states string");
if (ss2[1].equals("true")) initVals.put(ss2[0], new Boolean(true));
else if (ss2[1].equals("false")) initVals.put(ss2[0], new Boolean(false));
else {
try {
j = Integer.parseInt(ss2[1]);
initVals.put(ss2[0], new Integer(j));
}
catch (NumberFormatException e) {
throw new PrismException("Badly formatted value in initial states string");
}
}
}
}
// create info about vars from states file and put into ModulesFile object
public void createVarInfoFromStatesFile() throws PrismException
{
BufferedReader in;
String s, ss[];
int i, j, lineNum = 0;
Module m;
Declaration d;
Object o;
try {
// open file for reading
in = new BufferedReader(new FileReader(statesFile));
// read first line and extract var names
s = in.readLine().trim(); lineNum = 1;
if (s.charAt(0) != '(' || s.charAt(s.length()-1) != ')') throw new PrismException("");
s = s.substring(1, s.length()-1);
varNames = s.split(",");
numVars = varNames.length;
// create arrays to store info about vars
varMins = new int[numVars];
varMaxs = new int[numVars];
varRanges = new int[numVars];
varTypes = new int[numVars];
// read remaining lines
s = in.readLine(); lineNum++;
numStates = 0;
while (s != null) {
// increment state count
numStates++;
// split string
s = s.trim();
s = s.substring(s.indexOf('(')+1, s.indexOf(')'));
ss = s.split(",");
if (ss.length != numVars) throw new PrismException("");
// for each variable...
for (i = 0; i < numVars; i++) {
// if this is the first state, establish variable type
if (numStates == 1) {
if (ss[i].equals("true") || ss[i].equals("false")) varTypes[i] = Expression.BOOLEAN;
else varTypes[i] = Expression.INT;
}
// check for new min/max values (ints only)
if (varTypes[i] == Expression.INT) {
j = Integer.parseInt(ss[i]);
if (numStates == 1) {
varMins[i] = varMaxs[i] = j;
} else {
if (j < varMins[i]) varMins[i] = j;
if (j > varMaxs[i]) varMaxs[i] = j;
}
}
}
s = in.readLine(); lineNum++;
}
// compute variable ranges
for (i = 0; i < numVars; i++) {
if (varTypes[i] == Expression.INT) {
varRanges[i] = varMaxs[i] - varMins[i];
// if range = 0, increment maximum - we don't allow zero-range variables
if (varRanges[i] == 0) varMaxs[i]++;
}
}
// close file
in.close();
}
catch (IOException e) {
throw new PrismException("File I/O error reading from \"" + statesFile + "\"");
}
catch (NumberFormatException e) {
throw new PrismException("Error detected at line " + lineNum + " of states file \"" + statesFile + "\"");
}
catch (PrismException e) {
throw new PrismException("Error detected " + e.getMessage() + "at line " + lineNum + " of states file \"" + statesFile + "\"");
}
// create modules file
modulesFile = new ModulesFile();
m = new Module("M");
for (i = 0; i < numVars; i++) {
if (varTypes[i] == Expression.INT) {
o = initVals.get(varNames[i]);
if (o == null)
d = new Declaration(varNames[i], new ExpressionLiteral(Expression.INT, varMins[i]), new ExpressionLiteral(Expression.INT, varMaxs[i]), new ExpressionLiteral(Expression.INT, varMins[i]));
else
d = new Declaration(varNames[i], new ExpressionLiteral(Expression.INT, varMins[i]), new ExpressionLiteral(Expression.INT, varMaxs[i]), new ExpressionLiteral(Expression.INT, ((Integer)o).intValue()));
}
else {
o = initVals.get(varNames[i]);
if (o == null)
d = new Declaration(varNames[i], new ExpressionLiteral(Expression.BOOLEAN, false));
else
d = new Declaration(varNames[i], new ExpressionLiteral(Expression.BOOLEAN, ((Boolean)o).booleanValue()));
}
m.addDeclaration(d);
}
modulesFile.addModule(m);
modulesFile.tidyUp();
}
// create info about vars from trans file and put into ModulesFile object
public void createVarInfoFromTransFile() throws PrismException
{
BufferedReader in;
String s, ss[];
int lineNum = 0;
Module m;
Declaration d;
Expression init;
Object o;
try {
// open file for reading
in = new BufferedReader(new FileReader(transFile));
// read first line and extract num states
s = in.readLine().trim(); lineNum = 1;
ss = s.split(" ");
if (ss.length < 2) throw new PrismException("");
numStates = Integer.parseInt(ss[0]);
// close file
in.close();
}
catch (IOException e) {
throw new PrismException("File I/O error reading from \"" + transFile + "\"");
}
catch (NumberFormatException e) {
throw new PrismException("Error detected at line " + lineNum + " of transition matrix file \"" + transFile + "\"");
}
catch (PrismException e) {
throw new PrismException("Error detected " + e.getMessage() + "at line " + lineNum + " of transition matrix file \"" + transFile + "\"");
}
// determine initial value for variable
o = initVals.get("x");
if (o == null) init = new ExpressionLiteral(Expression.INT, 0);
else init = new ExpressionLiteral(Expression.INT, ((Integer)o).intValue());
// create modules file
modulesFile = new ModulesFile();
m = new Module("M");
d = new Declaration("x", new ExpressionLiteral(Expression.INT, 0), new ExpressionLiteral(Expression.INT, numStates-1), init);
m.addDeclaration(d);
modulesFile.addModule(m);
modulesFile.tidyUp();
}
// read info about reachable state space from file and store explicitly
public void readStatesFromFile() throws PrismException
{
BufferedReader in;
String s, ss[];
int i, j, k, lineNum = 0;
// create arrays for explicit state storage
statesArray = new int[numStates][];
try {
// open file for reading
in = new BufferedReader(new FileReader(statesFile));
// skip first line
in.readLine(); lineNum = 1;
// read remaining lines
s = in.readLine(); lineNum++;
while (s != null) {
s = s.trim();
// split into two parts
ss = s.split(":");
// determine which state this line describes
i = Integer.parseInt(ss[0]);
// now split up middle bit and extract var info
ss = ss[1].substring(ss[1].indexOf('(')+1, ss[1].indexOf(')')).split(",");
if (ss.length != numVars) throw new PrismException("(wrong number of variable values) ");
if (statesArray[i] != null) throw new PrismException("(duplicated state) ");
statesArray[i] = new int[numVars];
for (j = 0; j < numVars; j++) {
if (varTypes[j] == Expression.INT) {
k = Integer.parseInt(ss[j]);
statesArray[i][j] = k - varMins[j];
}
else {
if (ss[j].equals("true")) statesArray[i][j] = 1;
else if (ss[j].equals("false")) statesArray[i][j] = 0;
else throw new PrismException("(invalid Boolean value \""+ss[j]+"\") ");
}
}
s = in.readLine(); lineNum++;
}
// close file
in.close();
}
catch (IOException e) {
throw new PrismException("File I/O error reading from \"" + statesFile + "\"");
}
catch (NumberFormatException e) {
throw new PrismException("Error detected at line " + lineNum + " of states file \"" + statesFile + "\"");
}
catch (PrismException e) {
throw new PrismException("Error detected " + e.getMessage() + "at line " + lineNum + " of states file \"" + statesFile + "\"");
}
}
// build model
public Model buildModel() throws PrismException
{
Model model = null;
JDDNode tmp, tmp2;
JDDVars ddv;
int i;
// get variable info from ModulesFile
varList = modulesFile.createVarList();
numVars = varList.getNumVars();
// for an mdp, compute the max number of choices in a state
if (type == ModulesFile.NONDETERMINISTIC) computeMaxChoicesFromFile();
// allocate dd variables
allocateDDVars();
sortDDVars();
sortIdentities();
sortRanges();
// construct transition matrix from file
buildTrans();
// get rid of any nondet dd variables not needed
if (type == ModulesFile.NONDETERMINISTIC) {
tmp = JDD.GetSupport(trans);
tmp = JDD.ThereExists(tmp, allDDRowVars);
tmp = JDD.ThereExists(tmp, allDDColVars);
tmp2 = tmp;
ddv = new JDDVars();
while (!tmp2.equals(JDD.ONE)) {
ddv.addVar(JDD.Var(tmp2.getIndex()));
tmp2 = tmp2.getThen();
}
JDD.Deref(tmp);
allDDNondetVars.derefAll();
allDDNondetVars = ddv;
}
// // print dd variables actually used (support of trans)
// mainLog.print("\nMTBDD variables used (" + allDDRowVars.n() + "r, " + allDDRowVars.n() + "c");
// if (type == ModulesFile.NONDETERMINISTIC) mainLog.print(", " + allDDNondetVars.n() + "nd");
// mainLog.print("):");
// tmp = JDD.GetSupport(trans);
// tmp2 = tmp;
// while (!tmp2.isConstant()) {
// //mainLog.print(" " + tmp2.getIndex() + ":" + ddVarNames.elementAt(tmp2.getIndex()));
// mainLog.print(" " + ddVarNames.elementAt(tmp2.getIndex()));
// tmp2 = tmp2.getThen();
// }
// mainLog.println();
// JDD.Deref(tmp);
// calculate dd for initial state
start = JDD.Constant(1);
for (i = 0; i < numVars; i++) {
tmp = JDD.SetVectorElement(JDD.Constant(0), varDDRowVars[i], varList.getStart(i)-varList.getLow(i), 1);
start = JDD.And(start, tmp);
}
// compute state rewards
computeStateRewards();
int numModules = 1; // just one module
String moduleNames[] = modulesFile.getModuleNames(); // whose name is stored here
Values constantValues = new Values(); // no constants
JDDNode stateRewardsArray[] = new JDDNode[1]; stateRewardsArray[0] = stateRewards;
JDDNode transRewardsArray[] = new JDDNode[1]; transRewardsArray[0] = transRewards;
String rewardStructNames[] = new String[1]; rewardStructNames[0] = "";
// create new Model object to be returned
if (type == ModulesFile.PROBABILISTIC) {
model = new ProbModel(trans, start, stateRewardsArray, transRewardsArray, rewardStructNames, allDDRowVars, allDDColVars, ddVarNames,
numModules, moduleNames, moduleDDRowVars, moduleDDColVars,
numVars, varList, varDDRowVars, varDDColVars, constantValues);
}
else if (type == ModulesFile.NONDETERMINISTIC) {
model = new NondetModel(trans, start, stateRewardsArray, transRewardsArray, rewardStructNames, allDDRowVars, allDDColVars,
allDDSynchVars, allDDSchedVars, allDDChoiceVars, allDDNondetVars, ddVarNames,
numModules, moduleNames, moduleDDRowVars, moduleDDColVars,
numVars, varList, varDDRowVars, varDDColVars, constantValues);
}
else if (type == ModulesFile.STOCHASTIC) {
model = new StochModel(trans, start, stateRewardsArray, transRewardsArray, rewardStructNames, allDDRowVars, allDDColVars, ddVarNames,
numModules, moduleNames, moduleDDRowVars, moduleDDColVars,
numVars, varList, varDDRowVars, varDDColVars, constantValues);
}
// do reachability (or not)
if (prism.getDoReach()) {
mainLog.print("\nComputing reachable states...\n");
model.doReachability(prism.getExtraReachInfo());
model.filterReachableStates();
}
else {
mainLog.print("\nSkipping reachable state computation.\n");
model.skipReachability();
model.filterReachableStates();
}
// Print some info (if extraddinfo flag on)
if (prism.getExtraDDInfo()) {
mainLog.print("Reach: " + JDD.GetNumNodes(model.getReach()) + " nodes\n");
}
// find any deadlocks
model.findDeadlocks();
// deref spare dds
JDD.Deref(moduleIdentities[0]);
JDD.Deref(moduleRangeDDs[0]);
for (i = 0; i < numVars; i++) {
JDD.Deref(varIdentities[i]);
JDD.Deref(varRangeDDs[i]);
JDD.Deref(varColRangeDDs[i]);
}
JDD.Deref(range);
if (type == ModulesFile.NONDETERMINISTIC) {
for (i = 0; i < ddSynchVars.length; i++) {
JDD.Deref(ddSynchVars[i]);
}
for (i = 0; i < ddSchedVars.length; i++) {
JDD.Deref(ddSchedVars[i]);
}
for (i = 0; i < ddChoiceVars.length; i++) {
JDD.Deref(ddChoiceVars[i]);
}
}
return model;
}
// for an mdp, compute max number of choices in a state (from transitions file)
public void computeMaxChoicesFromFile() throws PrismException
{
BufferedReader in;
String s, ss[];
int j, lineNum = 0;
try {
// open file for reading
in = new BufferedReader(new FileReader(transFile));
// skip first line
in.readLine(); lineNum = 1;
// read remaining lines
s = in.readLine(); lineNum++;
maxNumChoices = 0;
while (s != null) {
s = s.trim();
ss = s.split(" ");
if (ss.length < 4 || ss.length > 5) throw new PrismException("");
j = Integer.parseInt(ss[1]);
if (j+1 > maxNumChoices) maxNumChoices = j+1;
s = in.readLine(); lineNum++;
}
// close file
in.close();
}
catch (IOException e) {
throw new PrismException("File I/O error reading from \"" + transFile + "\"");
}
catch (NumberFormatException e) {
throw new PrismException("Error detected at line " + lineNum + " of transition matrix file \"" + transFile + "\"");
}
catch (PrismException e) {
throw new PrismException("Error detected " + e.getMessage() + "at line " + lineNum + " of transition matrix file \"" + transFile + "\"");
}
}
// allocate DD vars for system
// i.e. decide on variable ordering and request variables from CUDD
private void allocateDDVars()
{
JDDNode v, vr, vc;
int i, j, n;
int ddVarsUsed = 0;
ddVarNames = new Vector<String>();
// create arrays/etc. first
// nondeterministic variables
if (type == ModulesFile.NONDETERMINISTIC) {
ddSynchVars = new JDDNode[0];
ddSchedVars = new JDDNode[0];
ddChoiceVars = new JDDNode[maxNumChoices];
}
// module variable (row/col) vars
varDDRowVars = new JDDVars[numVars];
varDDColVars = new JDDVars[numVars];
for (i = 0; i < numVars; i++) {
varDDRowVars[i] = new JDDVars();
varDDColVars[i] = new JDDVars();
}
// now allocate variables
// allocate nondeterministic variables
if (type == ModulesFile.NONDETERMINISTIC) {
for (i = 0; i < maxNumChoices; i++) {
v = JDD.Var(ddVarsUsed++);
ddChoiceVars[i] = v;
ddVarNames.add("l" + i);
}
}
// allocate dd variables for module variables (i.e. rows/cols)
// go through all vars in order (incl. global variables)
// so overall ordering can be specified by ordering in the input file
for (i = 0; i < numVars; i++) {
// get number of dd variables needed
// (ceiling of log2 of range of variable)
n = varList.getRangeLogTwo(i);
// add pairs of variables (row/col)
for (j = 0; j < n; j++) {
// new dd row variable
vr = JDD.Var(ddVarsUsed++);
// new dd col variable
vc = JDD.Var(ddVarsUsed++);
varDDRowVars[i].addVar(vr);
varDDColVars[i].addVar(vc);
// add names to list
ddVarNames.add(varList.getName(i) + "." + j);
ddVarNames.add(varList.getName(i) + "'." + j);
}
}
}
// sort out DD variables and the arrays they are stored in
// (more than one copy of most variables is stored)
private void sortDDVars()
{
int i;
// put refs for all vars in each module together
// create arrays
moduleDDRowVars = new JDDVars[1];
moduleDDColVars = new JDDVars[1];
moduleDDRowVars[0] = new JDDVars();
moduleDDColVars[0] = new JDDVars();
// go thru all variables
for (i = 0; i < numVars; i++) {
varDDRowVars[i].refAll();
varDDColVars[i].refAll();
moduleDDRowVars[0].addVars(varDDRowVars[i]);
moduleDDColVars[0].addVars(varDDColVars[i]);
}
// put refs for all vars in whole system together
// create arrays
allDDRowVars = new JDDVars();
allDDColVars = new JDDVars();
if (type == ModulesFile.NONDETERMINISTIC) {
allDDSynchVars = new JDDVars();
allDDSchedVars = new JDDVars();
allDDChoiceVars = new JDDVars();
allDDNondetVars = new JDDVars();
}
// go thru all variables
for (i = 0; i < numVars; i++) {
// add to list
varDDRowVars[i].refAll();
varDDColVars[i].refAll();
allDDRowVars.addVars(varDDRowVars[i]);
allDDColVars.addVars(varDDColVars[i]);
}
if (type == ModulesFile.NONDETERMINISTIC) {
for (i = 0; i < ddChoiceVars.length; i++) {
// add to list
JDD.Ref(ddChoiceVars[i]);
JDD.Ref(ddChoiceVars[i]);
allDDChoiceVars.addVar(ddChoiceVars[i]);
allDDNondetVars.addVar(ddChoiceVars[i]);
}
}
}
// sort DDs for identities
private void sortIdentities()
{
int i, j;
JDDNode id;
// variable identities
varIdentities = new JDDNode[numVars];
for (i = 0; i < numVars; i++) {
// set each element of the identity matrix
id = JDD.Constant(0);
for (j = 0; j < varList.getRange(i); j++) {
id = JDD.SetMatrixElement(id, varDDRowVars[i], varDDColVars[i], j, j, 1);
}
varIdentities[i] = id;
}
// module identities
moduleIdentities = new JDDNode[1];
// product of identities for vars in module
id = JDD.Constant(1);
for (j = 0; j < numVars; j++) {
if (varList.getModule(j) == 0) {
JDD.Ref(varIdentities[j]);
id = JDD.Apply(JDD.TIMES, id, varIdentities[j]);
}
}
moduleIdentities[0] = id;
}
// Sort DDs for ranges
private void sortRanges()
{
int i;
// initialise raneg for whole system
range = JDD.Constant(1);
// variable ranges
varRangeDDs = new JDDNode[numVars];
varColRangeDDs = new JDDNode[numVars];
for (i = 0; i < numVars; i++) {
// obtain range dd by abstracting from identity matrix
JDD.Ref(varIdentities[i]);
varRangeDDs[i] = JDD.SumAbstract(varIdentities[i], varDDColVars[i]);
// obtain range dd by abstracting from identity matrix
JDD.Ref(varIdentities[i]);
varColRangeDDs[i] = JDD.SumAbstract(varIdentities[i], varDDRowVars[i]);
// build up range for whole system as we go
JDD.Ref(varRangeDDs[i]);
range = JDD.Apply(JDD.TIMES, range, varRangeDDs[i]);
}
// module ranges
moduleRangeDDs = new JDDNode[1];
// obtain range dd by abstracting from identity matrix
JDD.Ref(moduleIdentities[0]);
moduleRangeDDs[0] = JDD.SumAbstract(moduleIdentities[0], moduleDDColVars[0]);
}
// construct transition matrix from file
private void buildTrans() throws PrismException
{
BufferedReader in;
String s, ss[];
int i, r, c, k = 0, lineNum = 0;
double d, x = 0;
boolean foundReward;
JDDNode tmp;
// initialise mtbdds
trans = JDD.Constant(0);
transRewards = JDD.Constant(0);
try {
// open file for reading
in = new BufferedReader(new FileReader(transFile));
// skip first line
in.readLine(); lineNum = 1;
// read remaining lines
s = in.readLine(); lineNum++;
while (s != null) {
foundReward = false;
// parse line, split into parts
s = s.trim();
ss = s.split(" ");
// case for dtmcs/ctmcs...
if (type != ModulesFile.NONDETERMINISTIC) {
if (ss.length < 3 || ss.length > 4) throw new PrismException("");
r = Integer.parseInt(ss[0]);
c = Integer.parseInt(ss[1]);
d = Double.parseDouble(ss[2]);
if (ss.length == 4) {
foundReward = true;
x = Double.parseDouble(ss[3]);
}
//System.out.println("("+r+","+c+") = "+d);
}
// case for mdps...
else {
if (ss.length < 4 || ss.length > 5) throw new PrismException("");
r = Integer.parseInt(ss[0]);
k = Integer.parseInt(ss[1]);
c = Integer.parseInt(ss[2]);
d = Double.parseDouble(ss[3]);
if (ss.length == 5) {
foundReward = true;
x = Double.parseDouble(ss[4]);
}
//System.out.println("("+r+","+k+","+c+") = "+d);
}
// construct element of matrix mtbdd
// case where we don't have a state list...
if (statesFile == null) {
/// ...for dtmcs/ctmcs...
if (type != ModulesFile.NONDETERMINISTIC) {
tmp = JDD.SetMatrixElement(JDD.Constant(0), varDDRowVars[0], varDDColVars[0], r, c, 1.0);
}
/// ...for mdps...
else {
tmp = JDD.Set3DMatrixElement(JDD.Constant(0), varDDRowVars[0], varDDColVars[0], allDDChoiceVars, r, c, k, 1.0);
}
}
// case where we do have a state list...
else {
tmp = JDD.Constant(1);
for (i = 0; i < numVars; i++) {
tmp = JDD.Apply(JDD.TIMES, tmp, JDD.SetVectorElement(JDD.Constant(0), varDDRowVars[i], statesArray[r][i], 1));
tmp = JDD.Apply(JDD.TIMES, tmp, JDD.SetVectorElement(JDD.Constant(0), varDDColVars[i], statesArray[c][i], 1));
}
if (type == ModulesFile.NONDETERMINISTIC) {
tmp = JDD.Apply(JDD.TIMES, tmp, JDD.SetVectorElement(JDD.Constant(0), allDDChoiceVars, k, 1));
}
}
// add it into mtbdds for transition matrix and transition rewards
JDD.Ref(tmp);
trans = JDD.Apply(JDD.PLUS, trans, JDD.Apply(JDD.TIMES, JDD.Constant(d), tmp));
if (foundReward) {
JDD.Ref(tmp);
transRewards = JDD.Apply(JDD.PLUS, transRewards, JDD.Apply(JDD.TIMES, JDD.Constant(x), tmp));
}
JDD.Deref(tmp);
// read next line
s = in.readLine(); lineNum++;
}
// close file
in.close();
}
catch (IOException e) {
throw new PrismException("File I/O error reading from \"" + transFile + "\"");
}
catch (NumberFormatException e) {
throw new PrismException("Error detected at line " + lineNum + " of transition matrix file \"" + transFile + "\"");
}
catch (PrismException e) {
throw new PrismException("Error detected " + e.getMessage() + "at line " + lineNum + " of transition matrix file \"" + transFile + "\"");
}
}
// read info about state rewards from states file
public void computeStateRewards() throws PrismException
{
BufferedReader in;
String s, ss[];
int i, j, lineNum = 0;
double d;
JDDNode tmp;
// initialise mtbdd
stateRewards = JDD.Constant(0);
if (statesFile == null) return;
try {
// open file for reading
in = new BufferedReader(new FileReader(statesFile));
// skip first line
in.readLine(); lineNum = 1;
// read remaining lines
s = in.readLine(); lineNum++;
while (s != null) {
s = s.trim();
// split into two/three parts
ss = s.split(":");
// determine which state this line describes
i = Integer.parseInt(ss[0]);
// if there is a state reward...
ss = ss[1].split("=");
if (ss.length == 2) {
// determine value
d = Double.parseDouble(ss[1]);
// construct element of vector mtbdd
// case where we don't have a state list...
if (statesFile == null) {
tmp = JDD.SetVectorElement(JDD.Constant(0), varDDRowVars[0], i, 1.0);
}
// case where we do have a state list...
else {
tmp = JDD.Constant(1);
for (j = 0; j < numVars; j++) {
tmp = JDD.Apply(JDD.TIMES, tmp, JDD.SetVectorElement(JDD.Constant(0), varDDRowVars[j], statesArray[i][j], 1));
}
}
// add it into mtbdd for state rewards
stateRewards = JDD.Apply(JDD.PLUS, stateRewards, JDD.Apply(JDD.TIMES, JDD.Constant(d), tmp));
}
// read next line
s = in.readLine(); lineNum++;
}
// close file
in.close();
}
catch (IOException e) {
throw new PrismException("File I/O error reading from \"" + statesFile + "\"");
}
catch (NumberFormatException e) {
throw new PrismException("Error detected at line " + lineNum + " of states file \"" + statesFile + "\"");
}
}
}
//------------------------------------------------------------------------------