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.
307 lines
10 KiB
307 lines
10 KiB
//==============================================================================
|
|
//
|
|
// Copyright (c) 2002-
|
|
// Authors:
|
|
// * Dave Parker <david.parker@comlab.ox.ac.uk> (University of Oxford)
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// 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 explicit;
|
|
|
|
import java.util.*;
|
|
import java.io.*;
|
|
|
|
import parser.ast.*;
|
|
import prism.*;
|
|
import parser.*; // Override some imports for which there are name clashes
|
|
import simulator.SimulatorEngine;
|
|
import explicit.Model;
|
|
import explicit.StateModelChecker;
|
|
|
|
/**
|
|
* This class connects PRISM to the various bits of explicit-state functionality that are implemented.
|
|
* The intention is to minimise dependencies on the Prism class by anything in this package.
|
|
* This makes these classes easier to use independently.
|
|
*/
|
|
public class PrismExplicit
|
|
{
|
|
// Parent Prism object
|
|
private PrismLog mainLog = null;
|
|
private PrismSettings settings = null;
|
|
// Model checker(s)
|
|
private StateModelChecker mc = null;
|
|
|
|
public PrismExplicit(PrismLog mainLog, PrismSettings settings)
|
|
{
|
|
this.mainLog = mainLog;
|
|
this.settings = settings;
|
|
}
|
|
|
|
/**
|
|
* Build a model from a PRISM modelling language description, storing it explicitly.,
|
|
* It is assumed that all constants in the model file have been defined by now.
|
|
* @param modulesFile Model to build
|
|
* @param simEngine PRISM simulator engine (for model exploration)
|
|
*/
|
|
public Model buildModel(ModulesFile modulesFile, SimulatorEngine simEngine) throws PrismException
|
|
{
|
|
long l; // timer
|
|
Model modelExpl;
|
|
ConstructModel constructModel;
|
|
|
|
if (modulesFile.getModelType() == ModelType.PTA) {
|
|
throw new PrismException("You cannot build a PTA model explicitly, only perform model checking");
|
|
}
|
|
|
|
mainLog.print("\nBuilding model...\n");
|
|
|
|
// create translator
|
|
constructModel = new ConstructModel(simEngine, mainLog);
|
|
|
|
// build model
|
|
l = System.currentTimeMillis();
|
|
modelExpl = constructModel.constructModel(modulesFile, false, true);
|
|
l = System.currentTimeMillis() - l;
|
|
|
|
mainLog.println("\nTime for model construction: " + l / 1000.0 + " seconds.");
|
|
|
|
return modelExpl;
|
|
}
|
|
|
|
/**
|
|
* Perform model checking of a property on a model and return result.
|
|
* @param model The model
|
|
* @param modulesFile Original model file (for rewards/...) (optional; null if not needed)
|
|
* @param propertiesFile Parent property file of property (for labels/constants/...) (optional; null if not needed)
|
|
* @param expr The property
|
|
*/
|
|
public Result modelCheck(Model model, ModulesFile modulesFile, PropertiesFile propertiesFile, Expression expr) throws PrismException, PrismLangException
|
|
{
|
|
Result result = null;
|
|
String s;
|
|
|
|
// Check that property is valid for this model type
|
|
// and create new model checker object
|
|
expr.checkValid(model.getModelType());
|
|
switch (model.getModelType()) {
|
|
case DTMC:
|
|
mc = new DTMCModelChecker();
|
|
break;
|
|
case MDP:
|
|
mc = new MDPModelChecker();
|
|
break;
|
|
case CTMC:
|
|
mc = new CTMCModelChecker();
|
|
break;
|
|
case CTMDP:
|
|
mc = new CTMDPModelChecker();
|
|
break;
|
|
case STPG:
|
|
mc = new STPGModelChecker();
|
|
break;
|
|
default:
|
|
throw new PrismException("Unknown model type " + model.getModelType());
|
|
}
|
|
|
|
mc.setLog(mainLog);
|
|
mc.setSettings(settings);
|
|
|
|
mc.setModulesFile(modulesFile);
|
|
mc.setPropertiesFile(propertiesFile);
|
|
|
|
mc.setPrecomp(settings.getBoolean(PrismSettings.PRISM_PRECOMPUTATION));
|
|
s = settings.getString(PrismSettings.PRISM_TERM_CRIT);
|
|
if (s.equals("Absolute")) {
|
|
mc.setTermCrit(StateModelChecker.TermCrit.ABSOLUTE);
|
|
} else if (s.equals("Relative")) {
|
|
mc.setTermCrit(StateModelChecker.TermCrit.RELATIVE);
|
|
}
|
|
mc.setTermCritParam(settings.getDouble(PrismSettings.PRISM_TERM_CRIT_PARAM));
|
|
mc.setMaxIters(settings.getInteger(PrismSettings.PRISM_MAX_ITERS));
|
|
switch (model.getModelType()) {
|
|
case DTMC:
|
|
case CTMC:
|
|
s = settings.getString(PrismSettings.PRISM_LIN_EQ_METHOD);
|
|
if (s.equals("Gauss-Seidel")) {
|
|
mc.setSolnMethod(StateModelChecker.SolnMethod.GAUSS_SEIDEL);
|
|
} else {
|
|
mc.setSolnMethod(StateModelChecker.SolnMethod.VALUE_ITERATION);
|
|
}
|
|
break;
|
|
case MDP:
|
|
s = settings.getString(PrismSettings.PRISM_MDP_SOLN_METHOD);
|
|
if (s.equals("Gauss-Seidel")) {
|
|
mc.setSolnMethod(StateModelChecker.SolnMethod.GAUSS_SEIDEL);
|
|
} else if (s.equals("Policy iteration")) {
|
|
mc.setSolnMethod(StateModelChecker.SolnMethod.POLICY_ITERATION);
|
|
} else if (s.equals("Modified policy iteration")) {
|
|
mc.setSolnMethod(StateModelChecker.SolnMethod.MODIFIED_POLICY_ITERATION);
|
|
} else {
|
|
mc.setSolnMethod(StateModelChecker.SolnMethod.VALUE_ITERATION);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// TODO: pass PRISM settings to mc
|
|
|
|
// Do model checking
|
|
result = mc.check(model, expr);
|
|
|
|
// Return result
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Compute transient probabilities (for a DTMC or CTMC).
|
|
* Output probability distribution to log.
|
|
*/
|
|
public void doTransient(Model model, double time) throws PrismException
|
|
{
|
|
doTransient(model, time, Prism.EXPORT_PLAIN, null, null);
|
|
}
|
|
|
|
/**
|
|
* Compute transient probabilities (for a DTMC or CTMC).
|
|
* 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 fileOut, File fileIn) throws PrismException
|
|
{
|
|
long l = 0; // timer
|
|
StateValues probs = null;
|
|
PrismLog tmpLog;
|
|
|
|
if (time < 0) throw new PrismException("Cannot compute transient probabilities for negative time value");
|
|
|
|
// no specific states format for MRMC
|
|
if (exportType == Prism.EXPORT_MRMC) exportType = Prism.EXPORT_PLAIN;
|
|
// rows format does not apply to states output
|
|
if (exportType == Prism.EXPORT_ROWS) exportType = Prism.EXPORT_PLAIN;
|
|
|
|
l = System.currentTimeMillis();
|
|
|
|
if (model.getModelType() == ModelType.DTMC) {
|
|
throw new PrismException("Not implemented yet"); // TODO
|
|
}
|
|
else if (model.getModelType() == ModelType.CTMC) {
|
|
mainLog.println("\nComputing transient probabilities (time = " + time + ")...");
|
|
CTMCModelChecker mcCTMC = new CTMCModelChecker();
|
|
// TODO: pass settings
|
|
probs = mcCTMC.doTransient((CTMC) model, time, null);
|
|
}
|
|
else {
|
|
throw new PrismException("Transient probabilities only computed for DTMCs/CTMCs");
|
|
}
|
|
|
|
l = System.currentTimeMillis() - l;
|
|
|
|
// print message
|
|
mainLog.print("\nPrinting transient probabilities ");
|
|
switch (exportType) {
|
|
case Prism.EXPORT_PLAIN: mainLog.print("in plain text format "); break;
|
|
case Prism.EXPORT_MATLAB: mainLog.print("in Matlab format "); break;
|
|
}
|
|
if (fileOut != null) mainLog.println("to file \"" + fileOut + "\"..."); else mainLog.println("below:");
|
|
|
|
// create new file log or use main log
|
|
if (fileOut != null) {
|
|
tmpLog = new PrismFileLog(fileOut.getPath());
|
|
if (!tmpLog.ready()) {
|
|
throw new PrismException("Could not open file \"" + fileOut + "\" for output");
|
|
}
|
|
} else {
|
|
tmpLog = mainLog;
|
|
}
|
|
|
|
// print out or export probabilities
|
|
probs.print(tmpLog, fileOut == null, exportType == Prism.EXPORT_MATLAB, fileOut == null);
|
|
|
|
// print out computation time
|
|
mainLog.println("\nTime for transient probability computation: " + l/1000.0 + " seconds.");
|
|
|
|
// tidy up
|
|
probs.clear();
|
|
if (fileOut != null) tmpLog.close();
|
|
}
|
|
|
|
/**
|
|
* Simple test program.
|
|
*/
|
|
public static void main(String args[])
|
|
{
|
|
modelCheckFromPrismFile(args);
|
|
//modelCheckViaExplicitFiles(args);
|
|
}
|
|
|
|
/**
|
|
* Simple test program.
|
|
*/
|
|
private static void modelCheckFromPrismFile(String args[])
|
|
{
|
|
Prism prism;
|
|
try {
|
|
PrismLog mainLog = new PrismFileLog("stdout");
|
|
prism = new Prism(mainLog, mainLog);
|
|
//prism.initialise();
|
|
ModulesFile modulesFile = prism.parseModelFile(new File(args[0]));
|
|
modulesFile.setUndefinedConstants(null);
|
|
PropertiesFile propertiesFile = prism.parsePropertiesFile(modulesFile, new File(args[1]));
|
|
propertiesFile.setUndefinedConstants(null);
|
|
PrismExplicit pe = new PrismExplicit(prism.getMainLog(), prism.getSettings());
|
|
Model modelExpl = pe.buildModel(modulesFile, prism.getSimulator());
|
|
pe.modelCheck(modelExpl, modulesFile, propertiesFile, propertiesFile.getProperty(0));
|
|
} catch (PrismException e) {
|
|
System.out.println(e);
|
|
} catch (FileNotFoundException e) {
|
|
System.out.println(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Simple test program.
|
|
*/
|
|
private static void modelCheckViaExplicitFiles(String args[])
|
|
{
|
|
Prism prism;
|
|
try {
|
|
PrismLog log = new PrismFileLog("stdout");
|
|
prism = new Prism(log, log);
|
|
prism.initialise();
|
|
prism.setDoProbChecks(false);
|
|
ModulesFile modulesFile = prism.parseModelFile(new File(args[0]));
|
|
modulesFile.setUndefinedConstants(null);
|
|
PropertiesFile propertiesFile = prism.parsePropertiesFile(modulesFile, new File(args[1]));
|
|
propertiesFile.setUndefinedConstants(null);
|
|
prism.Model model = prism.buildModel(modulesFile);
|
|
prism.exportTransToFile(model, true, Prism.EXPORT_PLAIN, new File("tmp.tra"));
|
|
prism.exportLabelsToFile(model, modulesFile, null, Prism.EXPORT_PLAIN, new File("tmp.lab"));
|
|
DTMCSimple modelExplicit = new DTMCSimple();
|
|
modelExplicit.buildFromPrismExplicit("tmp.tra");
|
|
PrismExplicit pe = new PrismExplicit(prism.getMainLog(), prism.getSettings());
|
|
pe.modelCheck(modelExplicit, null, propertiesFile, propertiesFile.getProperty(0));
|
|
} catch (PrismException e) {
|
|
System.out.println(e);
|
|
} catch (FileNotFoundException e) {
|
|
System.out.println(e);
|
|
}
|
|
}
|
|
}
|