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.
3918 lines
123 KiB
3918 lines
123 KiB
//==============================================================================
|
|
//
|
|
// Authors:
|
|
// * Dave Parker <david.parker@comlab.ox.ac.uk> (University of Oxford, formerly University of Birmingham)
|
|
// * Andrew Hinton <ug60axh@cs.bham.ac.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
|
|
//
|
|
//==============================================================================
|
|
|
|
package prism;
|
|
|
|
import hybrid.PrismHybrid;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileWriter;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import jdd.JDD;
|
|
import jdd.JDDNode;
|
|
import jdd.JDDVars;
|
|
import mtbdd.PrismMTBDD;
|
|
import odd.ODDUtils;
|
|
import param.BigRational;
|
|
import param.ModelBuilder;
|
|
import param.ParamModelChecker;
|
|
import param.RegionValues;
|
|
import parser.ExplicitFiles2ModulesFile;
|
|
import parser.PrismParser;
|
|
import parser.State;
|
|
import parser.Values;
|
|
import parser.ast.ConstantList;
|
|
import parser.ast.Expression;
|
|
import parser.ast.ForLoop;
|
|
import parser.ast.FormulaList;
|
|
import parser.ast.LabelList;
|
|
import parser.ast.ModulesFile;
|
|
import parser.ast.PropertiesFile;
|
|
import parser.ast.Property;
|
|
import pta.DigitalClocks;
|
|
import pta.PTAModelChecker;
|
|
import simulator.GenerateSimulationPath;
|
|
import simulator.PrismModelExplorer;
|
|
import simulator.SimulatorEngine;
|
|
import simulator.method.SimulationMethod;
|
|
import sparse.PrismSparse;
|
|
import strat.Strategy;
|
|
import dv.DoubleVector;
|
|
import explicit.CTMC;
|
|
import explicit.CTMCModelChecker;
|
|
import explicit.ConstructModel;
|
|
import explicit.DTMC;
|
|
import explicit.DTMCModelChecker;
|
|
import explicit.FastAdaptiveUniformisation;
|
|
import explicit.FastAdaptiveUniformisationModelChecker;
|
|
|
|
/**
|
|
* Main class for all PRISM's core functionality.
|
|
* This is independent of the user interface (command line or gui).
|
|
*/
|
|
public class Prism extends PrismComponent implements PrismSettingsListener
|
|
{
|
|
/** PRISM version (e.g. "4.0.3"). Read from prism.Version. */
|
|
private static String version = prism.Version.versionString;
|
|
|
|
/** Optional PRISM version suffix (e.g. "dev", "beta"). Read from prism.Version. */
|
|
private static String versionSuffix = prism.Version.versionSuffixString;
|
|
|
|
/** Build number (e.g. "6667"). Defaults to "" (undefined), read from prism.Revision class if present. */
|
|
private static String buildNumber = "";
|
|
static {
|
|
try {
|
|
buildNumber = Prism.class.getClassLoader().loadClass("prism.Revision").getField("svnRevision").get(null).toString();
|
|
} catch (Exception e) {
|
|
// Any problems (e.g. class not created), ignore.
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Constants
|
|
//------------------------------------------------------------------------------
|
|
|
|
// underlying computation engine
|
|
public static final int MTBDD = 1;
|
|
public static final int SPARSE = 2;
|
|
public static final int HYBRID = 3;
|
|
public static final int EXPLICIT = 4;
|
|
private static String[] engineStrings = { "?", "MTBDD", "Sparse", "Hybrid", "Explicit" };
|
|
|
|
// methods for solving linear equation systems
|
|
public static final int POWER = 1;
|
|
public static final int JACOBI = 2;
|
|
public static final int GAUSSSEIDEL = 3;
|
|
public static final int BGAUSSSEIDEL = 4;
|
|
public static final int PGAUSSSEIDEL = 5;
|
|
public static final int BPGAUSSSEIDEL = 6;
|
|
public static final int JOR = 7;
|
|
public static final int SOR = 8;
|
|
public static final int BSOR = 9;
|
|
public static final int PSOR = 10;
|
|
public static final int BPSOR = 11;
|
|
|
|
// methods for solving MDPs
|
|
public static final int MDP_VALITER = 1;
|
|
public static final int MDP_GAUSSSEIDEL = 2;
|
|
public static final int MDP_POLITER = 3;
|
|
public static final int MDP_MODPOLITER = 4;
|
|
public static final int MDP_LP = 5;
|
|
|
|
// methods for solving multi-objective queries on MDPs
|
|
public static final int MDP_MULTI_VALITER = 1;
|
|
public static final int MDP_MULTI_GAUSSSEIDEL = 2;
|
|
public static final int MDP_MULTI_LP = 3;
|
|
|
|
// termination criterion for iterative methods
|
|
public static final int ABSOLUTE = 1;
|
|
public static final int RELATIVE = 2;
|
|
|
|
// options for model matrix export
|
|
public static final int EXPORT_PLAIN = 1;
|
|
public static final int EXPORT_MATLAB = 2;
|
|
public static final int EXPORT_DOT = 3;
|
|
public static final int EXPORT_MRMC = 4;
|
|
public static final int EXPORT_ROWS = 5;
|
|
public static final int EXPORT_DOT_STATES = 6;
|
|
|
|
// options for adversary export
|
|
public static final int EXPORT_ADV_NONE = 1;
|
|
public static final int EXPORT_ADV_DTMC = 2;
|
|
public static final int EXPORT_ADV_MDP = 3;
|
|
|
|
// methods for SCC decomposition
|
|
public static final int XIEBEEREL = 1;
|
|
public static final int LOCKSTEP = 2;
|
|
public static final int SCCFIND = 3;
|
|
|
|
// Options for type of strategy export
|
|
public enum StrategyExportType {
|
|
ACTIONS, INDICES, INDUCED_MODEL, DOT_FILE;
|
|
public String description()
|
|
{
|
|
switch (this) {
|
|
case ACTIONS:
|
|
return "as actions";
|
|
case INDICES:
|
|
return "as indices";
|
|
case INDUCED_MODEL:
|
|
return "as an induced model";
|
|
case DOT_FILE:
|
|
return "as a dot file";
|
|
default:
|
|
return this.toString();
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Settings / flags / options
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Export parsed PRISM model?
|
|
protected boolean exportPrism = false;
|
|
protected File exportPrismFile = null;
|
|
protected boolean exportPrismConst = false;
|
|
protected File exportPrismConstFile = null;
|
|
// Export digital clocks translation PRISM model?
|
|
protected boolean exportDigital = false;
|
|
protected File exportDigitalFile = null;
|
|
// Export target state info?
|
|
protected boolean exportTarget = false;
|
|
protected String exportTargetFilename = null;
|
|
// Export product model info?
|
|
protected boolean exportProductTrans = false;
|
|
protected String exportProductTransFilename = null;
|
|
protected boolean exportProductStates = false;
|
|
protected String exportProductStatesFilename = null;
|
|
// Store the final results vector after model checking?
|
|
protected boolean storeVector = false;
|
|
// Generate/store a strategy during model checking?
|
|
protected boolean genStrat = false;
|
|
// Do bisimulation minimisation before model checking?
|
|
protected boolean doBisim = false;
|
|
|
|
// A few miscellaneous options (i.e. defunct/hidden/undocumented/etc.)
|
|
// See constructor below for default values
|
|
|
|
private boolean doReach = true; // do reachability? (sometimes might want to skip it)
|
|
private boolean bsccComp = true; // do bscc computation before steady-state?
|
|
private boolean checkZeroLoops = false;
|
|
|
|
// MTBDD construction method (NOW DEFUNCT)
|
|
// 1 - use with ordering 1: nondet vars form a tree at the top
|
|
// 3 - use with ordering 2: zero for nonexistant bits
|
|
// nb: option 2 removed because it was stupid
|
|
private int construction = 3;
|
|
|
|
// MTBDD variable ordering
|
|
// 1 - (s ... s) (l ... l) (r c ... r c)
|
|
// 2 - (s l ... l r c ... r c) (s l ... l r c ... r c) ...
|
|
private int ordering = 1;
|
|
|
|
// Method to use for (symbolic) state-space reachability
|
|
private int reachMethod = REACH_BFS;
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Logs
|
|
//------------------------------------------------------------------------------
|
|
|
|
private PrismLog techLog; // log for technical/diagnostic output
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parsers/translators/model checkers/simulators/etc.
|
|
//------------------------------------------------------------------------------
|
|
|
|
private static PrismParser thePrismParser = null;
|
|
private static boolean prismParserInUse = false;
|
|
private ExplicitFiles2MTBDD expf2mtbdd = null;
|
|
private ExplicitModel2MTBDD expm2mtbdd = null;
|
|
private SimulatorEngine theSimulator = null;
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Event listeners
|
|
//------------------------------------------------------------------------------
|
|
|
|
private List<PrismModelListener> modelListeners;
|
|
|
|
//------------------------------------------------------------------------------
|
|
// State
|
|
//------------------------------------------------------------------------------
|
|
|
|
private enum ModelSource {
|
|
PRISM_MODEL, EXPLICIT_FILES, BUILT_MODEL
|
|
}
|
|
|
|
// Info about currently loaded model, if any
|
|
// Model source
|
|
private ModelSource currentModelSource = ModelSource.PRISM_MODEL;
|
|
// Model type
|
|
private ModelType currentModelType = null;
|
|
// PRISM model (null if none loaded, or built model given directly)
|
|
private ModulesFile currentModulesFile = null;
|
|
// Constants to be defined for PRISM model
|
|
private Values currentDefinedMFConstants = null;
|
|
// Built model storage - symbolic or explicit - at most one is non-null
|
|
private Model currentModel = null;
|
|
private explicit.Model currentModelExpl = null;
|
|
// Are we doing digital clocks translation for PTAs?
|
|
boolean digital = false;
|
|
|
|
// Info for explicit files load
|
|
private File explicitFilesStatesFile = null;
|
|
private File explicitFilesTransFile = null;
|
|
private File explicitFilesLabelsFile = null;
|
|
private int explicitFilesNumStates = -1;
|
|
|
|
// Has the CUDD library been initialised yet?
|
|
private boolean cuddStarted = false;
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Constructors + options methods
|
|
//------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Construct a new Prism object.
|
|
* @param mainLog PrismLog where all output will be sent.
|
|
*/
|
|
public Prism(PrismLog mainLog)
|
|
{
|
|
this(mainLog, mainLog);
|
|
}
|
|
|
|
/**
|
|
* Construct a new Prism object.
|
|
* @param mainLog PrismLog where messages and model checking output will be sent.
|
|
* @param techLog PrismLog for output of detailed technical info (not really used).
|
|
*/
|
|
public Prism(PrismLog mainLog, PrismLog techLog)
|
|
{
|
|
// set up logs
|
|
this.mainLog = mainLog;
|
|
this.techLog = techLog;
|
|
|
|
// set up some default options
|
|
settings = new PrismSettings();
|
|
// add this Prism object as a results listener
|
|
settings.addSettingsListener(this);
|
|
// create list of model listeners
|
|
modelListeners = new ArrayList<PrismModelListener>();
|
|
}
|
|
|
|
/**
|
|
* Read in PRISM settings from the default file (.prism in user's home directory).
|
|
* If no file exists, attempt to create a new one with default settings.
|
|
*/
|
|
public void loadUserSettingsFile()
|
|
{
|
|
loadUserSettingsFile(null);
|
|
}
|
|
|
|
/**
|
|
* Read in PRISM settings from a specified file.
|
|
* If the file is null, use the default (.prism in user's home directory).
|
|
* If no file exists, attempt to create a new one with default settings.
|
|
*/
|
|
public void loadUserSettingsFile(File settingsFile)
|
|
{
|
|
// load user's default settings
|
|
try {
|
|
if (settingsFile == null)
|
|
settings.loadSettingsFile();
|
|
else
|
|
settings.loadSettingsFile(settingsFile);
|
|
} catch (PrismException e) {
|
|
// if there were no user defaults to load, create them
|
|
try {
|
|
if (settingsFile == null)
|
|
settings.saveSettingsFile();
|
|
else
|
|
settings.saveSettingsFile(settingsFile);
|
|
} catch (PrismException ex) {
|
|
mainLog.printWarning("Failed to create new PRISM settings file.");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set methods
|
|
|
|
/**
|
|
* Set the PrismLog where messages and model checking output will be sent.
|
|
*/
|
|
public void setMainLog(PrismLog l)
|
|
{
|
|
// store new log
|
|
mainLog = l;
|
|
// pass to other components
|
|
PrismMTBDD.setMainLog(mainLog);
|
|
PrismSparse.setMainLog(mainLog);
|
|
PrismHybrid.setMainLog(mainLog);
|
|
}
|
|
|
|
/**
|
|
* Set the PrismLog for output of detailed technical info (not really used).
|
|
*/
|
|
public void setTechLog(PrismLog l)
|
|
{
|
|
// store new log
|
|
techLog = l;
|
|
// pass to other components
|
|
JDD.SetOutputStream(techLog.getFilePointer());
|
|
PrismMTBDD.setTechLog(techLog);
|
|
PrismSparse.setTechLog(techLog);
|
|
PrismHybrid.setTechLog(techLog);
|
|
}
|
|
|
|
// Set methods for main prism settings
|
|
// (provided for convenience and for compatibility with old code)
|
|
|
|
public void setEngine(int e) throws PrismException
|
|
{
|
|
settings.setChoice(PrismSettings.PRISM_ENGINE, e);
|
|
}
|
|
|
|
public void setVerbose(boolean b) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_VERBOSE, b);
|
|
}
|
|
|
|
public void setFairness(boolean b) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_FAIRNESS, b);
|
|
}
|
|
|
|
public void setPrecomp(boolean b) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_PRECOMPUTATION, b);
|
|
}
|
|
|
|
public void setProb0(boolean b) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_PROB0, b);
|
|
}
|
|
|
|
public void setProb1(boolean b) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_PROB1, b);
|
|
}
|
|
|
|
public void setFixDeadlocks(boolean b) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_FIX_DEADLOCKS, b);
|
|
}
|
|
|
|
public void setDoProbChecks(boolean b) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_DO_PROB_CHECKS, b);
|
|
}
|
|
|
|
public void setSumRoundOff(double d) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_SUM_ROUND_OFF, d);
|
|
}
|
|
|
|
public void setCompact(boolean b) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_COMPACT, b);
|
|
}
|
|
|
|
public void setLinEqMethod(int i) throws PrismException
|
|
{
|
|
settings.setChoice(PrismSettings.PRISM_LIN_EQ_METHOD, i);
|
|
}
|
|
|
|
public void setLinEqMethodParam(double d) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_LIN_EQ_METHOD_PARAM, d);
|
|
}
|
|
|
|
public void setMDPSolnMethod(int i) throws PrismException
|
|
{
|
|
settings.setChoice(PrismSettings.PRISM_MDP_SOLN_METHOD, i);
|
|
}
|
|
|
|
public void setMDPMultiSolnMethod(int i) throws PrismException
|
|
{
|
|
settings.setChoice(PrismSettings.PRISM_MDP_MULTI_SOLN_METHOD, i);
|
|
}
|
|
|
|
public void setTermCrit(int i) throws PrismException
|
|
{
|
|
settings.setChoice(PrismSettings.PRISM_TERM_CRIT, i);
|
|
}
|
|
|
|
public void setTermCritParam(double d) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_TERM_CRIT_PARAM, d);
|
|
}
|
|
|
|
public void setMaxIters(int i) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_MAX_ITERS, i);
|
|
}
|
|
|
|
public void setCUDDMaxMem(String s) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_CUDD_MAX_MEM, s);
|
|
}
|
|
|
|
public void setCUDDEpsilon(double d) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_CUDD_EPSILON, d);
|
|
}
|
|
|
|
public void setNumSBLevels(int i) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_NUM_SB_LEVELS, i);
|
|
}
|
|
|
|
public void setSBMaxMem(int i) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_SB_MAX_MEM, i);
|
|
}
|
|
|
|
public void setNumSORLevels(int i) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_NUM_SOR_LEVELS, i);
|
|
}
|
|
|
|
public void setSORMaxMem(int i) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_SOR_MAX_MEM, i);
|
|
}
|
|
|
|
public void setDoSSDetect(boolean b) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_DO_SS_DETECTION, b);
|
|
}
|
|
|
|
public void setExtraDDInfo(boolean b) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_EXTRA_DD_INFO, b);
|
|
}
|
|
|
|
public void setExtraReachInfo(boolean b) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_EXTRA_REACH_INFO, b);
|
|
}
|
|
|
|
public void setSCCMethod(int i) throws PrismException
|
|
{
|
|
settings.setChoice(PrismSettings.PRISM_SCC_METHOD, i);
|
|
}
|
|
|
|
public void setExportAdv(int i) throws PrismException
|
|
{
|
|
settings.setChoice(PrismSettings.PRISM_EXPORT_ADV, i);
|
|
}
|
|
|
|
public void setExportAdvFilename(String s) throws PrismException
|
|
{
|
|
settings.set(PrismSettings.PRISM_EXPORT_ADV_FILENAME, s);
|
|
}
|
|
|
|
// Set methods for miscellaneous options
|
|
|
|
public void setExportPrism(boolean b) throws PrismException
|
|
{
|
|
exportPrism = b;
|
|
}
|
|
|
|
/**
|
|
* Set file to export parsed PRISM file to (null = stdout).
|
|
*/
|
|
public void setExportPrismFile(File f) throws PrismException
|
|
{
|
|
exportPrismFile = f;
|
|
}
|
|
|
|
public void setExportPrismConst(boolean b) throws PrismException
|
|
{
|
|
exportPrismConst = b;
|
|
}
|
|
|
|
/**
|
|
* Set file to export parsed PRISM file, with constants expanded, to (null = stdout).
|
|
*/
|
|
public void setExportPrismConstFile(File f) throws PrismException
|
|
{
|
|
exportPrismConstFile = f;
|
|
}
|
|
|
|
public void setExportDigital(boolean b) throws PrismException
|
|
{
|
|
exportDigital = b;
|
|
}
|
|
|
|
/**
|
|
* Set file to export digital clocks translation PRISM file to (null = stdout).
|
|
*/
|
|
public void setExportDigitalFile(File f) throws PrismException
|
|
{
|
|
exportDigitalFile = f;
|
|
}
|
|
|
|
public void setExportTarget(boolean b) throws PrismException
|
|
{
|
|
exportTarget = b;
|
|
}
|
|
|
|
public void setExportTargetFilename(String s) throws PrismException
|
|
{
|
|
exportTargetFilename = s;
|
|
}
|
|
|
|
public void setExportProductTrans(boolean b) throws PrismException
|
|
{
|
|
exportProductTrans = b;
|
|
}
|
|
|
|
public void setExportProductTransFilename(String s) throws PrismException
|
|
{
|
|
exportProductTransFilename = s;
|
|
}
|
|
|
|
public void setExportProductStates(boolean b) throws PrismException
|
|
{
|
|
exportProductStates = b;
|
|
}
|
|
|
|
public void setExportProductStatesFilename(String s) throws PrismException
|
|
{
|
|
exportProductStatesFilename = s;
|
|
}
|
|
|
|
/**
|
|
* Specify whether or not to store the final results vector after model checking.
|
|
*/
|
|
public void setStoreVector(boolean storeVector)
|
|
{
|
|
this.storeVector = storeVector;
|
|
}
|
|
|
|
/**
|
|
* Specify whether or not a strategy should be generated during model checking.
|
|
*/
|
|
public void setGenStrat(boolean genStrat)
|
|
{
|
|
this.genStrat = genStrat;
|
|
}
|
|
|
|
/**
|
|
* Specify whether or not to do bisimulation minimisation before model checking.
|
|
*/
|
|
public void setDoBisim(boolean doBisim)
|
|
{
|
|
this.doBisim = doBisim;
|
|
}
|
|
|
|
public void setDoReach(boolean b) throws PrismException
|
|
{
|
|
doReach = b;
|
|
}
|
|
|
|
public void setBSCCComp(boolean b) throws PrismException
|
|
{
|
|
bsccComp = b;
|
|
}
|
|
|
|
public void setCheckZeroLoops(boolean checkZeroLoops)
|
|
{
|
|
this.checkZeroLoops = checkZeroLoops;
|
|
}
|
|
|
|
public void setConstruction(int i) throws PrismException
|
|
{
|
|
construction = i;
|
|
}
|
|
|
|
public void setOrdering(int i) throws PrismException
|
|
{
|
|
ordering = i;
|
|
}
|
|
|
|
public static int REACH_BFS = 1;
|
|
public static int REACH_FRONTIER = 2;
|
|
|
|
public void setReachMethod(int reachMethod)
|
|
{
|
|
this.reachMethod = reachMethod;
|
|
}
|
|
|
|
// Get methods
|
|
|
|
/**
|
|
* Get current version number, as a string.
|
|
*/
|
|
public static String getVersion()
|
|
{
|
|
String v = version;
|
|
// Append version suffix (e.g. "dev", "beta") if non-empty
|
|
if (versionSuffix.length() > 0) {
|
|
v += "." + versionSuffix;
|
|
// In this case, also append any build number
|
|
if (buildNumber.length() > 0)
|
|
v += ".r" + buildNumber;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
/**
|
|
* Get build number (SVN revision) for current version. Returns "" if not set up.
|
|
*/
|
|
public static String getBuildNumber()
|
|
{
|
|
return buildNumber;
|
|
}
|
|
|
|
public PrismLog getMainLog()
|
|
{
|
|
return mainLog;
|
|
}
|
|
|
|
public PrismLog getTechLog()
|
|
{
|
|
return techLog;
|
|
}
|
|
|
|
public PrismSettings getSettings()
|
|
{
|
|
return settings;
|
|
}
|
|
|
|
// Get methods for main prism settings
|
|
// (as above, provided for convenience and for compatibility with old code)
|
|
|
|
public int getEngine()
|
|
{
|
|
return settings.getChoice(PrismSettings.PRISM_ENGINE);
|
|
}
|
|
|
|
/**
|
|
* Is the current engine "Explicit"?
|
|
*/
|
|
public boolean getExplicit()
|
|
{
|
|
return getEngine() == Prism.EXPLICIT;
|
|
}
|
|
|
|
public boolean getFixDeadlocks()
|
|
{
|
|
return settings.getBoolean(PrismSettings.PRISM_FIX_DEADLOCKS);
|
|
}
|
|
|
|
public boolean getDoProbChecks()
|
|
{
|
|
return settings.getBoolean(PrismSettings.PRISM_DO_PROB_CHECKS);
|
|
}
|
|
|
|
public double getSumRoundOff()
|
|
{
|
|
return settings.getDouble(PrismSettings.PRISM_SUM_ROUND_OFF);
|
|
}
|
|
|
|
public int getLinEqMethod()
|
|
{
|
|
return settings.getChoice(PrismSettings.PRISM_LIN_EQ_METHOD);
|
|
}
|
|
|
|
public double getLinEqMethodParam()
|
|
{
|
|
return settings.getDouble(PrismSettings.PRISM_LIN_EQ_METHOD_PARAM);
|
|
}
|
|
|
|
public int getMDPSolnMethod()
|
|
{
|
|
return settings.getChoice(PrismSettings.PRISM_MDP_SOLN_METHOD);
|
|
}
|
|
|
|
public int getMDPMultiSolnMethod()
|
|
{
|
|
return settings.getChoice(PrismSettings.PRISM_MDP_MULTI_SOLN_METHOD);
|
|
}
|
|
|
|
public int getTermCrit()
|
|
{
|
|
return settings.getChoice(PrismSettings.PRISM_TERM_CRIT);
|
|
}
|
|
|
|
public double getTermCritParam()
|
|
{
|
|
return settings.getDouble(PrismSettings.PRISM_TERM_CRIT_PARAM);
|
|
}
|
|
|
|
public int getMaxIters()
|
|
{
|
|
return settings.getInteger(PrismSettings.PRISM_MAX_ITERS);
|
|
}
|
|
|
|
public boolean getVerbose()
|
|
{
|
|
return settings.getBoolean(PrismSettings.PRISM_VERBOSE);
|
|
}
|
|
|
|
public boolean getPrecomp()
|
|
{
|
|
return settings.getBoolean(PrismSettings.PRISM_PRECOMPUTATION);
|
|
}
|
|
|
|
public boolean getProb0()
|
|
{
|
|
return settings.getBoolean(PrismSettings.PRISM_PROB0);
|
|
}
|
|
|
|
public boolean getProb1()
|
|
{
|
|
return settings.getBoolean(PrismSettings.PRISM_PROB1);
|
|
}
|
|
|
|
public boolean getPreRel()
|
|
{
|
|
return settings.getBoolean(PrismSettings.PRISM_PRE_REL);
|
|
}
|
|
|
|
public boolean getFairness()
|
|
{
|
|
return settings.getBoolean(PrismSettings.PRISM_FAIRNESS);
|
|
}
|
|
|
|
public int getSBMaxMem()
|
|
{
|
|
return settings.getInteger(PrismSettings.PRISM_SB_MAX_MEM);
|
|
}
|
|
|
|
public int getNumSBLevels()
|
|
{
|
|
return settings.getInteger(PrismSettings.PRISM_NUM_SB_LEVELS);
|
|
}
|
|
|
|
public int getSORMaxMem()
|
|
{
|
|
return settings.getInteger(PrismSettings.PRISM_SOR_MAX_MEM);
|
|
}
|
|
|
|
public boolean getDoSSDetect()
|
|
{
|
|
return settings.getBoolean(PrismSettings.PRISM_DO_SS_DETECTION);
|
|
}
|
|
|
|
public boolean getExtraDDInfo()
|
|
{
|
|
return settings.getBoolean(PrismSettings.PRISM_EXTRA_DD_INFO);
|
|
}
|
|
|
|
public boolean getExtraReachInfo()
|
|
{
|
|
return settings.getBoolean(PrismSettings.PRISM_EXTRA_REACH_INFO);
|
|
}
|
|
|
|
public int getNumSORLevels()
|
|
{
|
|
return settings.getInteger(PrismSettings.PRISM_NUM_SOR_LEVELS);
|
|
}
|
|
|
|
public boolean getCompact()
|
|
{
|
|
return settings.getBoolean(PrismSettings.PRISM_COMPACT);
|
|
}
|
|
|
|
public String getCUDDMaxMem()
|
|
{
|
|
return settings.getString(PrismSettings.PRISM_CUDD_MAX_MEM);
|
|
}
|
|
|
|
public double getCUDDEpsilon()
|
|
{
|
|
return settings.getDouble(PrismSettings.PRISM_CUDD_EPSILON);
|
|
}
|
|
|
|
public int getSCCMethod()
|
|
{
|
|
return settings.getChoice(PrismSettings.PRISM_SCC_METHOD);
|
|
}
|
|
|
|
public int getExportAdv()
|
|
{
|
|
return settings.getChoice(PrismSettings.PRISM_EXPORT_ADV);
|
|
}
|
|
|
|
public String getExportAdvFilename()
|
|
{
|
|
return settings.getString(PrismSettings.PRISM_EXPORT_ADV_FILENAME);
|
|
}
|
|
|
|
// Get methods for miscellaneous options
|
|
|
|
public boolean getExportPrism()
|
|
{
|
|
return exportPrism;
|
|
}
|
|
|
|
public File getExportPrismFile()
|
|
{
|
|
return exportPrismFile;
|
|
}
|
|
|
|
public boolean getExportPrismConst()
|
|
{
|
|
return exportPrismConst;
|
|
}
|
|
|
|
public File getExportPrismConstFile()
|
|
{
|
|
return exportPrismConstFile;
|
|
}
|
|
|
|
public boolean getExportTarget()
|
|
{
|
|
return exportTarget;
|
|
}
|
|
|
|
public String getExportTargetFilename()
|
|
{
|
|
return exportTargetFilename;
|
|
}
|
|
|
|
public boolean getExportProductTrans()
|
|
{
|
|
return exportProductTrans;
|
|
}
|
|
|
|
public String getExportProductTransFilename()
|
|
{
|
|
return exportProductTransFilename;
|
|
}
|
|
|
|
public boolean getExportProductStates()
|
|
{
|
|
return exportProductStates;
|
|
}
|
|
|
|
public String getExportProductStatesFilename()
|
|
{
|
|
return exportProductStatesFilename;
|
|
}
|
|
|
|
/**
|
|
* Whether or not to store the final results vector after model checking.
|
|
*/
|
|
public boolean getStoreVector()
|
|
{
|
|
return storeVector;
|
|
}
|
|
|
|
/**
|
|
* Whether or not a strategy should be generated during model checking.
|
|
*/
|
|
public boolean getGenStrat()
|
|
{
|
|
return genStrat;
|
|
}
|
|
|
|
/**
|
|
* Whether or not to do bisimulation minimisation before model checking.
|
|
*/
|
|
public boolean getDoBisim()
|
|
{
|
|
return doBisim;
|
|
}
|
|
|
|
public boolean getDoReach()
|
|
{
|
|
return doReach;
|
|
}
|
|
|
|
public boolean getBSCCComp()
|
|
{
|
|
return bsccComp;
|
|
}
|
|
|
|
public boolean getCheckZeroLoops()
|
|
{
|
|
return this.checkZeroLoops;
|
|
}
|
|
|
|
public int getConstruction()
|
|
{
|
|
return construction;
|
|
}
|
|
|
|
public int getOrdering()
|
|
{
|
|
return ordering;
|
|
}
|
|
|
|
public int getReachMethod()
|
|
{
|
|
return reachMethod;
|
|
}
|
|
|
|
public void addModelListener(PrismModelListener listener)
|
|
{
|
|
modelListeners.add(listener);
|
|
}
|
|
|
|
// String methods for options
|
|
|
|
public static String getEngineString(int engine)
|
|
{
|
|
return engineStrings[engine];
|
|
}
|
|
|
|
/**
|
|
* Let PrismSettings object notify us things have changed
|
|
*/
|
|
public void notifySettings(PrismSettings settings)
|
|
{
|
|
if (cuddStarted) {
|
|
JDD.SetCUDDEpsilon(settings.getDouble(PrismSettings.PRISM_CUDD_EPSILON));
|
|
try {
|
|
long cuddMaxMem = PrismUtils.convertMemoryStringtoKB(getCUDDMaxMem());
|
|
JDD.SetCUDDMaxMem(cuddMaxMem);
|
|
} catch (PrismException e) {
|
|
// Fail silently if memory string is invalid
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Access to parser, simulator, etc.
|
|
//------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Get (exclusive) access to the PRISM parser.
|
|
*/
|
|
public static PrismParser getPrismParser() throws InterruptedException
|
|
{
|
|
// Note: this mutex mechanism is based on public domain code by Doug Lea
|
|
if (Thread.interrupted())
|
|
throw new InterruptedException();
|
|
// this code is synchronized on the whole Prism class
|
|
// (because this is a static method)
|
|
synchronized (Prism.class) {
|
|
try {
|
|
// wait until parser is free
|
|
while (prismParserInUse) {
|
|
Prism.class.wait();
|
|
}
|
|
// lock parser
|
|
prismParserInUse = true;
|
|
// return parser, creating anew if necessary
|
|
if (thePrismParser == null)
|
|
thePrismParser = new PrismParser();
|
|
return thePrismParser;
|
|
} catch (InterruptedException e) {
|
|
Prism.class.notify();
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Release (exclusive) access to the PRISM parser.
|
|
*/
|
|
public static synchronized void releasePrismParser()
|
|
{
|
|
prismParserInUse = false;
|
|
Prism.class.notify();
|
|
}
|
|
|
|
/**
|
|
* Get the SimulatorEngine object for PRISM, creating if necessary.
|
|
*/
|
|
public SimulatorEngine getSimulator()
|
|
{
|
|
if (theSimulator == null) {
|
|
theSimulator = new SimulatorEngine(this);
|
|
}
|
|
return theSimulator;
|
|
}
|
|
|
|
/**
|
|
* Get an SCCComputer object.
|
|
* Type (i.e. algorithm) depends on SCCMethod PRISM option.
|
|
*/
|
|
public SCCComputer getSCCComputer(Model model) throws PrismException
|
|
{
|
|
return SCCComputer.createSCCComputer(this, model);
|
|
}
|
|
|
|
/**
|
|
* Get an SCCComputer object.
|
|
* Type (i.e. algorithm) depends on SCCMethod PRISM option.
|
|
*/
|
|
public SCCComputer getSCCComputer(JDDNode reach, JDDNode trans01, JDDVars allDDRowVars, JDDVars allDDColVars) throws PrismException
|
|
{
|
|
return SCCComputer.createSCCComputer(this, reach, trans01, allDDRowVars, allDDColVars);
|
|
}
|
|
|
|
/**
|
|
* Get an SCCComputer object for the explicit engine.
|
|
*/
|
|
public explicit.SCCComputer getExplicitSCCComputer(explicit.Model model) throws PrismException
|
|
{
|
|
return explicit.SCCComputer.createSCCComputer(this, model);
|
|
}
|
|
|
|
/**
|
|
* Get an ECComputer object.
|
|
*/
|
|
public ECComputer getECComputer(NondetModel model) throws PrismException
|
|
{
|
|
return ECComputer.createECComputer(this, model);
|
|
}
|
|
|
|
/**
|
|
* Get an ECComputer object.
|
|
*/
|
|
public ECComputer getECComputer(JDDNode reach, JDDNode trans, JDDNode trans01, JDDVars allDDRowVars, JDDVars allDDColVars, JDDVars allDDNondetVars) throws PrismException
|
|
{
|
|
return ECComputer.createECComputer(this, reach, trans, trans01, allDDRowVars, allDDColVars, allDDNondetVars);
|
|
}
|
|
|
|
/**
|
|
* Get an ECComputer object for the explicit engine.
|
|
*/
|
|
public explicit.ECComputer getExplicitECComputer(explicit.NondetModel model) throws PrismException
|
|
{
|
|
return explicit.ECComputer.createECComputer(this, model);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Utility methods
|
|
//------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Compare two version numbers of PRISM (strings).
|
|
* Example ordering: { "1", "2.0", "2.1.alpha", "2.1.alpha.r5555", "2.1.alpha.r5557", "2.1.beta", "2.1.beta4", "2.1", "2.1.dev", "2.1.dev.r6666", "2.1.dev1", "2.1.dev2", "2.1.2", "2.9", "3", "3.4"};
|
|
* Returns: 1 if v1>v2, -1 if v1<v2, 0 if v1=v2
|
|
*/
|
|
public static int compareVersions(String v1, String v2)
|
|
{
|
|
String ss1[], ss2[], tmp[];
|
|
int i, n, x;
|
|
double s1 = 0, s2 = 0;
|
|
boolean s1num, s2num;
|
|
|
|
// Exactly equal
|
|
if (v1.equals(v2))
|
|
return 0;
|
|
// Otherwise split into sections
|
|
ss1 = v1.split("\\.");
|
|
ss2 = v2.split("\\.");
|
|
// Pad if one is shorter
|
|
n = Math.max(ss1.length, ss2.length);
|
|
if (ss1.length < n) {
|
|
tmp = new String[n];
|
|
for (i = 0; i < ss1.length; i++)
|
|
tmp[i] = ss1[i];
|
|
for (i = ss1.length; i < n; i++)
|
|
tmp[i] = "";
|
|
ss1 = tmp;
|
|
}
|
|
if (ss2.length < n) {
|
|
tmp = new String[n];
|
|
for (i = 0; i < ss2.length; i++)
|
|
tmp[i] = ss2[i];
|
|
for (i = ss2.length; i < n; i++)
|
|
tmp[i] = "";
|
|
ss2 = tmp;
|
|
}
|
|
// Loop through sections of string
|
|
for (i = 0; i < n; i++) {
|
|
// 2.1.alpha < 2.1, etc.
|
|
// 2.1.alpha < 2.1.alpha2 < 2.1.alpha3, etc.
|
|
// so replace alphax with -10000+x
|
|
if (ss1[i].matches("alpha.*")) {
|
|
try {
|
|
if (ss1[i].length() == 5)
|
|
x = 0;
|
|
else
|
|
x = Integer.parseInt(ss1[i].substring(5));
|
|
} catch (NumberFormatException e) {
|
|
x = 0;
|
|
}
|
|
ss1[i] = "" + (-10000 + x);
|
|
}
|
|
if (ss2[i].matches("alpha.*")) {
|
|
try {
|
|
if (ss2[i].length() == 5)
|
|
x = 0;
|
|
else
|
|
x = Integer.parseInt(ss2[i].substring(5));
|
|
} catch (NumberFormatException e) {
|
|
x = 0;
|
|
}
|
|
ss2[i] = "" + (-10000 + x);
|
|
}
|
|
// 2.1.beta < 2.1, etc.
|
|
// 2.1.beta < 2.1.beta2 < 2.1.beta3, etc.
|
|
// so replace betax with -100+x
|
|
if (ss1[i].matches("beta.*")) {
|
|
try {
|
|
if (ss1[i].length() == 4)
|
|
x = 0;
|
|
else
|
|
x = Integer.parseInt(ss1[i].substring(4));
|
|
} catch (NumberFormatException e) {
|
|
x = 0;
|
|
}
|
|
ss1[i] = "" + (-100 + x);
|
|
}
|
|
if (ss2[i].matches("beta.*")) {
|
|
try {
|
|
if (ss2[i].length() == 4)
|
|
x = 0;
|
|
else
|
|
x = Integer.parseInt(ss2[i].substring(4));
|
|
} catch (NumberFormatException e) {
|
|
x = 0;
|
|
}
|
|
ss2[i] = "" + (-100 + x);
|
|
}
|
|
// 2 < 2.1, etc.
|
|
// so treat 2 as 2.0
|
|
if (ss1[i].equals(""))
|
|
ss1[i] = "0";
|
|
if (ss2[i].equals(""))
|
|
ss2[i] = "0";
|
|
// 2.1 < 2.1.dev, etc.
|
|
// 2.1.dev < 2.1.dev2 < 2.1.dev3, etc.
|
|
// so replace devx with 0.5+x/1000
|
|
if (ss1[i].matches("dev.*")) {
|
|
try {
|
|
if (ss1[i].length() == 3)
|
|
x = 0;
|
|
else
|
|
x = Integer.parseInt(ss1[i].substring(3));
|
|
} catch (NumberFormatException e) {
|
|
x = 0;
|
|
}
|
|
ss1[i] = "" + (0.5 + x / 1000.0);
|
|
}
|
|
if (ss2[i].matches("dev.*")) {
|
|
try {
|
|
if (ss2[i].length() == 3)
|
|
x = 0;
|
|
else
|
|
x = Integer.parseInt(ss2[i].substring(3));
|
|
} catch (NumberFormatException e) {
|
|
x = 0;
|
|
}
|
|
ss2[i] = "" + (0.5 + x / 1000.0);
|
|
}
|
|
// replace rx (e.g. as in 4.0.alpha.r5555) with x
|
|
if (ss1[i].matches("r.*")) {
|
|
try {
|
|
x = Integer.parseInt(ss1[i].substring(1));
|
|
} catch (NumberFormatException e) {
|
|
x = 0;
|
|
}
|
|
ss1[i] = "" + x;
|
|
}
|
|
if (ss2[i].matches("r.*")) {
|
|
try {
|
|
x = Integer.parseInt(ss2[i].substring(1));
|
|
} catch (NumberFormatException e) {
|
|
x = 0;
|
|
}
|
|
ss2[i] = "" + x;
|
|
}
|
|
// See if strings are integers
|
|
try {
|
|
s1num = true;
|
|
s1 = Double.parseDouble(ss1[i]);
|
|
} catch (NumberFormatException e) {
|
|
s1num = false;
|
|
}
|
|
try {
|
|
s2num = true;
|
|
s2 = Double.parseDouble(ss2[i]);
|
|
} catch (NumberFormatException e) {
|
|
s2num = false;
|
|
}
|
|
if (s1num && s2num) {
|
|
if (s1 < s2)
|
|
return -1;
|
|
if (s1 > s2)
|
|
return 1;
|
|
if (s1 == s2)
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*// Simple test harness for compareVersions
|
|
public static void main(String[] args)
|
|
{
|
|
String v[] = { "1", "2.0", "2.1.alpha", "2.1.alpha.r5555", "2.1.alpha.r5557", "2.1.beta", "2.1.beta4", "2.1", "2.1.dev", "2.1.dev.r6666", "2.1.dev1", "2.1.dev2", "2.1.2", "2.9", "3", "3.4"};
|
|
for (int i = 0; i < v.length; i++) {
|
|
for (int j = 0; j < v.length; j++) {
|
|
int d = compareVersions(v[i], v[j]);
|
|
System.out.print(d == 1 ? ">" : d==0 ? "=" : d==-1 ? "<" : "?");
|
|
if (d != compareVersions(""+i, ""+j))
|
|
System.out.print("ERR(" + v[i] + "," + v[j] + ")");
|
|
|
|
}
|
|
System.out.println();
|
|
}
|
|
}*/
|
|
|
|
/**
|
|
* Get access to the list of all PRISM language keywords.
|
|
*/
|
|
public static List<String> getListOfKeyords()
|
|
{
|
|
return PrismParser.getListOfKeywords();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Main API methods
|
|
//------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Initialise PRISM.
|
|
*/
|
|
public void initialise() throws PrismException
|
|
{
|
|
boolean verbose = this.getSettings().getBoolean("PRISM_VERBOSE");
|
|
mainLog.setVerbosityLevel(verbose ? PrismLog.VL_ALL : PrismLog.VL_DEFAULT);
|
|
mainLog.print("PRISM\n=====\n");
|
|
mainLog.print("\nVersion: " + getVersion() + "\n");
|
|
mainLog.print("Date: " + new java.util.Date() + "\n");
|
|
try {
|
|
String h = java.net.InetAddress.getLocalHost().getHostName();
|
|
mainLog.print("Hostname: " + h + "\n");
|
|
} catch (java.net.UnknownHostException e) {
|
|
}
|
|
mainLog.print("Memory limits: cudd=" + getCUDDMaxMem());
|
|
mainLog.println(", java(heap)=" + PrismUtils.convertBytesToMemoryString(Runtime.getRuntime().maxMemory()));
|
|
|
|
// initialise cudd/jdd
|
|
long cuddMaxMem = PrismUtils.convertMemoryStringtoKB(getCUDDMaxMem());
|
|
JDD.InitialiseCUDD(cuddMaxMem, getCUDDEpsilon());
|
|
cuddStarted = true;
|
|
JDD.SetOutputStream(techLog.getFilePointer());
|
|
|
|
// initialise libraries/engines
|
|
PrismNative.initialise(this);
|
|
PrismMTBDD.initialise(mainLog, techLog);
|
|
PrismSparse.initialise(mainLog, techLog);
|
|
PrismHybrid.initialise(mainLog, techLog);
|
|
|
|
// set cudd manager in other packages
|
|
DoubleVector.setCUDDManager();
|
|
ODDUtils.setCUDDManager();
|
|
}
|
|
|
|
/**
|
|
* Parse a PRISM model from a file.
|
|
* @param file File to read in
|
|
*/
|
|
public ModulesFile parseModelFile(File file) throws FileNotFoundException, PrismLangException
|
|
{
|
|
return parseModelFile(file, null);
|
|
}
|
|
|
|
/**
|
|
* Parse a PRISM model from a file.
|
|
* @param file File to read in
|
|
* @param typeOverride Optionally, override model type here (null if unused)
|
|
*/
|
|
public ModulesFile parseModelFile(File file, ModelType typeOverride) throws FileNotFoundException, PrismLangException
|
|
{
|
|
FileInputStream strModel;
|
|
PrismParser prismParser;
|
|
ModulesFile modulesFile = null;
|
|
|
|
// open file
|
|
strModel = new FileInputStream(file);
|
|
|
|
try {
|
|
// obtain exclusive access to the prism parser
|
|
// (don't forget to release it afterwards)
|
|
prismParser = getPrismParser();
|
|
try {
|
|
// parse file
|
|
modulesFile = prismParser.parseModulesFile(strModel, typeOverride);
|
|
} finally {
|
|
// release prism parser
|
|
releasePrismParser();
|
|
}
|
|
} catch (InterruptedException ie) {
|
|
throw new PrismLangException("Concurrency error in parser");
|
|
}
|
|
|
|
modulesFile.tidyUp();
|
|
|
|
return modulesFile;
|
|
}
|
|
|
|
/**
|
|
* Parse a PRISM model from a string.
|
|
* @param s String containing model
|
|
*/
|
|
public ModulesFile parseModelString(String s) throws PrismLangException
|
|
{
|
|
return parseModelString(s, null);
|
|
}
|
|
|
|
/**
|
|
* Parse a PRISM model from a string.
|
|
* @param s String containing model
|
|
* @param typeOverride Optionally, override model type here (null if unused)
|
|
*/
|
|
public ModulesFile parseModelString(String s, ModelType typeOverride) throws PrismLangException
|
|
{
|
|
PrismParser prismParser;
|
|
ModulesFile modulesFile = null;
|
|
|
|
try {
|
|
// obtain exclusive access to the prism parser
|
|
// (don't forget to release it afterwards)
|
|
prismParser = getPrismParser();
|
|
try {
|
|
// parse string
|
|
modulesFile = prismParser.parseModulesFile(new ByteArrayInputStream(s.getBytes()), typeOverride);
|
|
} finally {
|
|
// release prism parser
|
|
releasePrismParser();
|
|
}
|
|
} catch (InterruptedException ie) {
|
|
throw new PrismLangException("Concurrency error in parser");
|
|
}
|
|
|
|
modulesFile.tidyUp();
|
|
|
|
return modulesFile;
|
|
}
|
|
|
|
/**
|
|
* Import a PRISM model from a PEPA model in a file
|
|
* @param file File to read in
|
|
*/
|
|
public ModulesFile importPepaFile(File file) throws PrismException, PrismLangException
|
|
{
|
|
String modelString;
|
|
|
|
// compile pepa file to string
|
|
try {
|
|
modelString = pepa.compiler.Main.compile("" + file);
|
|
} catch (pepa.compiler.InternalError e) {
|
|
throw new PrismException("Could not import PEPA file:\n" + e.getMessage());
|
|
}
|
|
|
|
// parse string as prism model and return
|
|
return parseModelString(modelString);
|
|
}
|
|
|
|
/**
|
|
* Import a PRISM model from a PEPA model in a string
|
|
* @param s String containing model
|
|
*/
|
|
public ModulesFile importPepaString(String s) throws PrismException, PrismLangException
|
|
{
|
|
File pepaFile = null;
|
|
String modelString;
|
|
|
|
// create temporary file containing pepa model
|
|
try {
|
|
pepaFile = File.createTempFile("tempPepa" + System.currentTimeMillis(), ".pepa");
|
|
FileWriter write = new FileWriter(pepaFile);
|
|
write.write(s);
|
|
write.close();
|
|
} catch (IOException e) {
|
|
if (pepaFile != null)
|
|
pepaFile.delete();
|
|
throw new PrismException("Couldn't create temporary file for PEPA conversion");
|
|
}
|
|
|
|
// compile pepa file to string
|
|
try {
|
|
modelString = pepa.compiler.Main.compile("" + pepaFile);
|
|
} catch (pepa.compiler.InternalError e) {
|
|
if (pepaFile != null)
|
|
pepaFile.delete();
|
|
throw new PrismException("Could not import PEPA file:\n" + e.getMessage());
|
|
}
|
|
|
|
// parse string as prism model and return
|
|
return parseModelString(modelString);
|
|
}
|
|
|
|
/**
|
|
* Import a PRISM model from a PRISM preprocessor file
|
|
* @param file File to read in
|
|
* @param params List of values for preprocessor parameters
|
|
*/
|
|
public ModulesFile importPrismPreprocFile(File file, String params[]) throws PrismException
|
|
{
|
|
String modelString;
|
|
|
|
// Compile preprocessor file to a string
|
|
Preprocessor pp = new Preprocessor(this, file);
|
|
pp.setParameters(params);
|
|
modelString = pp.preprocess();
|
|
if (modelString == null) {
|
|
throw new PrismException("No preprocessing information");
|
|
}
|
|
|
|
// Parse string as PRISM model and return
|
|
return parseModelString(modelString);
|
|
}
|
|
|
|
/**
|
|
* Parse a PRISM properties file. Typically, you need to pass in the corresponding PRISM model
|
|
* (for access to constants, etc.) but if left null, a blank one is created automatically.
|
|
* @param mf Accompanying ModulesFile (null if not needed)
|
|
* @param file File to read in
|
|
*/
|
|
public PropertiesFile parsePropertiesFile(ModulesFile mf, File file) throws FileNotFoundException, PrismLangException
|
|
{
|
|
return parsePropertiesFile(mf, file, true);
|
|
}
|
|
|
|
/**
|
|
* Parse a PRISM properties file. Typically, you need to pass in the corresponding PRISM model
|
|
* (for access to constants, etc.) but if left null, a blank one is created automatically.
|
|
* You can also choose whether to do "tidy", i.e. post-parse checks and processing
|
|
* (this must be done at some point but may want to postpone to allow parsing of files with errors).
|
|
* @param mf Accompanying ModulesFile (null if not needed)
|
|
* @param file File to read in
|
|
* @param tidy Whether or not to do "tidy" (post-parse checks and processing)
|
|
*/
|
|
public PropertiesFile parsePropertiesFile(ModulesFile mf, File file, boolean tidy) throws FileNotFoundException, PrismLangException
|
|
{
|
|
FileInputStream strProperties;
|
|
PrismParser prismParser;
|
|
PropertiesFile propertiesFile = null;
|
|
|
|
// open file
|
|
strProperties = new FileInputStream(file);
|
|
|
|
// if null modules file passed, create a blank one
|
|
if (mf == null) {
|
|
mf = new ModulesFile();
|
|
mf.setFormulaList(new FormulaList());
|
|
mf.setConstantList(new ConstantList());
|
|
}
|
|
|
|
try {
|
|
// obtain exclusive access to the prism parser
|
|
// (don't forget to release it afterwards)
|
|
prismParser = getPrismParser();
|
|
try {
|
|
// parse file
|
|
propertiesFile = prismParser.parsePropertiesFile(mf, strProperties);
|
|
} finally {
|
|
// release prism parser
|
|
releasePrismParser();
|
|
}
|
|
} catch (InterruptedException ie) {
|
|
throw new PrismLangException("Concurrency error in parser");
|
|
}
|
|
|
|
if (tidy)
|
|
propertiesFile.tidyUp();
|
|
|
|
return propertiesFile;
|
|
}
|
|
|
|
/**
|
|
* Parse a PRISM properties file from a string. Typically, you need to pass in the corresponding PRISM model
|
|
* (for access to constants, etc.) but if left null, a blank one is created automatically.
|
|
* @param mf Accompanying ModulesFile (null if not needed)
|
|
* @param s String to parse
|
|
*/
|
|
public PropertiesFile parsePropertiesString(ModulesFile mf, String s) throws PrismLangException
|
|
{
|
|
PrismParser prismParser;
|
|
PropertiesFile propertiesFile = null;
|
|
|
|
// if null modules file passed, create a blank one
|
|
if (mf == null) {
|
|
mf = new ModulesFile();
|
|
mf.setFormulaList(new FormulaList());
|
|
mf.setConstantList(new ConstantList());
|
|
}
|
|
|
|
try {
|
|
// obtain exclusive access to the prism parser
|
|
// (don't forget to release it afterwards)
|
|
prismParser = getPrismParser();
|
|
try {
|
|
// parse string
|
|
propertiesFile = prismParser.parsePropertiesFile(mf, new ByteArrayInputStream(s.getBytes()));
|
|
} finally {
|
|
// release prism parser
|
|
releasePrismParser();
|
|
}
|
|
} catch (InterruptedException ie) {
|
|
throw new PrismLangException("Concurrency error in parser");
|
|
}
|
|
|
|
propertiesFile.tidyUp();
|
|
|
|
return propertiesFile;
|
|
}
|
|
|
|
/**
|
|
* Parse a single PRISM expression from a string.
|
|
* @param s String to parse
|
|
*/
|
|
public Expression parseSingleExpressionString(String s) throws PrismLangException
|
|
{
|
|
PrismParser prismParser;
|
|
Expression expr;
|
|
|
|
try {
|
|
// obtain exclusive access to the prism parser
|
|
// (don't forget to release it afterwards)
|
|
prismParser = getPrismParser();
|
|
try {
|
|
// parse expression
|
|
expr = prismParser.parseSingleExpression(new ByteArrayInputStream(s.getBytes()));
|
|
} finally {
|
|
// release prism parser
|
|
releasePrismParser();
|
|
}
|
|
} catch (InterruptedException ie) {
|
|
throw new PrismLangException("Concurrency error in parser");
|
|
}
|
|
|
|
return expr;
|
|
}
|
|
|
|
/**
|
|
* Parse a for-loop (as used e.g. in preprocessor) from a string.
|
|
* @param s String to parse
|
|
*/
|
|
public ForLoop parseForLoopString(String s) throws PrismLangException
|
|
{
|
|
PrismParser prismParser;
|
|
ForLoop fl;
|
|
|
|
try {
|
|
// obtain exclusive access to the prism parser
|
|
// (don't forget to release it afterwards)
|
|
prismParser = getPrismParser();
|
|
try {
|
|
// parse for loop
|
|
fl = prismParser.parseForLoop(new ByteArrayInputStream(s.getBytes()));
|
|
} finally {
|
|
// release prism parser
|
|
releasePrismParser();
|
|
}
|
|
} catch (InterruptedException ie) {
|
|
throw new PrismLangException("Concurrency error in parser");
|
|
}
|
|
|
|
return fl;
|
|
}
|
|
|
|
/**
|
|
* Load a (parsed) PRISM model, which will be stored and used for subsequent model checking etc.
|
|
* Some model constants can still be undefined at this stage.
|
|
* Pass in null to clear storage of the current PRISM model.
|
|
* @param modulesFile The PRISM model
|
|
*/
|
|
public void loadPRISMModel(ModulesFile modulesFile)
|
|
{
|
|
currentModelSource = ModelSource.PRISM_MODEL;
|
|
// Store PRISM model
|
|
currentModulesFile = modulesFile;
|
|
// Clear any existing built model(s)
|
|
clearBuiltModel();
|
|
// Reset dependent info
|
|
currentModelType = currentModulesFile == null ? null : currentModulesFile.getModelType();
|
|
currentDefinedMFConstants = null;
|
|
currentModel = null;
|
|
currentModelExpl = null;
|
|
|
|
// Print basic model info
|
|
mainLog.println("\nType: " + currentModulesFile.getModelType());
|
|
mainLog.print("Modules: ");
|
|
for (int i = 0; i < currentModulesFile.getNumModules(); i++) {
|
|
mainLog.print(currentModulesFile.getModuleName(i) + " ");
|
|
}
|
|
mainLog.println();
|
|
mainLog.print("Variables: ");
|
|
for (int i = 0; i < currentModulesFile.getNumVars(); i++) {
|
|
mainLog.print(currentModulesFile.getVarName(i) + " ");
|
|
}
|
|
mainLog.println();
|
|
|
|
// If required, export parsed PRISM model
|
|
if (exportPrism) {
|
|
try {
|
|
exportPRISMModel(exportPrismFile);
|
|
}
|
|
// In case of error, just print a warning
|
|
catch (FileNotFoundException e) {
|
|
mainLog.printWarning("PRISM code export failed: Couldn't open file \"" + exportPrismFile + "\" for output");
|
|
} catch (PrismException e) {
|
|
mainLog.printWarning("PRISM code export failed: " + e.getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set (some or all) undefined constants for the currently loaded PRISM model
|
|
* (assuming they have changed since the last time this was called).
|
|
* @param definedMFConstants The constant values
|
|
*/
|
|
public void setPRISMModelConstants(Values definedMFConstants) throws PrismLangException
|
|
{
|
|
if (currentDefinedMFConstants == null && definedMFConstants == null)
|
|
return;
|
|
if (currentDefinedMFConstants != null && currentDefinedMFConstants.equals(definedMFConstants))
|
|
return;
|
|
|
|
// Clear any existing built model(s)
|
|
clearBuiltModel();
|
|
// Store constants here and in ModulesFile
|
|
currentDefinedMFConstants = definedMFConstants;
|
|
currentModulesFile.setSomeUndefinedConstants(definedMFConstants);
|
|
// Reset dependent info
|
|
currentModel = null;
|
|
currentModelExpl = null;
|
|
|
|
// If required, export parsed PRISM model, with constants expanded
|
|
if (exportPrismConst) {
|
|
try {
|
|
exportPRISMModelWithExpandedConstants(exportPrismConstFile);
|
|
}
|
|
// In case of error, just print a warning
|
|
catch (FileNotFoundException e) {
|
|
mainLog.printWarning("PRISM code export failed: Couldn't open file \"" + exportPrismConstFile + "\" for output");
|
|
} catch (PrismException e) {
|
|
mainLog.printWarning("PRISM code export failed: " + e.getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load a (built) model, with an accompanying (parsed) PRISM model.
|
|
* These will be stored and used for subsequent model checking etc.
|
|
* Pass in nulls to clear storage of the current model.
|
|
* @param modulesFile The PRISM model
|
|
*/
|
|
public void loadPRISMModelAndBuiltModel(ModulesFile modulesFile, Model model)
|
|
{
|
|
currentModelSource = ModelSource.PRISM_MODEL;
|
|
// Clear any existing built model(s)
|
|
clearBuiltModel();
|
|
// Store model info
|
|
currentModulesFile = modulesFile;
|
|
currentModel = model;
|
|
// Reset dependent info
|
|
currentModelType = currentModulesFile == null ? null : currentModulesFile.getModelType();
|
|
currentDefinedMFConstants = null;
|
|
currentModelExpl = null;
|
|
}
|
|
|
|
/**
|
|
* Load a (built) model, without an accompanying (parsed) PRISM model.
|
|
* The model will be stored and used for subsequent model checking etc.
|
|
* Pass in null to clear storage of the current model.
|
|
* @param model The built model
|
|
*/
|
|
public void loadBuiltModel(Model model)
|
|
{
|
|
currentModelSource = ModelSource.BUILT_MODEL;
|
|
// Clear any existing built model(s)
|
|
clearBuiltModel();
|
|
// Store model info
|
|
currentModulesFile = null;
|
|
currentModel = model;
|
|
// Reset dependent info
|
|
currentModelType = currentModel == null ? null : currentModel.getModelType();
|
|
currentDefinedMFConstants = null;
|
|
currentModelExpl = null;
|
|
}
|
|
|
|
/**
|
|
* Load files containing an explicit list of transitions/etc. for subsequent model building.
|
|
* A corresponding ModulesFile object is created and returned.
|
|
* @param statesFile File containing a list of states (optional, can be null)
|
|
* @param transFile File containing the list of transitions (required)
|
|
* @param labelsFile File containing label definitions (optional, can be null)
|
|
* @param typeOverride Type of model to be built (optional, use null if not required)
|
|
*/
|
|
public ModulesFile loadModelFromExplicitFiles(File statesFile, File transFile, File labelsFile, ModelType typeOverride) throws PrismException
|
|
{
|
|
currentModelSource = ModelSource.EXPLICIT_FILES;
|
|
// Clear any existing built model(s)
|
|
clearBuiltModel();
|
|
// Construct ModulesFile
|
|
ExplicitFiles2ModulesFile ef2mf = new ExplicitFiles2ModulesFile(this);
|
|
currentModulesFile = ef2mf.buildModulesFile(statesFile, transFile, typeOverride);
|
|
// Store explicit files info for later
|
|
explicitFilesStatesFile = statesFile;
|
|
explicitFilesTransFile = transFile;
|
|
explicitFilesLabelsFile = labelsFile;
|
|
explicitFilesNumStates = ef2mf.getNumStates();
|
|
// Reset dependent info
|
|
currentModelType = currentModulesFile == null ? null : currentModulesFile.getModelType();
|
|
currentDefinedMFConstants = null;
|
|
currentModel = null;
|
|
currentModelExpl = null;
|
|
|
|
return currentModulesFile;
|
|
}
|
|
|
|
/**
|
|
* Get the type of the currently stored model.
|
|
* @return
|
|
*/
|
|
public ModelType getModelType()
|
|
{
|
|
return currentModelType;
|
|
}
|
|
|
|
/**
|
|
* Get the currently stored (parsed) PRISM model.
|
|
* @return
|
|
*/
|
|
public ModulesFile getPRISMModel()
|
|
{
|
|
return currentModulesFile;
|
|
}
|
|
|
|
/**
|
|
* Get the currently stored built (symbolic) model.
|
|
* @return
|
|
*/
|
|
public Model getBuiltModel()
|
|
{
|
|
return currentModel;
|
|
}
|
|
|
|
/**
|
|
* Get the currently stored built explicit model.
|
|
* @return
|
|
*/
|
|
public explicit.Model getBuiltModelExplicit()
|
|
{
|
|
return currentModelExpl;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the current model is of a type that can be built (e.g. not a PTA).
|
|
*/
|
|
public boolean modelCanBeBuilt()
|
|
{
|
|
if (currentModelType == ModelType.PTA)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the current model has been built (for the currently selected engine).
|
|
*/
|
|
public boolean modelIsBuilt()
|
|
{
|
|
return (getExplicit() ? (currentModelExpl != null) : (currentModel != null));
|
|
}
|
|
|
|
/**
|
|
* Build the currently loaded PRISM model and store for later use.
|
|
* The built model can be accessed subsequently via either
|
|
* {@link #getBuiltModel()} or {@link #getBuiltModelExplicit()},
|
|
* depending on the engine currently selected.
|
|
* Only call this to explicitly force a built; normally it is done automatically.
|
|
*/
|
|
public void buildModel() throws PrismException
|
|
{
|
|
mainLog.printSeparator();
|
|
doBuildModel();
|
|
}
|
|
|
|
/**
|
|
* Build the currently loaded PRISM model, if it needs to be done,
|
|
* i.e. if it has not been constructed yet for the current engine.
|
|
*/
|
|
public void buildModelIfRequired() throws PrismException
|
|
{
|
|
if (!modelIsBuilt())
|
|
doBuildModel();
|
|
}
|
|
|
|
/**
|
|
* Build the currently loaded PRISM model and store for later use.
|
|
* The built model can be accessed subsequently via either
|
|
* {@link #getBuiltModel()} or {@link #getBuiltModelExplicit()},
|
|
* depending on the engine currently selected.
|
|
*/
|
|
private void doBuildModel() throws PrismException
|
|
{
|
|
long l; // timer
|
|
|
|
// Clear any existing built model(s)
|
|
clearBuiltModel();
|
|
|
|
try {
|
|
if (currentModulesFile == null)
|
|
throw new PrismException("There is no currently loaded PRISM model to build");
|
|
|
|
if (currentModelType == ModelType.PTA) {
|
|
throw new PrismException("You cannot build a PTA model explicitly, only perform model checking");
|
|
}
|
|
|
|
mainLog.print("\nBuilding model...\n");
|
|
if (currentDefinedMFConstants != null && currentDefinedMFConstants.getNumValues() > 0)
|
|
mainLog.println("Model constants: " + currentDefinedMFConstants);
|
|
|
|
// Build model
|
|
l = System.currentTimeMillis();
|
|
switch (currentModelSource) {
|
|
case PRISM_MODEL:
|
|
if (!getExplicit()) {
|
|
Modules2MTBDD mod2mtbdd = new Modules2MTBDD(this, currentModulesFile);
|
|
currentModel = mod2mtbdd.translate();
|
|
currentModelExpl = null;
|
|
} else {
|
|
ConstructModel constructModel = new ConstructModel(this, getSimulator());
|
|
constructModel.setFixDeadlocks(getFixDeadlocks());
|
|
currentModelExpl = constructModel.constructModel(currentModulesFile, false, true);
|
|
currentModel = null;
|
|
}
|
|
// if (...) ... currentModel = buildModelExplicit(currentModulesFile);
|
|
break;
|
|
case EXPLICIT_FILES:
|
|
if (!getExplicit()) {
|
|
expf2mtbdd = new ExplicitFiles2MTBDD(this);
|
|
currentModel = expf2mtbdd.build(explicitFilesStatesFile, explicitFilesTransFile, explicitFilesLabelsFile, currentModulesFile,
|
|
explicitFilesNumStates);
|
|
} else {
|
|
throw new PrismNotSupportedException("Explicit import not yet supported for explicit engine");
|
|
}
|
|
break;
|
|
default:
|
|
throw new PrismException("Don't know how to build model from source " + currentModelSource);
|
|
}
|
|
l = System.currentTimeMillis() - l;
|
|
mainLog.println("\nTime for model construction: " + l / 1000.0 + " seconds.");
|
|
|
|
// For digital clocks, do some extra checks on the built model
|
|
if (digital) {
|
|
doBuildModelDigitalClocksChecks();
|
|
}
|
|
|
|
// Deal with deadlocks
|
|
if (!getExplicit()) {
|
|
StateList deadlocks = currentModel.getDeadlockStates();
|
|
int numDeadlocks = deadlocks.size();
|
|
if (numDeadlocks > 0) {
|
|
if (getFixDeadlocks()) {
|
|
mainLog.printWarning("Deadlocks detected and fixed in " + numDeadlocks + " states");
|
|
} else {
|
|
currentModel.printTransInfo(mainLog, getExtraDDInfo());
|
|
mainLog.print("\n" + numDeadlocks + " deadlock states found");
|
|
if (!getVerbose() && numDeadlocks > 10) {
|
|
mainLog.print(". The first 10 are below. Use verbose mode to view them all.\n");
|
|
deadlocks.print(mainLog, 10);
|
|
} else {
|
|
mainLog.print(":\n");
|
|
deadlocks.print(mainLog);
|
|
}
|
|
mainLog.print("\nTip: Use the \"fix deadlocks\" option to automatically add self-loops in deadlock states.\n");
|
|
throw new PrismException("Model contains " + numDeadlocks + " deadlock states");
|
|
}
|
|
}
|
|
} else {
|
|
explicit.StateValues deadlocks = currentModelExpl.getDeadlockStatesList();
|
|
int numDeadlocks = currentModelExpl.getNumDeadlockStates();
|
|
if (numDeadlocks > 0) {
|
|
if (getFixDeadlocks()) {
|
|
mainLog.printWarning("Deadlocks detected and fixed in " + numDeadlocks + " states");
|
|
} else {
|
|
mainLog.print(currentModelExpl.infoStringTable());
|
|
mainLog.print("\n" + numDeadlocks + " deadlock states found");
|
|
if (!getVerbose() && numDeadlocks > 10) {
|
|
mainLog.print(". The first 10 are below. Use verbose mode to view them all.\n");
|
|
deadlocks.print(mainLog, 10);
|
|
} else {
|
|
mainLog.print(":\n");
|
|
deadlocks.print(mainLog);
|
|
}
|
|
mainLog.print("\nTip: Use the \"fix deadlocks\" option to automatically add self-loops in deadlock states.\n");
|
|
throw new PrismException("Model contains " + numDeadlocks + " deadlock states");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Print model stats
|
|
mainLog.println();
|
|
if (!getExplicit()) {
|
|
mainLog.println("Type: " + currentModel.getModelType());
|
|
currentModel.printTransInfo(mainLog, getExtraDDInfo());
|
|
} else {
|
|
mainLog.println("Type: " + currentModelExpl.getModelType());
|
|
mainLog.print(currentModelExpl.infoStringTable());
|
|
}
|
|
|
|
// Notify model listeners of build success
|
|
for (PrismModelListener listener : modelListeners) {
|
|
if (listener != null)
|
|
listener.notifyModelBuildSuccessful();
|
|
}
|
|
} catch (PrismException e) {
|
|
// Notify model listeners of build failure
|
|
for (PrismModelListener listener : modelListeners) {
|
|
if (listener != null)
|
|
listener.notifyModelBuildFailed(e);
|
|
}
|
|
// Throw exception anyway
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
private void doBuildModelDigitalClocksChecks() throws PrismException
|
|
{
|
|
// For digital clocks, by construction, deadlocks can only occur from timelocks (and are not allowed)
|
|
if (!getExplicit()) {
|
|
StateList deadlocks = currentModel.getDeadlockStates();
|
|
if (deadlocks.size() > 0) {
|
|
throw new PrismException("Timelock in PTA, e.g. in state (" + deadlocks.getFirstAsValues() + ")");
|
|
}
|
|
} else {
|
|
if (currentModelExpl.getNumDeadlockStates() > 0) {
|
|
int dl = currentModelExpl.getFirstDeadlockState();
|
|
String dls = currentModelExpl.getStatesList().get(dl).toString(currentModulesFile);
|
|
throw new PrismException("Timelock in PTA, e.g. in state " + dls);
|
|
}
|
|
}
|
|
|
|
/*// Create new model checker object and do model checking
|
|
PropertiesFile pf = parsePropertiesString(currentModulesFile, "filter(exists,!\"invariants\"); E[F!\"invariants\"]");
|
|
if (!getExplicit()) {
|
|
ModelChecker mc = new NondetModelChecker(this, currentModel, pf);
|
|
if (((Boolean) mc.check(pf.getProperty(0)).getResult()).booleanValue()) {
|
|
mainLog.println(mc.check(pf.getProperty(1)).getCounterexample());
|
|
}
|
|
//sv.pr
|
|
//mainLog.println("XX" + res.getResult());
|
|
} else {
|
|
explicit.StateModelChecker mc = new MDPModelChecker();
|
|
mc.setLog(mainLog);
|
|
mc.setSettings(settings);
|
|
mc.setModulesFileAndPropertiesFile(currentModulesFile, pf);
|
|
explicit.StateValues sv = mc.checkExpression(currentModelExpl, pf.getProperty(0));
|
|
sv.print(mainLog, 1);
|
|
}*/
|
|
}
|
|
|
|
/**
|
|
* Build a model from a PRISM modelling language description, storing it symbolically,
|
|
* as MTBDDs) via explicit-state reachability and model construction.
|
|
* It is assumed that all constants in the model file have been defined by now.
|
|
* @param modulesFile Model to build
|
|
*/
|
|
public Model buildModelExplicit(ModulesFile modulesFile) throws PrismException
|
|
{
|
|
long l; // timer
|
|
ConstructModel constructModel;
|
|
explicit.Model modelExpl;
|
|
Model model;
|
|
List<State> statesList;
|
|
|
|
if (modulesFile.getModelType() == ModelType.PTA) {
|
|
throw new PrismException("You cannot build a PTA model explicitly, only perform model checking");
|
|
}
|
|
|
|
mainLog.print("\nBuilding model...\n");
|
|
if (currentDefinedMFConstants != null && currentDefinedMFConstants.getNumValues() > 0)
|
|
mainLog.println("Model constants: " + currentDefinedMFConstants);
|
|
|
|
constructModel = new ConstructModel(this, getSimulator());
|
|
modelExpl = constructModel.constructModel(modulesFile);
|
|
statesList = constructModel.getStatesList();
|
|
|
|
// create Explicit2MTBDD object
|
|
expm2mtbdd = new ExplicitModel2MTBDD(this);
|
|
|
|
// build model
|
|
l = System.currentTimeMillis();
|
|
model = expm2mtbdd.buildModel(modelExpl, statesList, modulesFile, false);
|
|
l = System.currentTimeMillis() - l;
|
|
|
|
mainLog.println("\nTime for model construction: " + l / 1000.0 + " seconds.");
|
|
|
|
return model;
|
|
}
|
|
|
|
/**
|
|
* Export the currently loaded and parsed PRISM model to a file.
|
|
* @param file File to export to
|
|
*/
|
|
public void exportPRISMModel(File file) throws FileNotFoundException, PrismException
|
|
{
|
|
mainLog.print("\nExporting parsed PRISM file ");
|
|
mainLog.println(getDestinationStringForFile(file));
|
|
PrismLog tmpLog = getPrismLogForFile(file);
|
|
tmpLog.print(currentModulesFile.toString());
|
|
// tidy up
|
|
if (file != null)
|
|
tmpLog.close();
|
|
}
|
|
|
|
/**
|
|
* Export the currently loaded and parsed PRISM model to a file,
|
|
* after expanding all constants to their actual, defined values.
|
|
* @param file File to export to
|
|
*/
|
|
public void exportPRISMModelWithExpandedConstants(File file) throws FileNotFoundException, PrismException
|
|
{
|
|
mainLog.print("\nExporting parsed PRISM file (with constant expansion) ");
|
|
mainLog.println(getDestinationStringForFile(file));
|
|
PrismLog tmpLog = getPrismLogForFile(file);
|
|
ModulesFile mfTmp = (ModulesFile) currentModulesFile.deepCopy();
|
|
mfTmp = (ModulesFile) mfTmp.replaceConstants(currentModulesFile.getConstantValues());
|
|
// NB: Don't use simplify() here because doesn't work for the purposes of printing out
|
|
// (e.g. loss of parentheses causes precedence problems)
|
|
tmpLog.print(mfTmp.toString());
|
|
// tidy up
|
|
if (file != null)
|
|
tmpLog.close();
|
|
}
|
|
|
|
/**
|
|
* Export the currently loaded model's transition matrix to a Spy file.
|
|
* @param file File to export to
|
|
*/
|
|
public void exportToSpyFile(File file) throws FileNotFoundException, PrismException
|
|
{
|
|
int depth;
|
|
JDDNode tmp;
|
|
|
|
if (getExplicit())
|
|
throw new PrismNotSupportedException("Export to Spy file not yet supported by explicit engine");
|
|
|
|
// Build model, if necessary
|
|
buildModelIfRequired();
|
|
|
|
mainLog.println("\nExporting to spy file \"" + file + "\"...");
|
|
|
|
// choose depth
|
|
depth = currentModel.getAllDDRowVars().n();
|
|
if (depth > 9)
|
|
depth = 9;
|
|
|
|
// get rid of non det vars if necessary
|
|
tmp = currentModel.getTrans();
|
|
JDD.Ref(tmp);
|
|
if (currentModelType == ModelType.MDP) {
|
|
tmp = JDD.MaxAbstract(tmp, ((NondetModel) currentModel).getAllDDNondetVars());
|
|
}
|
|
|
|
// export to spy file
|
|
JDD.ExportMatrixToSpyFile(tmp, currentModel.getAllDDRowVars(), currentModel.getAllDDColVars(), depth, file.getPath());
|
|
JDD.Deref(tmp);
|
|
}
|
|
|
|
/**
|
|
* Export the MTBDD for the currently loaded model's transition matrix to a Dot file.
|
|
* @param file File to export to
|
|
*/
|
|
public void exportToDotFile(File file) throws FileNotFoundException, PrismException
|
|
{
|
|
if (getExplicit())
|
|
throw new PrismNotSupportedException("Export to Dot file not yet supported by explicit engine");
|
|
|
|
// Build model, if necessary
|
|
buildModelIfRequired();
|
|
|
|
mainLog.println("\nExporting to dot file \"" + file + "\"...");
|
|
|
|
// export to dot file
|
|
JDD.ExportDDToDotFileLabelled(currentModel.getTrans(), file.getPath(), currentModel.getDDVarNames());
|
|
}
|
|
|
|
/**
|
|
* Export the currently loaded model's transition matrix to a file (or to the log)
|
|
* @param ordered Ensure that (source) states are in ascending order?
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* <li> {@link #EXPORT_DOT}
|
|
* <li> {@link #EXPORT_MRMC}
|
|
* <li> {@link #EXPORT_ROWS}
|
|
* <li> {@link #EXPORT_DOT_STATES}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportTransToFile(boolean ordered, int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
// can only do ordered version of export for MDPs
|
|
if (currentModelType == ModelType.MDP) {
|
|
if (!ordered)
|
|
mainLog.printWarning("Cannot export unordered transition matrix for MDPs; using ordered.");
|
|
ordered = true;
|
|
}
|
|
// can only do ordered version of export for MRMC
|
|
if (exportType == EXPORT_MRMC) {
|
|
if (!ordered)
|
|
mainLog.printWarning("Cannot export unordered transition matrix in MRMC format; using ordered.");
|
|
ordered = true;
|
|
}
|
|
// can only do ordered version of export for rows format
|
|
if (exportType == EXPORT_ROWS) {
|
|
if (!ordered)
|
|
mainLog.printWarning("Cannot export unordered transition matrix in rows format; using ordered.");
|
|
ordered = true;
|
|
}
|
|
|
|
// Build model, if necessary
|
|
buildModelIfRequired();
|
|
|
|
// print message
|
|
mainLog.print("\nExporting transition matrix ");
|
|
mainLog.print(getStringForExportType(exportType) + " ");
|
|
mainLog.println(getDestinationStringForFile(file));
|
|
|
|
// do export
|
|
if (!getExplicit()) {
|
|
currentModel.exportToFile(exportType, ordered, file);
|
|
} else {
|
|
PrismLog tmpLog = getPrismLogForFile(file);
|
|
switch (exportType) {
|
|
case Prism.EXPORT_PLAIN:
|
|
currentModelExpl.exportToPrismExplicitTra(tmpLog);
|
|
break;
|
|
case Prism.EXPORT_MATLAB:
|
|
throw new PrismNotSupportedException("Export not yet supported");
|
|
case Prism.EXPORT_DOT:
|
|
currentModelExpl.exportToDotFile(tmpLog);
|
|
break;
|
|
case Prism.EXPORT_DOT_STATES:
|
|
currentModelExpl.exportToDotFile(tmpLog, null, true);
|
|
break;
|
|
case Prism.EXPORT_MRMC:
|
|
case Prism.EXPORT_ROWS:
|
|
throw new PrismNotSupportedException("Export not yet supported");
|
|
}
|
|
tmpLog.close();
|
|
}
|
|
|
|
// for export to dot with states, need to do a bit more
|
|
if (!getExplicit() && exportType == EXPORT_DOT_STATES) {
|
|
// open (appending to) existing new file log or use main log
|
|
PrismLog tmpLog = getPrismLogForFile(file, true);
|
|
// insert states info into dot file
|
|
currentModel.getReachableStates().printDot(tmpLog);
|
|
// print footer
|
|
tmpLog.println("}");
|
|
// tidy up
|
|
if (file != null)
|
|
tmpLog.close();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Export the currently loaded model's state rewards to a file
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* <li> {@link #EXPORT_MRMC}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportStateRewardsToFile(int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
String s;
|
|
|
|
if (getExplicit())
|
|
throw new PrismNotSupportedException("Export of state rewards not yet supported by explicit engine");
|
|
|
|
// rows format does not apply to vectors
|
|
if (exportType == EXPORT_ROWS)
|
|
exportType = EXPORT_PLAIN;
|
|
|
|
// Build model, if necessary
|
|
buildModelIfRequired();
|
|
|
|
// print message
|
|
mainLog.print("\nExporting state rewards vector ");
|
|
mainLog.print(getStringForExportType(exportType) + " ");
|
|
mainLog.println(getDestinationStringForFile(file));
|
|
|
|
// do export
|
|
s = currentModel.exportStateRewardsToFile(exportType, file);
|
|
if (s != null)
|
|
mainLog.println("Rewards exported to files: " + s);
|
|
}
|
|
|
|
/**
|
|
* Export the currently loaded model's transition rewards to a file
|
|
* @param ordered Ensure that (source) states are in ascending order?
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* <li> {@link #EXPORT_MRMC}
|
|
* <li> {@link #EXPORT_ROWS}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportTransRewardsToFile(boolean ordered, int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
String s;
|
|
|
|
if (getExplicit())
|
|
throw new PrismException("Export of transition rewards not yet supported by explicit engine");
|
|
|
|
// can only do ordered version of export for MDPs
|
|
if (currentModelType == ModelType.MDP) {
|
|
if (!ordered)
|
|
mainLog.printWarning("Cannot export unordered transition reward matrix for MDPs; using ordered.");
|
|
ordered = true;
|
|
}
|
|
// can only do ordered version of export for MRMC
|
|
if (exportType == EXPORT_MRMC) {
|
|
if (!ordered)
|
|
mainLog.printWarning("Cannot export unordered transition reward matrix in MRMC format; using ordered.");
|
|
ordered = true;
|
|
}
|
|
// can only do ordered version of export for rows format
|
|
if (exportType == EXPORT_ROWS) {
|
|
if (!ordered)
|
|
mainLog.printWarning("Cannot export unordered transition matrix in rows format; using ordered.");
|
|
ordered = true;
|
|
}
|
|
|
|
// Build model, if necessary
|
|
buildModelIfRequired();
|
|
|
|
// print message
|
|
mainLog.print("\nExporting transition rewards matrix ");
|
|
mainLog.print(getStringForExportType(exportType) + " ");
|
|
mainLog.println(getDestinationStringForFile(file));
|
|
|
|
// do export
|
|
s = currentModel.exportTransRewardsToFile(exportType, ordered, file);
|
|
if (s != null)
|
|
mainLog.println("Rewards exported to files: " + s);
|
|
}
|
|
|
|
/**
|
|
* Export the currently loaded model's bottom strongly connected components (BSCCs) to a file
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportBSCCsToFile(int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
int i, n;
|
|
long l; // timer
|
|
PrismLog tmpLog;
|
|
SCCComputer sccComputer = null;
|
|
explicit.SCCComputer sccComputerExpl = null;
|
|
//Vector<JDDNode> bsccs;
|
|
//JDDNode not, bscc;
|
|
|
|
// no specific states format for MRMC
|
|
if (exportType == EXPORT_MRMC)
|
|
exportType = EXPORT_PLAIN;
|
|
// rows format does not apply to states output
|
|
if (exportType == EXPORT_ROWS)
|
|
exportType = EXPORT_PLAIN;
|
|
|
|
// Build model, if necessary
|
|
buildModelIfRequired();
|
|
|
|
// Compute BSCCs
|
|
mainLog.println("\nComputing BSCCs...");
|
|
l = System.currentTimeMillis();
|
|
if (!getExplicit()) {
|
|
sccComputer = getSCCComputer(currentModel);
|
|
sccComputer.computeBSCCs();
|
|
} else {
|
|
sccComputerExpl = getExplicitSCCComputer(currentModelExpl);
|
|
sccComputerExpl.computeBSCCs();
|
|
}
|
|
l = System.currentTimeMillis() - l;
|
|
mainLog.println("\nTime for BSCC computation: " + l / 1000.0 + " seconds.");
|
|
|
|
// print message
|
|
mainLog.print("\nExporting BSCCs ");
|
|
mainLog.print(getStringForExportType(exportType) + " ");
|
|
mainLog.println(getDestinationStringForFile(file));
|
|
|
|
// create new file log or use main log
|
|
tmpLog = getPrismLogForFile(file);
|
|
|
|
// print header: list of model vars
|
|
if (exportType == EXPORT_MATLAB)
|
|
tmpLog.print("% ");
|
|
tmpLog.print("Variables: (");
|
|
for (i = 0; i < currentModulesFile.getNumVars(); i++) {
|
|
tmpLog.print(currentModulesFile.getVarName(i));
|
|
if (i < currentModulesFile.getNumVars() - 1)
|
|
tmpLog.print(",");
|
|
}
|
|
tmpLog.println(")");
|
|
|
|
// print states for each bscc
|
|
if (!getExplicit()) {
|
|
n = sccComputer.getBSCCs().size();
|
|
} else {
|
|
n = sccComputerExpl.getBSCCs().size();
|
|
}
|
|
for (i = 0; i < n; i++) {
|
|
tmpLog.println();
|
|
if (exportType == EXPORT_MATLAB)
|
|
tmpLog.print("% ");
|
|
tmpLog.println("BSCC " + (i + 1) + "/" + n + ":");
|
|
if (exportType == EXPORT_MATLAB)
|
|
tmpLog.println("bscc" + (i + 1) + "=[");
|
|
if (!getExplicit()) {
|
|
if (exportType != EXPORT_MATLAB)
|
|
new StateListMTBDD(sccComputer.getBSCCs().get(i), currentModel).print(tmpLog);
|
|
else
|
|
new StateListMTBDD(sccComputer.getBSCCs().get(i), currentModel).printMatlab(tmpLog);
|
|
JDD.Deref(sccComputer.getBSCCs().get(i));
|
|
} else {
|
|
explicit.StateValues.createFromBitSet(sccComputerExpl.getBSCCs().get(i), currentModelExpl).print(tmpLog, true, exportType == EXPORT_MATLAB, true, true);
|
|
}
|
|
if (exportType == EXPORT_MATLAB)
|
|
tmpLog.println("];");
|
|
}
|
|
|
|
if (!getExplicit()) {
|
|
JDD.Deref(sccComputer.getNotInBSCCs());
|
|
}
|
|
|
|
// tidy up
|
|
if (file != null)
|
|
tmpLog.close();
|
|
}
|
|
|
|
/**
|
|
* Export the (states of the) currently loaded model's maximal end components (MECs) to a file
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportMECsToFile(int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
int i, n;
|
|
long l; // timer
|
|
PrismLog tmpLog;
|
|
ECComputer ecComputer = null;
|
|
explicit.ECComputer ecComputerExpl = null;
|
|
|
|
// no specific states format for MRMC
|
|
if (exportType == EXPORT_MRMC)
|
|
exportType = EXPORT_PLAIN;
|
|
// rows format does not apply to states output
|
|
if (exportType == EXPORT_ROWS)
|
|
exportType = EXPORT_PLAIN;
|
|
|
|
// Build model, if necessary
|
|
buildModelIfRequired();
|
|
|
|
// Compute MECs
|
|
mainLog.println("\nComputing MECs...");
|
|
l = System.currentTimeMillis();
|
|
if (!getExplicit()) {
|
|
ecComputer = getECComputer((NondetModel) currentModel);
|
|
ecComputer.computeMECStates();
|
|
} else {
|
|
ecComputerExpl = getExplicitECComputer((explicit.NondetModel) currentModelExpl);
|
|
ecComputerExpl.computeMECStates();
|
|
}
|
|
l = System.currentTimeMillis() - l;
|
|
mainLog.println("\nTime for MEC computation: " + l / 1000.0 + " seconds.");
|
|
|
|
// print message
|
|
mainLog.print("\nExporting MECs ");
|
|
mainLog.print(getStringForExportType(exportType) + " ");
|
|
mainLog.println(getDestinationStringForFile(file));
|
|
|
|
// create new file log or use main log
|
|
tmpLog = getPrismLogForFile(file);
|
|
|
|
// print header: list of model vars
|
|
if (exportType == EXPORT_MATLAB)
|
|
tmpLog.print("% ");
|
|
tmpLog.print("Variables: (");
|
|
for (i = 0; i < currentModulesFile.getNumVars(); i++) {
|
|
tmpLog.print(currentModulesFile.getVarName(i));
|
|
if (i < currentModulesFile.getNumVars() - 1)
|
|
tmpLog.print(",");
|
|
}
|
|
tmpLog.println(")");
|
|
|
|
// print states for each mec
|
|
if (!getExplicit()) {
|
|
n = ecComputer.getMECStates().size();
|
|
} else {
|
|
n = ecComputerExpl.getMECStates().size();
|
|
}
|
|
for (i = 0; i < n; i++) {
|
|
tmpLog.println();
|
|
if (exportType == EXPORT_MATLAB)
|
|
tmpLog.print("% ");
|
|
tmpLog.println("MEC " + (i + 1) + "/" + n + ":");
|
|
if (exportType == EXPORT_MATLAB)
|
|
tmpLog.println("mec" + (i + 1) + "=[");
|
|
if (!getExplicit()) {
|
|
if (exportType != EXPORT_MATLAB)
|
|
new StateListMTBDD(ecComputer.getMECStates().get(i), currentModel).print(tmpLog);
|
|
else
|
|
new StateListMTBDD(ecComputer.getMECStates().get(i), currentModel).printMatlab(tmpLog);
|
|
JDD.Deref(ecComputer.getMECStates().get(i));
|
|
} else {
|
|
explicit.StateValues.createFromBitSet(ecComputerExpl.getMECStates().get(i), currentModelExpl).print(tmpLog, true, exportType == EXPORT_MATLAB, true, true);
|
|
}
|
|
if (exportType == EXPORT_MATLAB)
|
|
tmpLog.println("];");
|
|
}
|
|
|
|
// tidy up
|
|
if (file != null)
|
|
tmpLog.close();
|
|
}
|
|
|
|
/**
|
|
* Export the (states of the) currently loaded model's strongly connected components (SCCs) to a file
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportSCCsToFile(int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
int i, n;
|
|
long l; // timer
|
|
PrismLog tmpLog;
|
|
SCCComputer sccComputer = null;
|
|
explicit.SCCComputer sccComputerExpl = null;
|
|
|
|
// no specific states format for MRMC
|
|
if (exportType == EXPORT_MRMC)
|
|
exportType = EXPORT_PLAIN;
|
|
// rows format does not apply to states output
|
|
if (exportType == EXPORT_ROWS)
|
|
exportType = EXPORT_PLAIN;
|
|
|
|
// Build model, if necessary
|
|
buildModelIfRequired();
|
|
|
|
// Compute SCCs
|
|
mainLog.println("\nComputing SCCs...");
|
|
l = System.currentTimeMillis();
|
|
if (!getExplicit()) {
|
|
sccComputer = getSCCComputer(currentModel);
|
|
sccComputer.computeSCCs();
|
|
} else {
|
|
sccComputerExpl = getExplicitSCCComputer(currentModelExpl);
|
|
sccComputerExpl.computeSCCs();
|
|
}
|
|
l = System.currentTimeMillis() - l;
|
|
mainLog.println("\nTime for SCC computation: " + l / 1000.0 + " seconds.");
|
|
|
|
// print message
|
|
mainLog.print("\nExporting SCCs ");
|
|
mainLog.print(getStringForExportType(exportType) + " ");
|
|
mainLog.println(getDestinationStringForFile(file));
|
|
|
|
// create new file log or use main log
|
|
tmpLog = getPrismLogForFile(file);
|
|
|
|
// print header: list of model vars
|
|
if (exportType == EXPORT_MATLAB)
|
|
tmpLog.print("% ");
|
|
tmpLog.print("Variables: (");
|
|
for (i = 0; i < currentModulesFile.getNumVars(); i++) {
|
|
tmpLog.print(currentModulesFile.getVarName(i));
|
|
if (i < currentModulesFile.getNumVars() - 1)
|
|
tmpLog.print(",");
|
|
}
|
|
tmpLog.println(")");
|
|
|
|
// print states for each scc
|
|
if (!getExplicit()) {
|
|
n = sccComputer.getSCCs().size();
|
|
} else {
|
|
n = sccComputerExpl.getSCCs().size();
|
|
}
|
|
for (i = 0; i < n; i++) {
|
|
tmpLog.println();
|
|
if (exportType == EXPORT_MATLAB)
|
|
tmpLog.print("% ");
|
|
tmpLog.println("SCC " + (i + 1) + "/" + n + ":");
|
|
if (exportType == EXPORT_MATLAB)
|
|
tmpLog.println("scc" + (i + 1) + "=[");
|
|
if (!getExplicit()) {
|
|
if (exportType != EXPORT_MATLAB)
|
|
new StateListMTBDD(sccComputer.getSCCs().get(i), currentModel).print(tmpLog);
|
|
else
|
|
new StateListMTBDD(sccComputer.getSCCs().get(i), currentModel).printMatlab(tmpLog);
|
|
JDD.Deref(sccComputer.getSCCs().get(i));
|
|
} else {
|
|
explicit.StateValues.createFromBitSet(sccComputerExpl.getSCCs().get(i), currentModelExpl).print(tmpLog, true, exportType == EXPORT_MATLAB, true, true);
|
|
}
|
|
if (exportType == EXPORT_MATLAB)
|
|
tmpLog.println("];");
|
|
}
|
|
|
|
if (!getExplicit()) {
|
|
JDD.Deref(sccComputer.getNotInSCCs());
|
|
}
|
|
|
|
// tidy up
|
|
if (file != null)
|
|
tmpLog.close();
|
|
}
|
|
|
|
/**
|
|
* Export the states satisfying labels from the currently loaded model and a properties file to a file.
|
|
* The PropertiesFile should correspond to the currently loaded model.
|
|
* @param propertiesFile The properties file (for further labels)
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportLabelsToFile(PropertiesFile propertiesFile, int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
int numLabels;
|
|
LabelList ll;
|
|
|
|
// Get label list and size
|
|
if (propertiesFile == null) {
|
|
ll = currentModulesFile.getLabelList();
|
|
numLabels = ll.size();
|
|
} else {
|
|
ll = propertiesFile.getCombinedLabelList();
|
|
numLabels = ll.size();
|
|
}
|
|
|
|
// Build model, if necessary
|
|
buildModelIfRequired();
|
|
|
|
// Print message
|
|
mainLog.print("\nExporting labels and satisfying states ");
|
|
mainLog.print(getStringForExportType(exportType) + " ");
|
|
mainLog.println(getDestinationStringForFile(file));
|
|
|
|
// Collect labels to export
|
|
List<String> labelNames = new ArrayList<String>();
|
|
labelNames.add("init");
|
|
labelNames.add("deadlock");
|
|
for (int i = 0; i < numLabels; i++) {
|
|
labelNames.add(ll.getLabelName(i));
|
|
}
|
|
|
|
// Export
|
|
if (getExplicit()) {
|
|
PrismLog out = getPrismLogForFile(file);
|
|
explicit.StateModelChecker mcExpl = createModelCheckerExplicit(propertiesFile);
|
|
mcExpl.exportLabels(currentModelExpl, labelNames, exportType, out);
|
|
out.close();
|
|
} else {
|
|
prism.StateModelChecker mc = createModelChecker(propertiesFile);
|
|
mc.exportLabels(labelNames, exportType, file);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Export the currently loaded model's states to a file
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportStatesToFile(int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
PrismLog tmpLog;
|
|
|
|
// No specific states format for MRMC
|
|
if (exportType == EXPORT_MRMC)
|
|
exportType = EXPORT_PLAIN;
|
|
// Rows format does not apply to states output
|
|
if (exportType == EXPORT_ROWS)
|
|
exportType = EXPORT_PLAIN;
|
|
|
|
// Build model, if necessary
|
|
buildModelIfRequired();
|
|
|
|
// Print message
|
|
mainLog.print("\nExporting list of reachable states ");
|
|
mainLog.print(getStringForExportType(exportType) + " ");
|
|
mainLog.println(getDestinationStringForFile(file));
|
|
|
|
// Create new file log or use main log
|
|
tmpLog = getPrismLogForFile(file);
|
|
|
|
// Export
|
|
if (!getExplicit()) {
|
|
currentModel.exportStates(exportType, tmpLog);
|
|
} else {
|
|
currentModelExpl.exportStates(exportType, currentModulesFile.createVarList(), tmpLog);
|
|
}
|
|
|
|
// Tidy up
|
|
if (file != null)
|
|
tmpLog.close();
|
|
}
|
|
|
|
/**
|
|
* Perform model checking of a property on the currently loaded model and return result.
|
|
* @param propertiesFile Parent property file of property (for labels/constants/...)
|
|
* @param expr The property to check
|
|
*/
|
|
public Result modelCheck(PropertiesFile propertiesFile, Expression expr) throws PrismException, PrismLangException
|
|
{
|
|
return modelCheck(propertiesFile, new Property(expr));
|
|
}
|
|
|
|
/**
|
|
* Perform model checking of a property on the currently loaded model and return result.
|
|
* @param propertiesFile Parent property file of property (for labels/constants/...)
|
|
* @param prop The property to check
|
|
*/
|
|
public Result modelCheck(PropertiesFile propertiesFile, Property prop) throws PrismException, PrismLangException
|
|
{
|
|
Result res = null;
|
|
Values definedPFConstants = propertiesFile.getConstantValues();
|
|
boolean engineSwitch = false;
|
|
int lastEngine = -1;
|
|
|
|
if (!digital)
|
|
mainLog.printSeparator();
|
|
mainLog.println("\nModel checking: " + prop);
|
|
if (currentDefinedMFConstants != null && currentDefinedMFConstants.getNumValues() > 0)
|
|
mainLog.println("Model constants: " + currentDefinedMFConstants);
|
|
if (definedPFConstants != null && definedPFConstants.getNumValues() > 0)
|
|
mainLog.println("Property constants: " + definedPFConstants);
|
|
|
|
// Check that property is valid for the current model type
|
|
prop.getExpression().checkValid(currentModelType);
|
|
|
|
// For PTAs...
|
|
if (currentModelType == ModelType.PTA) {
|
|
return modelCheckPTA(propertiesFile, prop.getExpression(), definedPFConstants);
|
|
}
|
|
|
|
// For exact model checking
|
|
if (settings.getBoolean(PrismSettings.PRISM_EXACT_ENABLED)) {
|
|
return modelCheckExact(propertiesFile, prop);
|
|
}
|
|
// For fast adaptive uniformisation
|
|
if (currentModelType == ModelType.CTMC && settings.getString(PrismSettings.PRISM_TRANSIENT_METHOD).equals("Fast adaptive uniformisation")) {
|
|
FastAdaptiveUniformisationModelChecker fauMC;
|
|
fauMC = new FastAdaptiveUniformisationModelChecker(this, currentModulesFile, propertiesFile, getSimulator());
|
|
return fauMC.check(prop.getExpression());
|
|
}
|
|
// Auto-switch engine if required
|
|
else if (currentModelType == ModelType.MDP && !Expression.containsMultiObjective(prop.getExpression())) {
|
|
if (getMDPSolnMethod() != Prism.MDP_VALITER && !getExplicit()) {
|
|
mainLog.printWarning("Switching to explicit engine to allow use of chosen MDP solution method.");
|
|
engineSwitch = true;
|
|
lastEngine = getEngine();
|
|
setEngine(Prism.EXPLICIT);
|
|
}
|
|
}
|
|
try {
|
|
// Build model, if necessary
|
|
buildModelIfRequired();
|
|
|
|
// Compatibility check
|
|
if (genStrat && currentModelType.nondeterministic() && !getExplicit()) {
|
|
if (!((NondetModel) currentModel).areAllChoiceActionsUnique())
|
|
throw new PrismException("Cannot generate strategies with the current engine "
|
|
+ "because some state of the model do not have unique action labels for each choice. "
|
|
+ "Either switch to the explicit engine or add more action labels to the model");
|
|
}
|
|
|
|
// Create new model checker object and do model checking
|
|
if (!getExplicit()) {
|
|
ModelChecker mc = createModelChecker(propertiesFile);
|
|
res = mc.check(prop.getExpression());
|
|
} else {
|
|
explicit.StateModelChecker mc = createModelCheckerExplicit(propertiesFile);
|
|
res = mc.check(currentModelExpl, prop.getExpression());
|
|
}
|
|
} finally {
|
|
// Undo auto-switch (if any)
|
|
if (engineSwitch) {
|
|
setEngine(lastEngine);
|
|
}
|
|
}
|
|
|
|
// Return result
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* Perform model checking of a property on the currently loaded PTA PRISM model and return result.
|
|
* @param propertiesFile Parent property file of property (for labels/constants/...)
|
|
* @param expr The property to check
|
|
* @param definedPFConstants Optional values info for properties file (to display in log)
|
|
*/
|
|
public Result modelCheckPTA(PropertiesFile propertiesFile, Expression expr, Values definedPFConstants) throws PrismException, PrismLangException
|
|
{
|
|
// Check that property is valid for this model type
|
|
// and create new model checker object
|
|
expr.checkValid(currentModelType);
|
|
|
|
// Digital clocks translation
|
|
if (settings.getString(PrismSettings.PRISM_PTA_METHOD).equals("Digital clocks")) {
|
|
digital = true;
|
|
ModulesFile oldModulesFile = currentModulesFile;
|
|
try {
|
|
DigitalClocks dc = new DigitalClocks(this);
|
|
dc.translate(oldModulesFile, propertiesFile, expr);
|
|
currentModulesFile = dc.getNewModulesFile();
|
|
currentModulesFile.setUndefinedConstants(oldModulesFile.getConstantValues());
|
|
currentModelType = ModelType.MDP;
|
|
clearBuiltModel();
|
|
currentModel = null;
|
|
currentModelExpl = null;
|
|
// If required, export generated PRISM model
|
|
if (exportDigital) {
|
|
try {
|
|
exportPRISMModel(exportDigitalFile);
|
|
}
|
|
// In case of error, just print a warning
|
|
catch (FileNotFoundException e) {
|
|
mainLog.printWarning("PRISM code export failed: Couldn't open file \"" + exportDigitalFile + "\" for output");
|
|
} catch (PrismException e) {
|
|
mainLog.printWarning("PRISM code export failed: " + e.getMessage());
|
|
}
|
|
}
|
|
return modelCheck(propertiesFile, expr);
|
|
} finally {
|
|
digital = false;
|
|
currentModulesFile = oldModulesFile;
|
|
currentModelType = ModelType.PTA;
|
|
clearBuiltModel();
|
|
currentModel = null;
|
|
currentModelExpl = null;
|
|
}
|
|
}
|
|
// Other methods
|
|
else {
|
|
PTAModelChecker mcPta;
|
|
mcPta = new PTAModelChecker(this, currentModulesFile, propertiesFile);
|
|
return mcPta.check(expr);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check whether a property is suitable for approximate model checking using the simulator.
|
|
* @param expr The property to check.
|
|
*/
|
|
public boolean isPropertyOKForSimulation(Expression expr)
|
|
{
|
|
return getSimulator().isPropertyOKForSimulation(expr);
|
|
}
|
|
|
|
/**
|
|
* Check if a property is suitable for analysis with the simulator.
|
|
* If not, an explanatory exception is thrown.
|
|
* @param expr The property to check.
|
|
*/
|
|
public void checkPropertyForSimulation(Expression expr) throws PrismException
|
|
{
|
|
getSimulator().checkPropertyForSimulation(expr);
|
|
}
|
|
|
|
/**
|
|
* Perform approximate model checking of a property on the currently loaded model, using the simulator.
|
|
* Sampling starts from the initial state provided or, if null, the default
|
|
* initial state is used, selecting randomly (each time) if there are more than one.
|
|
* Returns a Result object, except in case of error, where an Exception is thrown.
|
|
* Note: All constants in the model/property files must have already been defined.
|
|
* @param propertiesFile Parent property file of property (for labels/constants/...)
|
|
* @param expr The property to check
|
|
* @param definedPFConstants Optional values info for properties file (to display in log)
|
|
* @param initialState Initial state (if null, use default, selecting randomly if needed)
|
|
* @param maxPathLength The maximum path length for sampling
|
|
* @param simMethod Object specifying details of method to use for simulation
|
|
*/
|
|
public Result modelCheckSimulator(PropertiesFile propertiesFile, Expression expr, Values definedPFConstants, State initialState, long maxPathLength,
|
|
SimulationMethod simMethod) throws PrismException
|
|
{
|
|
Object res = null;
|
|
|
|
// Print info
|
|
mainLog.printSeparator();
|
|
mainLog.println("\nSimulating: " + expr);
|
|
if (currentDefinedMFConstants != null && currentDefinedMFConstants.getNumValues() > 0)
|
|
mainLog.println("Model constants: " + currentDefinedMFConstants);
|
|
if (definedPFConstants != null && definedPFConstants.getNumValues() > 0)
|
|
mainLog.println("Property constants: " + definedPFConstants);
|
|
|
|
// Check that property is valid for this model type
|
|
expr.checkValid(currentModelType);
|
|
|
|
// Do simulation
|
|
res = getSimulator().modelCheckSingleProperty(currentModulesFile, propertiesFile, expr, initialState, maxPathLength, simMethod);
|
|
|
|
return new Result(res);
|
|
}
|
|
|
|
/**
|
|
* Perform approximate model checking of several properties (simultaneously) on the currently loaded model, using the simulator.
|
|
* Sampling starts from the initial state provided or, if null, the default
|
|
* initial state is used, selecting randomly (each time) if there are more than one.
|
|
* Returns an array of results, some of which may be Exception objects if there were errors.
|
|
* In the case of an error which affects all properties, an exception is thrown.
|
|
* Note: All constants in the model/property files must have already been defined.
|
|
* @param propertiesFile Parent property file of property (for labels/constants/...)
|
|
* @param exprs The properties to check
|
|
* @param definedPFConstants Optional values info for properties file (to display in log)
|
|
* @param initialState Initial state (if null, use default, selecting randomly if needed)
|
|
* @param maxPathLength The maximum path length for sampling
|
|
* @param simMethod Object specifying details of method to use for simulation
|
|
*/
|
|
public Result[] modelCheckSimulatorSimultaneously(PropertiesFile propertiesFile, List<Expression> exprs, Values definedPFConstants, State initialState,
|
|
long maxPathLength, SimulationMethod simMethod) throws PrismException
|
|
{
|
|
Object[] res = null;
|
|
|
|
// Print info
|
|
mainLog.printSeparator();
|
|
mainLog.print("\nSimulating");
|
|
if (exprs.size() == 1) {
|
|
mainLog.println(": " + exprs.get(0));
|
|
} else {
|
|
mainLog.println(" " + exprs.size() + " properties:");
|
|
for (int i = 0; i < exprs.size(); i++) {
|
|
mainLog.println(" " + exprs.get(i));
|
|
}
|
|
}
|
|
if (currentDefinedMFConstants != null && currentDefinedMFConstants.getNumValues() > 0)
|
|
mainLog.println("Model constants: " + currentDefinedMFConstants);
|
|
if (definedPFConstants != null && definedPFConstants.getNumValues() > 0)
|
|
mainLog.println("Property constants: " + definedPFConstants);
|
|
|
|
// Check that properties are valid for this model type
|
|
for (Expression expr : exprs)
|
|
expr.checkValid(currentModelType);
|
|
|
|
// Do simulation
|
|
res = getSimulator().modelCheckMultipleProperties(currentModulesFile, propertiesFile, exprs, initialState, maxPathLength, simMethod);
|
|
|
|
Result[] resArray = new Result[res.length];
|
|
for (int i = 0; i < res.length; i++)
|
|
resArray[i] = new Result(res[i]);
|
|
return resArray;
|
|
}
|
|
|
|
/**
|
|
* Perform an approximate model checking experiment on the currently loaded model, using the simulator.
|
|
* (specified by values for undefined constants from the property only).
|
|
* Sampling starts from the initial state provided or, if null, the default
|
|
* initial state is used, selecting randomly (each time) if there are more than one.
|
|
* Results are stored in the ResultsCollection object passed in,
|
|
* some of which may be Exception objects if there were errors.
|
|
* In the case of an error which affects all properties, an exception is thrown.
|
|
* Note: All constants in the model file must have already been defined.
|
|
* @param propertiesFile Properties file containing property to check, constants defined
|
|
* @param undefinedConstants Details of constant ranges defining the experiment
|
|
* @param results Where to store the results
|
|
* @param expr The property to check
|
|
* @param initialState Initial state (if null, is selected randomly)
|
|
* @param maxPathLength The maximum path length for sampling
|
|
* @param simMethod Object specifying details of method to use for simulation
|
|
* @throws PrismException if something goes wrong with the sampling algorithm
|
|
* @throws InterruptedException if the thread is interrupted
|
|
*/
|
|
public void modelCheckSimulatorExperiment(PropertiesFile propertiesFile, UndefinedConstants undefinedConstants, ResultsCollection results, Expression expr,
|
|
State initialState, long maxPathLength, SimulationMethod simMethod) throws PrismException, InterruptedException
|
|
{
|
|
// Print info
|
|
mainLog.printSeparator();
|
|
mainLog.println("\nSimulating: " + expr);
|
|
if (currentDefinedMFConstants != null && currentDefinedMFConstants.getNumValues() > 0)
|
|
mainLog.println("Model constants: " + currentDefinedMFConstants);
|
|
mainLog.println("Property constants: " + undefinedConstants.getPFDefinedConstantsString());
|
|
|
|
// Do simulation
|
|
getSimulator().modelCheckExperiment(currentModulesFile, propertiesFile, undefinedConstants, results, expr, initialState, maxPathLength, simMethod);
|
|
}
|
|
|
|
/**
|
|
* Perform model checking on the currently loaded model using exact methods
|
|
* (currently, this is done via the parametric model checking functionality)
|
|
* @param propertiesFile parent properties file
|
|
* @param prop property to model check
|
|
*/
|
|
public Result modelCheckExact(PropertiesFile propertiesFile, Property prop) throws PrismException
|
|
{
|
|
// Some checks
|
|
if (!(currentModelType == ModelType.DTMC || currentModelType == ModelType.CTMC || currentModelType == ModelType.MDP))
|
|
throw new PrismException("Exact model checking is only supported for DTMCs, CTMCs and MDPs");
|
|
|
|
// Set up a dummy parameter (not used)
|
|
String[] paramNames = new String[] { "dummy" };
|
|
String[] paramLowerBounds = new String[] { "0" };
|
|
String[] paramUpperBounds = new String[] { "1" };
|
|
// And execute parameteric model checking
|
|
param.ModelBuilder builder = new ModelBuilder(this);
|
|
builder.setModulesFile(currentModulesFile);
|
|
builder.setParameters(paramNames, paramLowerBounds, paramUpperBounds);
|
|
builder.build();
|
|
explicit.Model modelExpl = builder.getModel();
|
|
ParamModelChecker mc = new ParamModelChecker(this);
|
|
mc.setModelBuilder(builder);
|
|
mc.setParameters(paramNames, paramLowerBounds, paramUpperBounds);
|
|
mc.setModulesFileAndPropertiesFile(currentModulesFile, propertiesFile);
|
|
Result result = mc.check(modelExpl, prop.getExpression());
|
|
|
|
// Convert result of parametric model checking to just a rational
|
|
// There should be just one region since no parameters are used
|
|
RegionValues regVals = (RegionValues) result.getResult();
|
|
if (regVals.getNumRegions() != 1)
|
|
throw new PrismException("Unexpected result from paramteric model checker");
|
|
param.Function func = regVals.getResult(0).getInitStateValueAsFunction();
|
|
// Evaluate the function at an arbitrary point (should not depend on parameter values)
|
|
BigRational rat = func.evaluate(new param.Point(new BigRational[] { new BigRational(0) }));
|
|
// Restore in result object
|
|
result.setResult(rat);
|
|
|
|
// Print result to log
|
|
String resultString = "Result";
|
|
if (!("Result".equals(prop.getExpression().getResultName())))
|
|
resultString += " (" + prop.getExpression().getResultName().toLowerCase() + ")";
|
|
resultString += ": " + result.getResultString();
|
|
mainLog.print("\n" + resultString);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Perform parametric model checking on the currently loaded model.
|
|
* @param propertiesFile parent properties file
|
|
* @param prop property to model check
|
|
* @param paramNames parameter names
|
|
* @param paramLowerBounds lower bounds of parameters
|
|
* @param paramUpperBounds upper bounds of parameters
|
|
*/
|
|
public Result modelCheckParametric(PropertiesFile propertiesFile, Property prop, String[] paramNames, String[] paramLowerBounds, String[] paramUpperBounds)
|
|
throws PrismException
|
|
{
|
|
// Some checks
|
|
if (paramNames == null) {
|
|
throw new PrismException("Must specify some parameters when using " + "the parametric analysis");
|
|
}
|
|
if (!(currentModelType == ModelType.DTMC || currentModelType == ModelType.CTMC || currentModelType == ModelType.MDP))
|
|
throw new PrismException("Parametric model checking is only supported for DTMCs, CTMCs and MDPs");
|
|
|
|
Values definedPFConstants = propertiesFile.getConstantValues();
|
|
Values constlist = currentModulesFile.getConstantValues();
|
|
for (int pnr = 0; pnr < paramNames.length; pnr++) {
|
|
constlist.removeValue(paramNames[pnr]);
|
|
}
|
|
|
|
// Print info
|
|
mainLog.printSeparator();
|
|
mainLog.println("\nParametric model checking: " + prop);
|
|
if (currentDefinedMFConstants != null && currentDefinedMFConstants.getNumValues() > 0)
|
|
mainLog.println("Model constants: " + currentDefinedMFConstants);
|
|
if (definedPFConstants != null && definedPFConstants.getNumValues() > 0)
|
|
mainLog.println("Property constants: " + definedPFConstants);
|
|
|
|
param.ModelBuilder builder = new ModelBuilder(this);
|
|
builder.setModulesFile(currentModulesFile);
|
|
builder.setParameters(paramNames, paramLowerBounds, paramUpperBounds);
|
|
builder.build();
|
|
explicit.Model modelExpl = builder.getModel();
|
|
ParamModelChecker mc = new ParamModelChecker(this);
|
|
mc.setModelBuilder(builder);
|
|
mc.setParameters(paramNames, paramLowerBounds, paramUpperBounds);
|
|
mc.setModulesFileAndPropertiesFile(currentModulesFile, propertiesFile);
|
|
Result result = mc.check(modelExpl, prop.getExpression());
|
|
|
|
// Print result to log
|
|
String resultString = "Result";
|
|
if (!("Result".equals(prop.getExpression().getResultName())))
|
|
resultString += " (" + prop.getExpression().getResultName().toLowerCase() + ")";
|
|
resultString += ": " + result.getResultString();
|
|
mainLog.print("\n" + resultString);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Export a strategy. The associated model should be attached to the strategy.
|
|
* Strictly, speaking that does not need to be the currently loaded model,
|
|
* but it would probably have been discarded if that was not the case.
|
|
* @param strat The strategy
|
|
* @param exportType The type of output
|
|
* @param file File to output the path to (stdout if null)
|
|
*/
|
|
public void exportStrategy(Strategy strat, StrategyExportType exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
PrismLog tmpLog;
|
|
|
|
// Print message
|
|
mainLog.print("\nExporting strategy " + exportType.description() + " ");
|
|
mainLog.println(getDestinationStringForFile(file));
|
|
|
|
// Export to file (or use main log)
|
|
tmpLog = getPrismLogForFile(file);
|
|
switch (exportType) {
|
|
case ACTIONS:
|
|
strat.exportActions(tmpLog);
|
|
break;
|
|
case INDICES:
|
|
strat.exportIndices(tmpLog);
|
|
break;
|
|
case INDUCED_MODEL:
|
|
strat.exportInducedModel(tmpLog);
|
|
break;
|
|
case DOT_FILE:
|
|
strat.exportDotFile(tmpLog);
|
|
break;
|
|
}
|
|
if (file != null)
|
|
tmpLog.close();
|
|
}
|
|
|
|
/**
|
|
* Generate a random path through the model using the simulator.
|
|
* @param modulesFile The model
|
|
* @param details Information about the path to be generated
|
|
* @param maxPathLength The maximum length of path to generate
|
|
* @param file File to output the path to (stdout if null)
|
|
*/
|
|
public void generateSimulationPath(ModulesFile modulesFile, String details, long maxPathLength, File file) throws PrismException, PrismLangException
|
|
{
|
|
GenerateSimulationPath genPath = new GenerateSimulationPath(getSimulator(), mainLog);
|
|
genPath.generateSimulationPath(modulesFile, null, details, maxPathLength, file);
|
|
}
|
|
|
|
/**
|
|
* Compute steady-state probabilities for the current model (DTMCs/CTMCs only).
|
|
* Output probability distribution to log.
|
|
*/
|
|
public void doSteadyState() throws PrismException
|
|
{
|
|
doSteadyState(EXPORT_PLAIN, null, null);
|
|
}
|
|
|
|
/**
|
|
* Compute steady-state probabilities for the current model (DTMCs/CTMCs only).
|
|
* Output probability distribution to a file (or, if {@code fileOut} is null, to log).
|
|
* The exportType should be EXPORT_PLAIN or EXPORT_MATLAB.
|
|
* Optionally (if non-null), read in the initial probability distribution from a file.
|
|
*/
|
|
public void doSteadyState(int exportType, File fileOut, File fileIn) throws PrismException
|
|
{
|
|
long l = 0; // timer
|
|
StateValues probs = null;
|
|
explicit.StateValues probsExpl = null;
|
|
PrismLog tmpLog;
|
|
|
|
// Do some checks
|
|
if (!(currentModelType == ModelType.CTMC || currentModelType == ModelType.DTMC))
|
|
throw new PrismException("Steady-state probabilities only computed for DTMCs/CTMCs");
|
|
if (fileOut != null && getEngine() == MTBDD)
|
|
// TODO: auto-switch?
|
|
throw new PrismException("Steady-state probability export not supported for MTBDD engine");
|
|
if (exportType == EXPORT_MRMC)
|
|
exportType = EXPORT_PLAIN; // no specific states format for MRMC
|
|
if (exportType == EXPORT_ROWS)
|
|
exportType = EXPORT_PLAIN; // rows format does not apply to states output
|
|
|
|
// Print message
|
|
mainLog.printSeparator();
|
|
mainLog.println("\nComputing steady-state probabilities...");
|
|
|
|
// Build model, if necessary
|
|
buildModelIfRequired();
|
|
|
|
l = System.currentTimeMillis();
|
|
if (!getExplicit()) {
|
|
probs = computeSteadyStateProbabilities(currentModel, fileIn);
|
|
} else {
|
|
probsExpl = computeSteadyStateProbabilitiesExplicit(currentModelExpl, fileIn);
|
|
}
|
|
l = System.currentTimeMillis() - l;
|
|
|
|
// print message
|
|
mainLog.print("\nPrinting steady-state probabilities ");
|
|
mainLog.print(getStringForExportType(exportType) + " ");
|
|
mainLog.println(getDestinationStringForFile(fileOut));
|
|
|
|
// create new file log or use main log
|
|
tmpLog = getPrismLogForFile(fileOut);
|
|
|
|
// print out or export probabilities
|
|
if (!getExplicit())
|
|
probs.print(tmpLog, fileOut == null, exportType == EXPORT_MATLAB, fileOut == null, fileOut == null);
|
|
else
|
|
probsExpl.print(tmpLog, fileOut == null, exportType == EXPORT_MATLAB, fileOut == null, fileOut == null);
|
|
|
|
// print out computation time
|
|
mainLog.println("\nTime for steady-state probability computation: " + l / 1000.0 + " seconds.");
|
|
|
|
// tidy up
|
|
if (!getExplicit())
|
|
probs.clear();
|
|
else
|
|
probsExpl.clear();
|
|
if (fileOut != null)
|
|
tmpLog.close();
|
|
}
|
|
|
|
/**
|
|
* Compute steady-state probabilities (for a DTMC or CTMC) using symbolic engines.
|
|
* Optionally (if non-null), read in the initial probability distribution from a file.
|
|
* If null, start from initial state (or uniform distribution over multiple initial states).
|
|
*/
|
|
protected StateValues computeSteadyStateProbabilities(Model model, File fileIn) throws PrismException
|
|
{
|
|
ProbModelChecker mc;
|
|
if (model.getModelType() == ModelType.DTMC) {
|
|
mc = new ProbModelChecker(this, model, null);
|
|
}
|
|
else if (model.getModelType() == ModelType.CTMC) {
|
|
mc = new StochModelChecker(this, model, null);
|
|
}
|
|
else {
|
|
throw new PrismException("Steady-state probabilities only computed for DTMCs/CTMCs");
|
|
}
|
|
return mc.doSteadyState(fileIn);
|
|
}
|
|
|
|
/**
|
|
* Compute steady-state probabilities (for a DTMC or CTMC) using the explicit engine.
|
|
* Optionally (if non-null), read in the initial probability distribution from a file.
|
|
* If null, start from initial state (or uniform distribution over multiple initial states).
|
|
*/
|
|
protected explicit.StateValues computeSteadyStateProbabilitiesExplicit(explicit.Model model, File fileIn) throws PrismException
|
|
{
|
|
DTMCModelChecker mcDTMC;
|
|
explicit.StateValues probs;
|
|
if (model.getModelType() == ModelType.DTMC) {
|
|
mcDTMC = new DTMCModelChecker(this);
|
|
//TODO: probs = mcDTMC.doSteadyState((DTMC) model, fileIn);
|
|
probs = mcDTMC.doSteadyState((DTMC) model, (File) null);
|
|
} else if (model.getModelType() == ModelType.CTMC) {
|
|
throw new PrismException("Not implemented yet");
|
|
} else {
|
|
throw new PrismException("Steady-state probabilities only computed for DTMCs/CTMCs");
|
|
}
|
|
return probs;
|
|
}
|
|
|
|
/**
|
|
* Compute transient probabilities (forwards) for the current model (DTMCs/CTMCs only).
|
|
* Output probability distribution to log.
|
|
* For a discrete-time model, {@code time} will be cast to an integer.
|
|
*/
|
|
public void doTransient(double time) throws PrismException
|
|
{
|
|
doTransient(time, EXPORT_PLAIN, null, null);
|
|
}
|
|
|
|
/**
|
|
* Compute transient probabilities (forwards) for the current model (DTMCs/CTMCs only).
|
|
* Output probability distribution to a file (or, if {@code fileOut} is null, to log).
|
|
* For a discrete-time model, {@code time} will be cast to an integer.
|
|
* The exportType should be EXPORT_PLAIN or EXPORT_MATLAB.
|
|
* Optionally (if non-null), read in the initial probability distribution from a file.
|
|
*/
|
|
public void doTransient(double time, int exportType, File fileOut, File fileIn) throws PrismException
|
|
{
|
|
long l = 0; // timer
|
|
ModelChecker mc = null;
|
|
StateValues probs = null;
|
|
explicit.StateValues probsExpl = null;
|
|
PrismLog tmpLog;
|
|
|
|
// Do some checks
|
|
if (!(currentModelType == ModelType.CTMC || currentModelType == ModelType.DTMC))
|
|
throw new PrismException("Steady-state probabilities only computed for DTMCs/CTMCs");
|
|
if (time < 0)
|
|
throw new PrismException("Cannot compute transient probabilities for negative time value");
|
|
if (fileOut != null && getEngine() == MTBDD)
|
|
throw new PrismException("Transient probability export only supported for sparse/hybrid engines");
|
|
if (exportType == EXPORT_MRMC)
|
|
exportType = EXPORT_PLAIN; // no specific states format for MRMC
|
|
if (exportType == EXPORT_ROWS)
|
|
exportType = EXPORT_PLAIN; // rows format does not apply to states output
|
|
|
|
// Print message
|
|
mainLog.printSeparator();
|
|
String strTime = currentModelType.continuousTime() ? Double.toString(time) : Integer.toString((int) time);
|
|
mainLog.println("\nComputing transient probabilities (time = " + strTime + ")...");
|
|
|
|
l = System.currentTimeMillis();
|
|
|
|
// FAU
|
|
if (currentModelType == ModelType.CTMC && settings.getString(PrismSettings.PRISM_TRANSIENT_METHOD).equals("Fast adaptive uniformisation")) {
|
|
PrismModelExplorer modelExplorer = new PrismModelExplorer(getSimulator(), currentModulesFile);
|
|
FastAdaptiveUniformisation fau = new FastAdaptiveUniformisation(this, modelExplorer);
|
|
fau.setConstantValues(currentModulesFile.getConstantValues());
|
|
probsExpl = fau.doTransient(time, fileIn, currentModel);
|
|
}
|
|
// Symbolic
|
|
else if (!getExplicit()) {
|
|
buildModelIfRequired();
|
|
if (currentModelType == ModelType.DTMC) {
|
|
mc = new ProbModelChecker(this, currentModel, null);
|
|
probs = ((ProbModelChecker) mc).doTransient((int) time, fileIn);
|
|
} else {
|
|
mc = new StochModelChecker(this, currentModel, null);
|
|
probs = ((StochModelChecker) mc).doTransient(time, fileIn);
|
|
}
|
|
}
|
|
// Explicit
|
|
else {
|
|
buildModelIfRequired();
|
|
if (currentModelType == ModelType.DTMC) {
|
|
throw new PrismException("Not implemented yet");
|
|
} else if (currentModelType == ModelType.CTMC) {
|
|
CTMCModelChecker mcCTMC = new CTMCModelChecker(this);
|
|
probsExpl = mcCTMC.doTransient((CTMC) currentModelExpl, time, fileIn);
|
|
} else {
|
|
throw new PrismException("Transient probabilities only computed for DTMCs/CTMCs");
|
|
}
|
|
}
|
|
|
|
l = System.currentTimeMillis() - l;
|
|
|
|
// print message
|
|
mainLog.print("\nPrinting transient probabilities ");
|
|
mainLog.print(getStringForExportType(exportType) + " ");
|
|
mainLog.println(getDestinationStringForFile(fileOut));
|
|
|
|
// create new file log or use main log
|
|
tmpLog = getPrismLogForFile(fileOut);
|
|
|
|
// print out or export probabilities
|
|
if (probs != null)
|
|
probs.print(tmpLog, fileOut == null, exportType == EXPORT_MATLAB, fileOut == null, fileOut == null);
|
|
else
|
|
probsExpl.print(tmpLog, fileOut == null, exportType == EXPORT_MATLAB, fileOut == null, fileOut == null);
|
|
|
|
// print out computation time
|
|
mainLog.println("\nTime for transient probability computation: " + l / 1000.0 + " seconds.");
|
|
|
|
// tidy up
|
|
if (probs != null)
|
|
probs.clear();
|
|
if (probsExpl != null)
|
|
probsExpl.clear();
|
|
if (fileOut != null)
|
|
tmpLog.close();
|
|
}
|
|
|
|
/**
|
|
* Compute transient probabilities (forwards) for the current model (DTMCs/CTMCs only)
|
|
* for a range of time points. Each distribution is computed incrementally.
|
|
* Output probability distribution to a file (or, if file is null, to log).
|
|
* Time points are specified using an UndefinedConstants with a single ranging variable
|
|
* (of the appropriate type (int/double) and with arbitrary name).
|
|
* The exportType should be EXPORT_PLAIN or EXPORT_MATLAB.
|
|
* Optionally (if non-null), read in the initial probability distribution from a file.
|
|
*/
|
|
public void doTransient(UndefinedConstants times, int exportType, File fileOut, File fileIn) throws PrismException
|
|
{
|
|
int i, timeInt = 0, initTimeInt = 0;
|
|
double timeDouble = 0, initTimeDouble = 0;
|
|
Object time;
|
|
long l = 0; // timer
|
|
StateValues probs = null, initDist = null;
|
|
explicit.StateValues probsExpl = null, initDistExpl = null;
|
|
PrismLog tmpLog = null;
|
|
File fileOutActual = null;
|
|
|
|
// Do some checks
|
|
if (!(currentModelType == ModelType.CTMC || currentModelType == ModelType.DTMC))
|
|
throw new PrismException("Steady-state probabilities only computed for DTMCs/CTMCs");
|
|
if (fileOut != null && getEngine() == MTBDD)
|
|
throw new PrismException("Transient probability export only supported for sparse/hybrid engines");
|
|
if (exportType == EXPORT_MRMC)
|
|
exportType = EXPORT_PLAIN; // no specific states format for MRMC
|
|
if (exportType == EXPORT_ROWS)
|
|
exportType = EXPORT_PLAIN; // rows format does not apply to states output
|
|
|
|
// Step through required time points
|
|
for (i = 0; i < times.getNumPropertyIterations(); i++) {
|
|
|
|
// Get time, check non-negative
|
|
time = times.getPFConstantValues().getValue(0);
|
|
if (currentModelType.continuousTime())
|
|
timeDouble = ((Double) time).doubleValue();
|
|
else
|
|
timeInt = ((Integer) time).intValue();
|
|
if (currentModelType.continuousTime() ? (((Double) time).doubleValue() < 0) : (((Integer) time).intValue() < 0))
|
|
throw new PrismException("Cannot compute transient probabilities for negative time value");
|
|
|
|
// Print message
|
|
mainLog.printSeparator();
|
|
mainLog.println("\nComputing transient probabilities (time = " + time + ")...");
|
|
|
|
l = System.currentTimeMillis();
|
|
|
|
// FAU
|
|
if (currentModelType == ModelType.CTMC && settings.getString(PrismSettings.PRISM_TRANSIENT_METHOD).equals("Fast adaptive uniformisation")) {
|
|
PrismModelExplorer modelExplorer = new PrismModelExplorer(getSimulator(), currentModulesFile);
|
|
FastAdaptiveUniformisation fau = new FastAdaptiveUniformisation(this, modelExplorer);
|
|
fau.setConstantValues(currentModulesFile.getConstantValues());
|
|
if (i == 0) {
|
|
probsExpl = fau.doTransient(timeDouble, fileIn, currentModel);
|
|
initTimeDouble = 0.0;
|
|
} else {
|
|
probsExpl = fau.doTransient(timeDouble - initTimeDouble, probsExpl);
|
|
}
|
|
}
|
|
// Symbolic
|
|
else if (!getExplicit()) {
|
|
buildModelIfRequired();
|
|
if (currentModelType.continuousTime()) {
|
|
StochModelChecker mc = new StochModelChecker(this, currentModel, null);
|
|
if (i == 0) {
|
|
initDist = mc.readDistributionFromFile(fileIn);
|
|
initTimeDouble = 0;
|
|
}
|
|
probs = ((StochModelChecker) mc).doTransient(timeDouble - initTimeDouble, initDist);
|
|
} else {
|
|
ProbModelChecker mc = new ProbModelChecker(this, currentModel, null);
|
|
if (i == 0) {
|
|
initDist = mc.readDistributionFromFile(fileIn);
|
|
initTimeInt = 0;
|
|
}
|
|
probs = ((ProbModelChecker) mc).doTransient(timeInt - initTimeInt, initDist);
|
|
}
|
|
}
|
|
// Explicit
|
|
else {
|
|
buildModelIfRequired();
|
|
if (currentModelType.continuousTime()) {
|
|
CTMCModelChecker mc = new CTMCModelChecker(this);
|
|
if (i == 0) {
|
|
initDistExpl = mc.readDistributionFromFile(fileIn, currentModelExpl);
|
|
initTimeDouble = 0;
|
|
}
|
|
probsExpl = mc.doTransient((CTMC) currentModelExpl, timeDouble - initTimeDouble, initDistExpl);
|
|
} else {
|
|
throw new PrismException("Not implemented yet");
|
|
}
|
|
}
|
|
|
|
l = System.currentTimeMillis() - l;
|
|
|
|
// If output is to a file and there are multiple points, change filename
|
|
if (fileOut != null && times.getNumPropertyIterations() > 1) {
|
|
fileOutActual = new File(PrismUtils.addSuffixToFilename(fileOut.getPath(), time.toString()));
|
|
} else {
|
|
fileOutActual = fileOut;
|
|
}
|
|
|
|
// print message
|
|
mainLog.print("\nPrinting transient probabilities ");
|
|
mainLog.print(getStringForExportType(exportType) + " ");
|
|
mainLog.println(getDestinationStringForFile(fileOutActual));
|
|
|
|
// create new file log or use main log
|
|
tmpLog = getPrismLogForFile(fileOutActual);
|
|
|
|
// print out or export probabilities
|
|
if (probs != null)
|
|
probs.print(tmpLog, fileOut == null, exportType == EXPORT_MATLAB, fileOut == null);
|
|
else if (!settings.getString(PrismSettings.PRISM_TRANSIENT_METHOD).equals("Fast adaptive uniformisation")) {
|
|
probsExpl.print(tmpLog, fileOut == null, exportType == EXPORT_MATLAB, fileOut == null, true);
|
|
} else {
|
|
// If full state space not computed, don't print vectors and always show states
|
|
probsExpl.print(tmpLog, fileOut == null, exportType == EXPORT_MATLAB, true, false);
|
|
}
|
|
|
|
// print out computation time
|
|
mainLog.println("\nTime for transient probability computation: " + l / 1000.0 + " seconds.");
|
|
|
|
// Prepare for next iteration
|
|
initDist = probs;
|
|
initDistExpl = probsExpl;
|
|
initTimeInt = timeInt;
|
|
initTimeDouble = timeDouble;
|
|
times.iterateProperty();
|
|
}
|
|
|
|
// tidy up
|
|
if (probs != null)
|
|
probs.clear();
|
|
if (probsExpl != null)
|
|
probsExpl.clear();
|
|
if (fileOut != null)
|
|
tmpLog.close();
|
|
}
|
|
|
|
public void explicitBuildTest() throws PrismException
|
|
{
|
|
/* old code...
|
|
String tmpFile = "";
|
|
try {
|
|
explicit.ConstructModel constructModel = new explicit.ConstructModel(getSimulator(), mainLog);
|
|
mainLog.println("\nConstructing model explicitly...");
|
|
explicit.Model modelExplicit = constructModel.constructModel(currentModulesFile);
|
|
tmpFile = File.createTempFile("explicitbuildtest", ".tra").getAbsolutePath();
|
|
tmpFile = "explicitbuildtest.tra";
|
|
mainLog.println("\nExporting (explicit) model to \"" + tmpFile + "1\"...");
|
|
modelExplicit.exportToPrismExplicitTra(tmpFile + "1");
|
|
mainLog.println("\nExporting (normal) model to \"" + tmpFile + "2\"...");
|
|
exportTransToFile(true, Prism.EXPORT_PLAIN, new File(tmpFile + "2"));
|
|
explicit.ModelSimple modelExplicit2 = null;
|
|
switch (currentModelType) {
|
|
case DTMC:
|
|
modelExplicit2 = new explicit.DTMCSimple();
|
|
break;
|
|
case CTMC:
|
|
modelExplicit2 = new explicit.CTMCSimple();
|
|
break;
|
|
case MDP:
|
|
modelExplicit2 = new explicit.MDPSimple();
|
|
break;
|
|
}
|
|
modelExplicit2.buildFromPrismExplicit(tmpFile + "2");
|
|
if (!modelExplicit.equals(modelExplicit2)) {
|
|
throw new PrismException("Explicit models differ");
|
|
}
|
|
} catch (IOException e) {
|
|
throw new PrismException("Could not create temporary file \"" + tmpFile + "\"");
|
|
}*/
|
|
}
|
|
|
|
/**
|
|
* Clear the built model if needed (free/deallocate memory etc)
|
|
*/
|
|
private void clearBuiltModel()
|
|
{
|
|
if (currentModel != null)
|
|
currentModel.clear();
|
|
/*if (currentModelExpl != null)
|
|
currentModelExpl.clear();*/
|
|
}
|
|
|
|
/**
|
|
* Clear up and close down.
|
|
*/
|
|
public void closeDown()
|
|
{
|
|
closeDown(true);
|
|
}
|
|
|
|
/**
|
|
* Clear up and close down.
|
|
* @param check Whether to perform checks on CUDD status when shutting it down.
|
|
*/
|
|
public void closeDown(boolean check)
|
|
{
|
|
// Clear any built model(s)
|
|
clearBuiltModel();
|
|
// Close down libraries/engines
|
|
PrismNative.closeDown();
|
|
PrismMTBDD.closeDown();
|
|
PrismSparse.closeDown();
|
|
PrismHybrid.closeDown();
|
|
ParamModelChecker.closeDown();
|
|
// Close down CUDD/JDD
|
|
if (cuddStarted) {
|
|
JDD.CloseDownCUDD(check);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Utility method to create and initialise a (symbolic) model checker based on the current model.
|
|
* @param propertiesFile Optional properties file for extra info needed during model checking (can be null)
|
|
*/
|
|
private StateModelChecker createModelChecker(PropertiesFile propertiesFile) throws PrismException
|
|
{
|
|
// Create a dummy properties file if none exist
|
|
// (the symbolic model checkers rely on this to store e.g. model labels)
|
|
if (propertiesFile == null) {
|
|
propertiesFile = parsePropertiesString(currentModulesFile, "");
|
|
}
|
|
// Create model checker
|
|
StateModelChecker mc = StateModelChecker.createModelChecker(currentModelType, this, currentModel, propertiesFile);
|
|
// Pass any additional local settings
|
|
// TODO
|
|
|
|
return mc;
|
|
}
|
|
|
|
/**
|
|
* Utility method to create and initialise an (explicit) model checker based on the current model.
|
|
* @param propertiesFile Optional properties file for extra info needed during model checking (can be null)
|
|
*/
|
|
private explicit.StateModelChecker createModelCheckerExplicit(PropertiesFile propertiesFile) throws PrismException
|
|
{
|
|
// Create model checker
|
|
explicit.StateModelChecker mc = explicit.StateModelChecker.createModelChecker(currentModelType, this);
|
|
mc.setModulesFileAndPropertiesFile(currentModulesFile, propertiesFile);
|
|
// Pass any additional local settings
|
|
mc.setExportTarget(exportTarget);
|
|
mc.setExportTargetFilename(exportTargetFilename);
|
|
mc.setExportProductTrans(exportProductTrans);
|
|
mc.setExportProductTransFilename(exportProductTransFilename);
|
|
mc.setExportProductStates(exportProductStates);
|
|
mc.setExportProductStatesFilename(exportProductStatesFilename);
|
|
mc.setStoreVector(storeVector);
|
|
mc.setGenStrat(genStrat);
|
|
mc.setDoBisim(doBisim);
|
|
|
|
return mc;
|
|
}
|
|
|
|
/**
|
|
* Either create a new PrismFileLog for {@code file} or,
|
|
* if {@code file} is null, return {@code mainLog}.
|
|
* Throws a {@code PrismException} if there is a problem opening the file.
|
|
*/
|
|
private PrismLog getPrismLogForFile(File file) throws PrismException
|
|
{
|
|
return getPrismLogForFile(file, false);
|
|
}
|
|
|
|
/**
|
|
* Either create a new PrismFileLog for {@code file} or,
|
|
* if {@code file} is null, return {@code mainLog}.
|
|
* Throws a {@code PrismException} if there is a problem opening the file.
|
|
* If {@code append} is true, file should be opened in "append" mode.
|
|
*/
|
|
private PrismLog getPrismLogForFile(File file, boolean append) throws PrismException
|
|
{
|
|
// create new file log or use main log
|
|
PrismLog tmpLog;
|
|
if (file != null) {
|
|
tmpLog = PrismFileLog.create(file.getPath(), append);
|
|
} else {
|
|
tmpLog = mainLog;
|
|
}
|
|
return tmpLog;
|
|
}
|
|
|
|
/**
|
|
* Get a string describing an output format, e.g. "in plain text format" for EXPORT_PLAIN.
|
|
*/
|
|
private static String getStringForExportType(int exportType)
|
|
{
|
|
switch (exportType) {
|
|
case EXPORT_PLAIN:
|
|
return "in plain text format";
|
|
case EXPORT_MATLAB:
|
|
return "in Matlab format";
|
|
case EXPORT_DOT:
|
|
return "in Dot format";
|
|
case EXPORT_MRMC:
|
|
return "in MRMC format";
|
|
case EXPORT_ROWS:
|
|
return "in rows format";
|
|
case EXPORT_DOT_STATES:
|
|
return "in Dot format (with states)";
|
|
default:
|
|
return "in ? format";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a string describing the output destination specified by a File:
|
|
* "to file \"filename\"..." if non-null; "below:" if null
|
|
*/
|
|
private static String getDestinationStringForFile(File file)
|
|
{
|
|
return (file == null) ? "below:" : "to file \"" + file + "\"...";
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Old API methods, supported via new one
|
|
//------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Old API:
|
|
* Load a PRISM model, build it, store for later use and return.
|
|
* Reachability and model construction are done symbolically, i.e. using (MT)BDDs.
|
|
* It is assumed that all constants in the PRISM model file have been defined by now.
|
|
* @param modulesFile Model to build
|
|
*/
|
|
public Model buildModel(ModulesFile modulesFile) throws PrismException
|
|
{
|
|
loadPRISMModel(modulesFile);
|
|
buildModel();
|
|
return getBuiltModel();
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load a (built) model and export its transition matrix to a Spy file.
|
|
* @param model The model
|
|
* @param file File to export to
|
|
*/
|
|
public void exportToSpyFile(Model model, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
loadBuiltModel(model);
|
|
exportToSpyFile(file);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load a (built) model and export the MTBDD for its transition matrix to a Dot file.
|
|
* @param model The model
|
|
* @param file File to export to
|
|
*/
|
|
public void exportToDotFile(Model model, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
loadBuiltModel(model);
|
|
exportToDotFile(file);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load a (built) model and export its transition matrix to a file
|
|
* @param model The model
|
|
* @param ordered Ensure that (source) states are in ascending order?
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* <li> {@link #EXPORT_DOT}
|
|
* <li> {@link #EXPORT_MRMC}
|
|
* <li> {@link #EXPORT_ROWS}
|
|
* <li> {@link #EXPORT_DOT_STATES}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportToFile(Model model, boolean ordered, int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
exportTransToFile(model, ordered, exportType, file);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load a (built) model and export its transition matrix to a file (or to the log)
|
|
* @param model The model
|
|
* @param ordered Ensure that (source) states are in ascending order?
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* <li> {@link #EXPORT_DOT}
|
|
* <li> {@link #EXPORT_MRMC}
|
|
* <li> {@link #EXPORT_ROWS}
|
|
* <li> {@link #EXPORT_DOT_STATES}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportTransToFile(Model model, boolean ordered, int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
loadBuiltModel(model);
|
|
exportTransToFile(ordered, exportType, file);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load a (built) model and export its state rewards to a file
|
|
* @param model The model
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* <li> {@link #EXPORT_MRMC}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportStateRewardsToFile(Model model, int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
loadBuiltModel(model);
|
|
exportStateRewardsToFile(exportType, file);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load a (built) model and export its transition rewards to a file
|
|
* @param model The model
|
|
* @param ordered Ensure that (source) states are in ascending order?
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* <li> {@link #EXPORT_MRMC}
|
|
* <li> {@link #EXPORT_ROWS}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportTransRewardsToFile(Model model, boolean ordered, int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
loadBuiltModel(model);
|
|
exportTransRewardsToFile(ordered, exportType, file);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load a (built) model and export its bottom strongly connected components (BSCCs) to a file
|
|
* @param model The model
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportBSCCsToFile(Model model, int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
loadBuiltModel(model);
|
|
exportBSCCsToFile(exportType, file);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load a (built) model and export the states satisfying labels from it and a properties file to a file
|
|
* The PropertiesFile should correspond to the model.
|
|
* @param model The model
|
|
* @param modulesFile The corresponding (parsed) PRISM model (for the labels)
|
|
* @param propertiesFile The properties file (for further labels)
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportLabelsToFile(Model model, ModulesFile modulesFile, PropertiesFile propertiesFile, int exportType, File file)
|
|
throws FileNotFoundException, PrismException
|
|
{
|
|
loadPRISMModelAndBuiltModel(modulesFile, model);
|
|
exportLabelsToFile(propertiesFile, exportType, file);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load a (built) model and export its states to a file
|
|
* @param model The model
|
|
* @param exportType Type of export; one of: <ul>
|
|
* <li> {@link #EXPORT_PLAIN}
|
|
* <li> {@link #EXPORT_MATLAB}
|
|
* </ul>
|
|
* @param file File to export to (if null, print to the log instead)
|
|
*/
|
|
public void exportStatesToFile(Model model, int exportType, File file) throws FileNotFoundException, PrismException
|
|
{
|
|
loadBuiltModel(model);
|
|
exportStateRewardsToFile(exportType, file);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load a (built) model, perform model checking of a property on it and return result.
|
|
* @param model The model to check
|
|
* @param propertiesFile Parent property file of property (for labels/constants/...)
|
|
* @param expr The property to check
|
|
*/
|
|
public Result modelCheck(Model model, PropertiesFile propertiesFile, Expression expr) throws PrismException, PrismLangException
|
|
{
|
|
loadBuiltModel(model);
|
|
return modelCheck(propertiesFile, expr);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load a PRISM PTA model, perform model checking of a property on it and return result.
|
|
* @param modulesFile The corresponding (parsed) PRISM model (for the labels)
|
|
* @param propertiesFile Parent property file of property (for labels/constants/...)
|
|
* @param expr The property to check
|
|
*/
|
|
public Result modelCheckPTA(ModulesFile modulesFile, PropertiesFile propertiesFile, Expression expr) throws PrismException, PrismLangException
|
|
{
|
|
loadPRISMModel(modulesFile);
|
|
return modelCheckPTA(propertiesFile, expr, null);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
*/
|
|
public Result modelCheckSimulator(ModulesFile modulesFile, PropertiesFile propertiesFile, Expression expr, State initialState, long maxPathLength,
|
|
SimulationMethod simMethod) throws PrismException
|
|
{
|
|
loadPRISMModel(modulesFile);
|
|
return modelCheckSimulator(propertiesFile, expr, null, initialState, maxPathLength, simMethod);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
*/
|
|
public Result[] modelCheckSimulatorSimultaneously(ModulesFile modulesFile, PropertiesFile propertiesFile, List<Expression> exprs, State initialState,
|
|
long maxPathLength, SimulationMethod simMethod) throws PrismException
|
|
{
|
|
loadPRISMModel(modulesFile);
|
|
return modelCheckSimulatorSimultaneously(propertiesFile, exprs, null, initialState, maxPathLength, simMethod);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
*/
|
|
public void modelCheckSimulatorExperiment(ModulesFile modulesFile, PropertiesFile propertiesFile, UndefinedConstants undefinedConstants,
|
|
ResultsCollection results, Expression propertyToCheck, State initialState, long maxPathLength, SimulationMethod simMethod) throws PrismException,
|
|
InterruptedException
|
|
{
|
|
loadPRISMModel(modulesFile);
|
|
modelCheckSimulatorExperiment(propertiesFile, undefinedConstants, results, propertyToCheck, initialState, maxPathLength, simMethod);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load (built) model and compute steady-state probabilities (DTMCs/CTMCs only).
|
|
* Output probability distribution to log.
|
|
*/
|
|
public void doSteadyState(Model model) throws PrismException
|
|
{
|
|
doSteadyState(model, EXPORT_PLAIN, null);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load (built) model and compute steady-state probabilities (DTMCs/CTMCs only).
|
|
* Output probability distribution to a file (or, if file is null, to log).
|
|
* The exportType should be EXPORT_PLAIN or EXPORT_MATLAB.
|
|
*/
|
|
public void doSteadyState(Model model, int exportType, File file) throws PrismException
|
|
{
|
|
loadBuiltModel(model);
|
|
doSteadyState(exportType, file, null);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load (built) model and compute transient probabilities (DTMCs/CTMCs only).
|
|
* Output probability distribution to log.
|
|
*/
|
|
public void doTransient(Model model, double time) throws PrismException
|
|
{
|
|
doTransient(model, time, EXPORT_PLAIN, null, null);
|
|
}
|
|
|
|
/**
|
|
* Old API:
|
|
* Load (built) model and compute transient probabilities (DTMCs/CTMCs only).
|
|
* Output probability distribution to a file (or, if file is null, to log).
|
|
* The exportType should be EXPORT_PLAIN or EXPORT_MATLAB.
|
|
* Optionally (if non-null), read in the initial probability distribution from a file.
|
|
*/
|
|
public void doTransient(Model model, double time, int exportType, File file, File fileIn) throws PrismException
|
|
{
|
|
loadBuiltModel(model);
|
|
doTransient(time, exportType, file, fileIn);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|