//============================================================================== // // Copyright (c) 2002- // Authors: // * Dave Parker (University of Birmingham/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 simulator; import parser.State; import parser.ast.ModulesFile; import prism.PrismLog; /** * Class to display a simulation path in text form, sending to a PrismLog. */ public class PathToText extends PathDisplayer { /** Log to display path to */ private PrismLog log; // Model info private ModulesFile modulesFile; private int numVars; private int numRewardStructs; private boolean contTime; // Config private boolean showTimeCumul = true; private boolean showTimeSpent = false; private String colSep = " "; // Displayer state /** Is the next column the first? */ private boolean firstCol; /** Last state */ private State lastState; /** Last state rewards */ private double[] lastStateRewards; /** Did the displayed info change in the current step? */ private boolean changed; /** * Construct a {@link PathToText} object * @param log Log to output path to * @param modulesFile Model associated with path */ public PathToText(PrismLog log, ModulesFile modulesFile) { this.log = log; this.modulesFile = modulesFile; // Get model info numVars = modulesFile.getNumVars(); numRewardStructs = modulesFile.getNumRewardStructs(); contTime = modulesFile.getModelType().continuousTime(); } // Setters /** * Set whether we show cumulative time (for continuous models only) */ public void setShowTimeCumul(boolean showTimeCumul) { this.showTimeCumul = showTimeCumul; } /** * Set whether we show time spent in each state (for continuous models only) */ public void setShowTimeSpent(boolean showTimeSpent) { this.showTimeSpent = showTimeSpent; } /** * Set the column separator for the table of path contents */ public void setColSep(String colSep) { this.colSep = colSep; } // Display methods @Override public void startDisplay(State initialState, double[] initialStateRewards) { int j; // Display header firstCol = true; if (!getShowSnapshots()) { log.print(getColSep() + "action"); if (showProbs) log.print(getColSep() + "probability"); } log.print(getColSep() + "step"); if (contTime && showTimeCumul) log.print(getColSep() + "time"); if (varsToShow == null) for (j = 0; j < numVars; j++) log.print(getColSep() + modulesFile.getVarName(j)); else for (int v : varsToShow) log.print(getColSep() + modulesFile.getVarName(v)); if (getShowRewards()) { if (numRewardStructs == 1) { log.print(getColSep() + "state_reward"); if (!getShowSnapshots()) log.print(getColSep() + "transition_reward"); } else { for (j = 0; j < numRewardStructs; j++) { log.print(getColSep() + "state_reward" + (j + 1)); if (!getShowSnapshots()) log.print(getColSep() + "transition_reward" + (j + 1)); } } } if (!getShowSnapshots()) { if (contTime && showTimeSpent) log.print(getColSep() + "time_in_state"); } log.println(); // Display initial step changed = true; firstCol = true; if (!getShowSnapshots()) { log.print(getColSep() + "-"); if (showProbs) log.print(getColSep() + "-"); } log.print(getColSep() + "0"); if (contTime && showTimeCumul) log.print(getColSep() + "0.0"); lastState = new State(initialState.varValues.length); displayState(initialState); if (getShowRewards()) { lastStateRewards = explicit.Utils.cloneDoubleArray(initialStateRewards); } if (getShowSnapshots()) { log.println(); } } @Override public void displayStep(double timeSpent, double timeCumul, Object action, double probability, double[] transitionRewards, int newStateIndex, State newState, double[] newStateRewards) { if (!showChangesOnly || changed) { // display rewards for last state if (getShowRewards()) { for (int j = 0; j < numRewardStructs; j++) { log.print(getColSep() + lastStateRewards[j]); log.print(getColSep() + transitionRewards[j]); } } // display time spent in state if (contTime && showTimeSpent) log.print(getColSep() + timeSpent); log.println(); } // if required, check whether the info to be displayed changed if (showChangesOnly) { changed = stateChanged(lastState, newState) || rewardsChanged(lastStateRewards, newStateRewards); if (!changed) return; } firstCol = true; // display action log.print(getColSep() + action); // display probability/rate if (showProbs) log.print(getColSep() + probability); // display state index log.print(getColSep() + newStateIndex); // display cumulative time if (contTime && showTimeCumul) log.print(getColSep() + timeCumul); // display state displayState(newState); // store state rewards if (getShowRewards()) { explicit.Utils.copyDoubleArray(newStateRewards, lastStateRewards); } } @Override public void displaySnapshot(double timeCumul, int newStateIndex, State newState, double[] newStateRewards) { firstCol = true; // display state index log.print(getColSep() + newStateIndex); // display cumulative time if (contTime && showTimeCumul) log.print(getColSep() + timeCumul); // display state displayState(newState); // display state rewards if (getShowRewards()) { for (int j = 0; j < numRewardStructs; j++) { log.print(getColSep() + newStateRewards[j]); } } log.println(); } private void displayState(State state) { int j; if (varsToShow == null) { for (j = 0; j < numVars; j++) { log.print(getColSep()); log.print(state.varValues[j]); } } else { for (int v : varsToShow) { log.print(getColSep()); log.print(state.varValues[v]); } } lastState.copy(state); } private String getColSep() { if (firstCol) { firstCol = false; return ""; } else { return colSep; } } private boolean stateChanged(State lastState, State newState) { if (varsToShow == null) { for (int j = 0; j < numVars; j++) { if (!newState.varValues[j].equals(lastState.varValues[j])) { return true; } } } else { for (int v : varsToShow) { if (!newState.varValues[v].equals(lastState.varValues[v])) { return true; } } } return false; } private boolean rewardsChanged(double[] lastStateRewards, double[] newStateRewards) { if (!showRewards) return false; for (int j = 0; j < numRewardStructs; j++) { if (newStateRewards[j] != lastStateRewards[j]) { return true; } } return false; } @Override public void endDisplay() { if (!getShowSnapshots() && (!showChangesOnly || changed)) { // display state rewards for last state // (transition rewards unknown because no outgoing transition) if (getShowRewards()) { for (int j = 0; j < numRewardStructs; j++) { log.print(getColSep() + lastStateRewards[j]); log.print(getColSep() + "?"); } } // display (zero) time spent in state if (contTime && showTimeSpent) log.print(getColSep() + 0.0); log.println(); } } }