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.
391 lines
12 KiB
391 lines
12 KiB
//==============================================================================
|
|
//
|
|
// Copyright (c) 2002-
|
|
// Authors:
|
|
// * Andrew Hinton <ug60axh@cs.bham.ac.uk> (University of Birmingham)
|
|
// * Dave Parker <david.parker@comlab.ox.ac.uk> (University of Oxford, formerly University of Birmingham)
|
|
// * Vojtech Forejt <vojtech.forejt@cs.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 userinterface.properties;
|
|
|
|
import parser.*;
|
|
import parser.ast.*;
|
|
import parser.type.*;
|
|
import prism.*;
|
|
import userinterface.*;
|
|
|
|
import javax.swing.*;
|
|
import java.util.*;
|
|
import userinterface.util.*;
|
|
|
|
public class GUIExperiment
|
|
{
|
|
private GUIMultiProperties guiProp;
|
|
private GUIExperimentTable table;
|
|
private prism.ResultsCollection results;
|
|
private boolean finished = false;
|
|
|
|
private UndefinedConstants cons;
|
|
private PropertiesFile prop; //contains 1 property only
|
|
|
|
private boolean running = false;
|
|
|
|
private Thread theThread;
|
|
|
|
private boolean useSimulation;
|
|
|
|
private Values definedMFConstants;
|
|
private Values definedPFConstants;
|
|
private Result res;
|
|
|
|
/** Creates a new instance of GUIExperiment */
|
|
public GUIExperiment(GUIExperimentTable table, GUIMultiProperties guiProp, PropertiesFile prop, UndefinedConstants cons, boolean useSimulation)
|
|
{
|
|
this.table = table;
|
|
this.guiProp = guiProp;
|
|
this.prop = prop;
|
|
this.cons = cons;
|
|
this.useSimulation = useSimulation;
|
|
|
|
results = new prism.ResultsCollection(cons, prop.getProperty(0).getResultName());
|
|
}
|
|
|
|
//ACCESS METHODS
|
|
|
|
public int getTotalIterations()
|
|
{
|
|
return cons.getNumIterations();
|
|
}
|
|
|
|
public int getCurrentIterations()
|
|
{
|
|
return results.getCurrentIteration();
|
|
}
|
|
|
|
public Vector<DefinedConstant> getRangingConstants()
|
|
{
|
|
return cons.getRangingConstants();
|
|
}
|
|
|
|
public String getDefinedConstantsString()
|
|
{
|
|
return cons.getDefinedConstantsString();
|
|
}
|
|
|
|
public String getPFDefinedConstantsString()
|
|
{
|
|
return cons.getPFDefinedConstantsString();
|
|
}
|
|
|
|
public String getPropertyString()
|
|
{
|
|
int i = prop.getNumProperties() - 1;
|
|
return prop.getProperty(i).toString();
|
|
}
|
|
|
|
public Type getPropertyType()
|
|
{
|
|
int i = prop.getNumProperties() - 1;
|
|
return prop.getProperty(i).getType();
|
|
}
|
|
|
|
public ResultsCollection getResults()
|
|
{
|
|
return results;
|
|
}
|
|
|
|
public boolean isFinished()
|
|
{
|
|
return finished;
|
|
}
|
|
|
|
public boolean isUseSimulation()
|
|
{
|
|
return useSimulation;
|
|
}
|
|
|
|
public GUIExperimentTable getTable()
|
|
{
|
|
return table;
|
|
}
|
|
|
|
//UPDATE METHODS
|
|
|
|
public void startExperiment()
|
|
{
|
|
theThread = new ExperimentThread(guiProp, cons, prop);
|
|
running = true;
|
|
theThread.start();
|
|
}
|
|
|
|
public synchronized void experimentDone()
|
|
{
|
|
running = false;
|
|
theThread = null;
|
|
finished = true;
|
|
this.table.repaint();
|
|
}
|
|
|
|
// note: presently, this is never actually called
|
|
// (in case of errors, these are stored as the results of the experiment and things end normally)
|
|
public synchronized void experimentFailed()
|
|
{
|
|
running = false;
|
|
theThread = null;
|
|
finished = true;
|
|
table.repaint();
|
|
}
|
|
|
|
public synchronized void experimentInterrupted()
|
|
{
|
|
running = false;
|
|
theThread = null;
|
|
finished = true;
|
|
table.repaint();
|
|
}
|
|
|
|
public synchronized void setResult(Values mfValues, Values pfValues, Result res)
|
|
{
|
|
results.setResult(mfValues, pfValues, res.getResult());
|
|
}
|
|
|
|
public synchronized void setMultipleErrors(Values mfValues, Values pfValues, Exception e)
|
|
{
|
|
results.setMultipleErrors(mfValues, pfValues, e);
|
|
}
|
|
|
|
public void stop()
|
|
{
|
|
if (running && theThread != null) {
|
|
if (useSimulation)
|
|
guiProp.getPrism().getSimulator().stopSampling();
|
|
theThread.interrupt();
|
|
}
|
|
}
|
|
|
|
//tidy up ResultsCollection when it has been removed (to tidy up graphs)
|
|
public void clear()
|
|
{
|
|
}
|
|
|
|
class ExperimentThread extends GUIComputationThread
|
|
{
|
|
private UndefinedConstants undefinedConstants;
|
|
private PropertiesFile propertiesFile;
|
|
|
|
public ExperimentThread(GUIMultiProperties guiProp, UndefinedConstants undefinedConstants, PropertiesFile propertiesFile)
|
|
{
|
|
super(guiProp);
|
|
this.undefinedConstants = undefinedConstants;
|
|
this.propertiesFile = propertiesFile;
|
|
}
|
|
|
|
public void run()
|
|
{
|
|
int i, k;
|
|
int propertyIndex = propertiesFile.getNumProperties() - 1;
|
|
Property propertyToCheck = propertiesFile.getPropertyObject(propertyIndex);
|
|
SimulationInformation info = null;
|
|
boolean reuseInfo = false, reuseInfoAsked = false;
|
|
|
|
definedMFConstants = null;
|
|
definedPFConstants = null;
|
|
res = null;
|
|
|
|
try {
|
|
SwingUtilities.invokeAndWait(new Runnable()
|
|
{
|
|
public void run()
|
|
{
|
|
guiProp.startProgress();
|
|
guiProp.setTaskBarText("Running experiment...");
|
|
guiProp.notifyEventListeners(new GUIComputationEvent(GUIComputationEvent.COMPUTATION_START, guiProp));
|
|
guiProp.notifyEventListeners(new GUIPropertiesEvent(GUIPropertiesEvent.EXPERIMENT_START));
|
|
}
|
|
});
|
|
|
|
for (i = 0; i < undefinedConstants.getNumModelIterations(); i++) {
|
|
|
|
// set values for ModulesFile constants
|
|
try {
|
|
definedMFConstants = undefinedConstants.getMFConstantValues();
|
|
prism.setPRISMModelConstants(definedMFConstants);
|
|
} catch (Exception e) {
|
|
// in case of error, report it (in log only), store as result, and go on to the next model
|
|
errorLog(e);
|
|
setMultipleErrors(definedMFConstants, null, e);
|
|
undefinedConstants.iterateModel();
|
|
continue;
|
|
}
|
|
|
|
// collect information for simulation if required
|
|
if (useSimulation && !reuseInfo) {
|
|
try {
|
|
info = null;
|
|
info = GUISimulationPicker.defineSimulationWithDialog(guiProp.getGUI(), propertyToCheck.getExpression(), prism.getPRISMModel(), "("
|
|
+ definedMFConstants + ")");
|
|
} catch (Exception e) {
|
|
// in case of error, report it (in log only), store as result, and go on to the next model
|
|
errorLog(e);
|
|
setMultipleErrors(definedMFConstants, null, e);
|
|
undefinedConstants.iterateModel();
|
|
continue;
|
|
}
|
|
|
|
// if info is null, the user clicked cancel
|
|
if (info == null)
|
|
break;
|
|
|
|
// if there are multiple models, offer the chance to reuse simulation info
|
|
if (undefinedConstants.getNumModelIterations() > 1 && !reuseInfoAsked) {
|
|
reuseInfoAsked = true;
|
|
int q = guiProp.questionYesNo("Do you want to reuse the same simulation\n"
|
|
+ "parameters for the remaining models in this experiment?\n" + "If not you will be prompted for new values for each one.");
|
|
if (q == 0)
|
|
reuseInfo = true;
|
|
}
|
|
}
|
|
|
|
// for simulation where "simultaneous property checking" is enabled...
|
|
if (useSimulation && prism.getSettings().getBoolean(PrismSettings.SIMULATOR_SIMULTANEOUS)
|
|
&& undefinedConstants.getNumPropertyIterations() > 1) {
|
|
try {
|
|
// convert initial Values -> State
|
|
// (remember: null means use default or pick randomly)
|
|
parser.State initialState;
|
|
if (info.getInitialState() == null) {
|
|
initialState = null;
|
|
} else {
|
|
initialState = new parser.State(info.getInitialState(), prism.getPRISMModel());
|
|
}
|
|
// do simulation
|
|
prism.modelCheckSimulatorExperiment(propertiesFile, undefinedConstants, results, propertyToCheck.getExpression(), initialState,
|
|
info.getMaxPathLength(), info.createSimulationMethod());
|
|
// update progress meter
|
|
// (all properties simulated simultaneously so can't get more accurate feedback at the moment anyway)
|
|
table.progressChanged();
|
|
} catch (Exception e) {
|
|
// in case of error, report it (in log only), store as result, and go on to the next model
|
|
errorLog(e);
|
|
setMultipleErrors(definedMFConstants, null, e);
|
|
undefinedConstants.iterateModel();
|
|
continue;
|
|
}
|
|
} else {
|
|
// iterate through as many properties as necessary
|
|
for (k = 0; k < undefinedConstants.getNumPropertyIterations(); k++) {
|
|
// interrupt if requested
|
|
if (interrupted())
|
|
throw new InterruptedException();
|
|
|
|
try {
|
|
// Set values for PropertiesFile constants
|
|
if (propertiesFile != null) {
|
|
definedPFConstants = undefinedConstants.getPFConstantValues();
|
|
propertiesFile.setSomeUndefinedConstants(definedPFConstants);
|
|
}
|
|
// Normal model checking
|
|
if (!useSimulation) {
|
|
res = prism.modelCheck(propertiesFile, propertyToCheck);
|
|
}
|
|
// Approximate (simulation-based) model checking
|
|
else {
|
|
// convert initial Values -> State
|
|
// (remember: null means use default or pick randomly)
|
|
parser.State initialState;
|
|
if (info.getInitialState() == null) {
|
|
initialState = null;
|
|
} else {
|
|
initialState = new parser.State(info.getInitialState(), prism.getPRISMModel());
|
|
}
|
|
// do simulation
|
|
res = prism.modelCheckSimulator(propertiesFile, propertyToCheck.getExpression(), definedPFConstants, initialState,
|
|
info.getMaxPathLength(), info.createSimulationMethod());
|
|
}
|
|
} catch (Exception e) {
|
|
// in case of error, report it (in log only), store exception as the result and proceed
|
|
errorLog(e);
|
|
res = new Result(e);
|
|
}
|
|
// store result of model checking
|
|
SwingUtilities.invokeAndWait(new Runnable()
|
|
{
|
|
public void run()
|
|
{
|
|
GUIExperiment.this.setResult(definedMFConstants, definedPFConstants, res);
|
|
}
|
|
});
|
|
|
|
table.progressChanged();
|
|
|
|
// iterate to next property
|
|
undefinedConstants.iterateProperty();
|
|
yield();
|
|
}
|
|
}
|
|
// iterate to next model
|
|
undefinedConstants.iterateModel();
|
|
yield();
|
|
}
|
|
|
|
SwingUtilities.invokeAndWait(new Runnable()
|
|
{
|
|
public void run()
|
|
{
|
|
guiProp.stopProgress();
|
|
guiProp.setTaskBarText("Running experiment... done.");
|
|
guiProp.notifyEventListeners(new GUIComputationEvent(GUIComputationEvent.COMPUTATION_DONE, guiProp));
|
|
guiProp.notifyEventListeners(new GUIPropertiesEvent(GUIPropertiesEvent.EXPERIMENT_END));
|
|
}
|
|
});
|
|
experimentDone();
|
|
|
|
if (results.containsErrors())
|
|
errorDialog("One or more errors occured during this experiment.\nSelect \"View results\" or check the log for more information");
|
|
} catch (InterruptedException e) {
|
|
try {
|
|
SwingUtilities.invokeAndWait(new Runnable()
|
|
{
|
|
public void run()
|
|
{
|
|
|
|
guiProp.stopProgress();
|
|
guiProp.setTaskBarText("Running experiment... interrupted.");
|
|
guiProp.notifyEventListeners(new GUIComputationEvent(GUIComputationEvent.COMPUTATION_DONE, guiProp));
|
|
guiProp.notifyEventListeners(new GUIPropertiesEvent(GUIPropertiesEvent.EXPERIMENT_END));
|
|
|
|
}
|
|
});
|
|
}
|
|
// catch and ignore possible exceptions from invokeAndWait call
|
|
catch (InterruptedException e2) {
|
|
} catch (java.lang.reflect.InvocationTargetException e2) {
|
|
}
|
|
experimentInterrupted();
|
|
}
|
|
// catch and ignore possible exception from invokeAndWait calls
|
|
catch (java.lang.reflect.InvocationTargetException e) {
|
|
}
|
|
}
|
|
}
|
|
}
|