Browse Source
Create ModelGenerator class for a ModulesFile object. Base code on existing stuff in SimulatorEngine, but do not remove anything from there.
Create ModelGenerator class for a ModulesFile object. Base code on existing stuff in SimulatorEngine, but do not remove anything from there.
git-svn-id: https://www.prismmodelchecker.org/svn/prism/prism/trunk@10973 bbc10eb1-c90d-0410-af57-cb519fbb1720master
1 changed files with 330 additions and 0 deletions
@ -0,0 +1,330 @@ |
|||||
|
package simulator; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
import parser.State; |
||||
|
import parser.Values; |
||||
|
import parser.VarList; |
||||
|
import parser.ast.Expression; |
||||
|
import parser.ast.LabelList; |
||||
|
import parser.ast.ModulesFile; |
||||
|
import parser.ast.RewardStruct; |
||||
|
import prism.DefaultModelGenerator; |
||||
|
import prism.ModelType; |
||||
|
import prism.PrismComponent; |
||||
|
import prism.PrismException; |
||||
|
import prism.PrismLangException; |
||||
|
|
||||
|
public class ModulesFileModelGenerator extends DefaultModelGenerator |
||||
|
{ |
||||
|
// Parent PrismComponent (logs, settings etc.) |
||||
|
protected PrismComponent parent; |
||||
|
|
||||
|
// PRISM model info |
||||
|
private ModulesFile modulesFile; |
||||
|
private ModelType modelType; |
||||
|
private Values mfConstants; |
||||
|
private VarList varList; |
||||
|
private LabelList labelList; |
||||
|
|
||||
|
// Model exploration info |
||||
|
|
||||
|
// State currently being explored |
||||
|
private State exploreState; |
||||
|
// Updater object for model |
||||
|
protected Updater updater; |
||||
|
// List of currently available transitions |
||||
|
protected TransitionList transitionList; |
||||
|
// Has the transition list been built? |
||||
|
protected boolean transitionListBuilt; |
||||
|
|
||||
|
/** |
||||
|
* Build a ModulesFileModelGenerator for a particular PRISM model, represented by a ModuleFile instance. |
||||
|
* @param modulesFile The PRISM model |
||||
|
*/ |
||||
|
public ModulesFileModelGenerator(ModulesFile modulesFile) throws PrismException |
||||
|
{ |
||||
|
this(modulesFile, null); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Build a ModulesFileModelGenerator for a particular PRISM model, represented by a ModuleFile instance. |
||||
|
* @param modulesFile The PRISM model |
||||
|
*/ |
||||
|
public ModulesFileModelGenerator(ModulesFile modulesFile, PrismComponent parent) throws PrismException |
||||
|
{ |
||||
|
this.parent = parent; |
||||
|
|
||||
|
// No support for PTAs yet |
||||
|
if (modulesFile.getModelType() == ModelType.PTA) { |
||||
|
throw new PrismException("Sorry - the simulator does not currently support PTAs"); |
||||
|
} |
||||
|
// No support for system...endsystem yet |
||||
|
if (modulesFile.getSystemDefn() != null) { |
||||
|
throw new PrismException("Sorry - the simulator does not currently handle the system...endsystem construct"); |
||||
|
} |
||||
|
|
||||
|
// Store basic model info |
||||
|
this.modulesFile = modulesFile; |
||||
|
modelType = modulesFile.getModelType(); |
||||
|
|
||||
|
// If there are no constants to define, go ahead and initialise; |
||||
|
// Otherwise, setSomeUndefinedConstants needs to be called when the values are available |
||||
|
mfConstants = modulesFile.getConstantValues(); |
||||
|
if (mfConstants != null) { |
||||
|
initialise(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Initialise the class ready for model exploration |
||||
|
* (can only be done once any constants needed have been provided) |
||||
|
*/ |
||||
|
private void initialise() throws PrismLangException |
||||
|
{ |
||||
|
// Get info |
||||
|
varList = modulesFile.createVarList(); |
||||
|
labelList = modulesFile.getLabelList(); |
||||
|
|
||||
|
// Evaluate constants and optimise (a copy of) the model for analysis |
||||
|
modulesFile = (ModulesFile) modulesFile.deepCopy().replaceConstants(mfConstants).simplify(); |
||||
|
|
||||
|
// Create data structures for exploring model |
||||
|
updater = new Updater(modulesFile, varList, parent); |
||||
|
transitionList = new TransitionList(); |
||||
|
transitionListBuilt = false; |
||||
|
} |
||||
|
|
||||
|
// Model info |
||||
|
|
||||
|
@Override |
||||
|
public ModelType getModelType() |
||||
|
{ |
||||
|
return modelType; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean containsUnboundedVariables() |
||||
|
{ |
||||
|
return modulesFile.containsUnboundedVariables(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void setSomeUndefinedConstants(Values someValues) throws PrismException |
||||
|
{ |
||||
|
modulesFile.setSomeUndefinedConstants(someValues); |
||||
|
mfConstants = modulesFile.getConstantValues(); |
||||
|
initialise(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Values getConstantValues() |
||||
|
{ |
||||
|
return mfConstants; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int getNumLabels() |
||||
|
{ |
||||
|
return labelList.size(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getLabelName(int i) throws PrismException |
||||
|
{ |
||||
|
return labelList.getLabelName(i); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int getLabelIndex(String label) |
||||
|
{ |
||||
|
return labelList.getLabelIndex(label); |
||||
|
} |
||||
|
|
||||
|
//@Override |
||||
|
public VarList getVarList() |
||||
|
{ |
||||
|
return varList; |
||||
|
} |
||||
|
|
||||
|
//@Override |
||||
|
public int getNumRewardStructs() |
||||
|
{ |
||||
|
return modulesFile.getNumRewardStructs(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean hasSingleInitialState() throws PrismException |
||||
|
{ |
||||
|
return modulesFile.getInitialStates() == null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public State getInitialState() throws PrismException |
||||
|
{ |
||||
|
if (modulesFile.getInitialStates() == null) { |
||||
|
return modulesFile.getDefaultInitialState(); |
||||
|
} else { |
||||
|
// Inefficient but probably won't be called |
||||
|
return getInitialStates().get(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<State> getInitialStates() throws PrismException |
||||
|
{ |
||||
|
List<State> initStates = new ArrayList<State>(); |
||||
|
// Easy (normal) case: just one initial state |
||||
|
if (modulesFile.getInitialStates() == null) { |
||||
|
State state = modulesFile.getDefaultInitialState(); |
||||
|
initStates.add(state); |
||||
|
} |
||||
|
// Otherwise, there may be multiple initial states |
||||
|
// For now, we handle this is in a very inefficient way |
||||
|
else { |
||||
|
Expression init = modulesFile.getInitialStates(); |
||||
|
List<State> allPossStates = varList.getAllStates(); |
||||
|
for (State possState : allPossStates) { |
||||
|
if (init.evaluateBoolean(modulesFile.getConstantValues(), possState)) { |
||||
|
initStates.add(possState); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return initStates; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void exploreState(State exploreState) throws PrismException |
||||
|
{ |
||||
|
this.exploreState = exploreState; |
||||
|
transitionListBuilt = false; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public State getExploreState() |
||||
|
{ |
||||
|
return exploreState; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int getNumChoices() throws PrismException |
||||
|
{ |
||||
|
return getTransitionList().getNumChoices(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int getNumTransitions() throws PrismException |
||||
|
{ |
||||
|
return getTransitionList().getNumTransitions(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int getNumTransitions(int index) throws PrismException |
||||
|
{ |
||||
|
return getTransitionList().getChoice(index).size(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getTransitionAction(int index, int offset) throws PrismException |
||||
|
{ |
||||
|
TransitionList transitions = getTransitionList(); |
||||
|
int a = transitions.getTransitionModuleOrActionIndex(transitions.getTotalIndexOfTransition(index, offset)); |
||||
|
return a < 0 ? null : modulesFile.getSynch(a - 1); |
||||
|
} |
||||
|
|
||||
|
//@Override |
||||
|
public String getTransitionAction(int index) throws PrismException |
||||
|
{ |
||||
|
int a = getTransitionList().getTransitionModuleOrActionIndex(index); |
||||
|
return a < 0 ? null : modulesFile.getSynch(a - 1); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public double getTransitionProbability(int index, int offset) throws PrismException |
||||
|
{ |
||||
|
TransitionList transitions = getTransitionList(); |
||||
|
return transitions.getChoice(index).getProbability(offset); |
||||
|
} |
||||
|
|
||||
|
//@Override |
||||
|
public double getTransitionProbability(int index) throws PrismException |
||||
|
{ |
||||
|
TransitionList transitions = getTransitionList(); |
||||
|
return transitions.getTransitionProbability(index); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public State computeTransitionTarget(int index, int offset) throws PrismException |
||||
|
{ |
||||
|
return getTransitionList().getChoice(index).computeTarget(offset, exploreState); |
||||
|
} |
||||
|
|
||||
|
//@Override |
||||
|
public State computeTransitionTarget(int index) throws PrismException |
||||
|
{ |
||||
|
return getTransitionList().computeTransitionTarget(index, exploreState); |
||||
|
} |
||||
|
|
||||
|
//@Override |
||||
|
public void calculateStateRewards(State state, double[] store) throws PrismLangException |
||||
|
{ |
||||
|
updater.calculateStateRewards(state, store); |
||||
|
} |
||||
|
|
||||
|
//@Override |
||||
|
public void getRandomInitialState(RandomNumberGenerator rng, State initialState) throws PrismException |
||||
|
{ |
||||
|
if (modulesFile.getInitialStates() == null) { |
||||
|
initialState.copy(modulesFile.getDefaultInitialState()); |
||||
|
} else { |
||||
|
throw new PrismException("Random choice of multiple initial states not yet supported"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean isLabelTrue(int i) throws PrismException |
||||
|
{ |
||||
|
Expression expr = labelList.getLabel(i); |
||||
|
return expr.evaluateBoolean(exploreState); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public double getStateReward(int index, State state) throws PrismException |
||||
|
{ |
||||
|
RewardStruct rewStr = modulesFile.getRewardStruct(index); |
||||
|
int n = rewStr.getNumItems(); |
||||
|
double d = 0; |
||||
|
for (int i = 0; i < n; i++) { |
||||
|
Expression guard = rewStr.getStates(i); |
||||
|
if (guard.evaluateBoolean(modulesFile.getConstantValues(), state)) { |
||||
|
double rew = rewStr.getReward(i).evaluateDouble(modulesFile.getConstantValues(), state); |
||||
|
if (Double.isNaN(rew)) |
||||
|
throw new PrismLangException("Reward structure evaluates to NaN at state " + state, rewStr.getReward(i)); |
||||
|
d += rew; |
||||
|
} |
||||
|
} |
||||
|
return d; |
||||
|
} |
||||
|
|
||||
|
// Local utility methods |
||||
|
|
||||
|
/** |
||||
|
* Returns the current list of available transitions, generating it first if this has not yet been done. |
||||
|
*/ |
||||
|
private TransitionList getTransitionList() throws PrismException |
||||
|
{ |
||||
|
// Compute the current transition list, if required |
||||
|
if (!transitionListBuilt) { |
||||
|
updater.calculateTransitions(exploreState, transitionList); |
||||
|
transitionListBuilt = true; |
||||
|
} |
||||
|
return transitionList; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public VarList createVarList() |
||||
|
{ |
||||
|
return varList; |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue