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.
 
 
 
 
 
 

369 lines
8.5 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.util.*;
import jdd.*;
import odd.*;
import parser.Values;
import parser.VarList;
import parser.type.*;
// list of states (mtbdd)
public class StateListMTBDD implements StateList
{
// states vector mtbdd
JDDNode states;
// info from model
JDDVars vars;
int numVars;
ODDNode odd;
VarList varList;
double size;
// stuff to keep track of variable values in print method
int[] varSizes;
int[] varValues;
int currentVar;
int currentVarLevel;
// stuff to control printing limit
boolean limit;
int numToPrint;
int count;
// log for output from print method
PrismLog outputLog;
// string array when exporting
List<String> strList;
// output format
enum OutputFormat { NORMAL, MATLAB, DOT, STRINGS };
OutputFormat outputFormat = OutputFormat.NORMAL;
// Constructors
public StateListMTBDD(JDDNode s, Model model)
{
int i;
// store states vector mtbdd
states = s;
// get info from model
vars = model.getAllDDRowVars();
numVars = vars.n();
odd = model.getODD();
varList = model.getVarList();
// count number of states in list
size = JDD.GetNumMinterms(states, model.getNumDDRowVars());
// initialise arrays
varSizes = new int[varList.getNumVars()];
for (i = 0; i < varList.getNumVars(); i++) {
varSizes[i] = varList.getRangeLogTwo(i);
}
varValues = new int[varList.getNumVars()];
}
public StateListMTBDD(JDDNode s, JDDVars vars, ODDNode odd, VarList varList)
{
int i;
// store states vector mtbdd
states = s;
// get info from model
this.vars = vars;
this.numVars = vars.n();
this.odd = odd;
this.varList = varList;
// count number of states in list
size = JDD.GetNumMinterms(states, numVars);
// initialise arrays
varSizes = new int[varList.getNumVars()];
for (i = 0; i < varList.getNumVars(); i++) {
varSizes[i] = varList.getRangeLogTwo(i);
}
varValues = new int[varList.getNumVars()];
}
// return size (number of states in list)
public int size()
{
return (size > Integer.MAX_VALUE) ? -1 : (int)Math.round(size);
}
public String sizeString()
{
return (size > Long.MAX_VALUE) ? "" + size : "" + Math.round(size);
}
// print/export whole list
public void print(PrismLog log)
{
outputFormat = OutputFormat.NORMAL;
limit = false;
outputLog = log;
doPrint();
if (count == 0)
outputLog.println("(none)");
}
public void printMatlab(PrismLog log)
{
outputFormat = OutputFormat.MATLAB;
limit = false;
outputLog = log;
doPrint();
}
public void printDot(PrismLog log)
{
outputFormat = OutputFormat.DOT;
limit = false;
outputLog = log;
doPrint();
}
public List<String> exportToStringList()
{
strList = new ArrayList<String>((int)size);
outputFormat = OutputFormat.STRINGS;
limit = false;
doPrint();
return strList;
}
// print first n states of list
public void print(PrismLog log, int n)
{
outputFormat = OutputFormat.NORMAL;
limit = true;
numToPrint = n;
outputLog = log;
doPrint();
if (count == 0)
outputLog.println("(none)");
}
public void printMatlab(PrismLog log, int n)
{
outputFormat = OutputFormat.MATLAB;
limit = true;
numToPrint = n;
outputLog = log;
doPrint();
}
// printing method
public void doPrint()
{
int i;
count = 0;
for (i = 0; i < varList.getNumVars(); i++) {
varValues[i] = 0;
}
currentVar = 0;
currentVarLevel = 0;
printRec(states, 0, odd, 0);
//log.println();
}
// recursive bit of print
// (nb: traversal of mtbdd/odd is quite simple,
// tricky bit is keeping track of variable values
// throughout traversal - we want to be efficient
// and not compute the values from scratch each
// time, but we also want to avoid passing arrays
// into the resursive method)
private void printRec(JDDNode dd, int level, ODDNode o, long n)
{
int i, j;
JDDNode e, t;
String varsString;
// if we've printed enough states, stop
if (limit) if (count >= numToPrint) return;
// zero constant - bottom out of recursion
if (dd.equals(JDD.ZERO)) return;
// base case - at bottom (nonzero terminal)
if (level == numVars) {
switch (outputFormat) {
case NORMAL: outputLog.print(n + ":("); break;
case MATLAB: break;
case DOT: outputLog.print(n + " [label=\"" + n + "\\n("); break;
}
j = varList.getNumVars();
varsString = "";
for (i = 0; i < j; i++) {
// integer variable
if (varList.getType(i) instanceof TypeInt) {
varsString += varValues[i]+varList.getLow(i);
}
// boolean variable
else {
varsString += (varValues[i] == 1);
}
if (i < j-1) varsString += ",";
}
switch (outputFormat) {
case NORMAL: outputLog.println(varsString + ")"); break;
case MATLAB: outputLog.println(varsString); break;
case DOT: outputLog.println(varsString + ")\"];"); break;
case STRINGS: strList.add(varsString);
}
count++;
return;
}
// select else and then branches
else if (dd.getIndex() > vars.getVarIndex(level)) {
e = t = dd;
}
else {
e = dd.getElse();
t = dd.getThen();
}
// then recurse...
currentVarLevel++; if (currentVarLevel == varSizes[currentVar]) { currentVar++; currentVarLevel=0; }
printRec(e, level+1, o.getElse(), n);
currentVarLevel--; if (currentVarLevel == -1) { currentVar--; currentVarLevel=varSizes[currentVar]-1; }
varValues[currentVar] += (1 << (varSizes[currentVar]-1-currentVarLevel));
currentVarLevel++; if (currentVarLevel == varSizes[currentVar]) { currentVar++; currentVarLevel=0; }
printRec(t, level+1, o.getThen(), n+o.getEOff());
currentVarLevel--; if (currentVarLevel == -1) { currentVar--; currentVarLevel=varSizes[currentVar]-1; }
varValues[currentVar] -= (1 << (varSizes[currentVar]-1-currentVarLevel));
}
/**
* Check for (partial) state inclusion - state(s) given by BDD
*/
public boolean includes(JDDNode state)
{
JDDNode tmp;
boolean incl;
JDD.Ref(states);
JDD.Ref(state);
tmp = JDD.And(states, state);
incl = !tmp.equals(JDD.ZERO);
JDD.Deref(tmp);
return incl;
}
/**
* Check for (full) state inclusion - state(s) given by BDD
*/
public boolean includesAll(JDDNode state)
{
JDDNode tmp;
boolean incl;
JDD.Ref(states);
JDD.Ref(state);
tmp = JDD.And(states, state);
incl = tmp.equals(state);
JDD.Deref(tmp);
return incl;
}
// get first state as Values object
public Values getFirstAsValues() throws PrismException
{
Values values;
int i, j, n, n2, level, v;
JDDNode first, tmp;
Object o;
// check there is a first state
if (size < 1) throw new PrismException("The state list contains no states");
// get bdd of first state
JDD.Ref(states);
first = JDD.RestrictToFirst(states, vars);
// traverse bdd, top to bottom, getting val (v) for each var
tmp = states;
values = new Values();
n = varList.getNumVars();
level = 0;
for (i = 0; i < n; i++) {
v = 0;
n2 = varSizes[i];
for (j = 0; j < n2; j++) {
if (tmp.getIndex() > vars.getVarIndex(level)) {
// tmp = tmp;
} else if (!tmp.getElse().equals(JDD.ZERO)) {
tmp = tmp.getElse();
} else {
tmp = tmp.getThen();
v += (1 << (n2-1-j));
}
level++;
}
v += varList.getLow(i);
if (varList.getType(i) instanceof TypeInt) {
o = new Integer(v);
} else {
o = new Boolean(v == 1);
}
values.addValue(varList.getName(i), o);
}
// derefs
JDD.Deref(first);
return values;
}
// clear
public void clear()
{
JDD.Deref(states);
}
}