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.
614 lines
17 KiB
614 lines
17 KiB
//==============================================================================
|
|
//
|
|
// Copyright (c) 2002-
|
|
// Authors:
|
|
// * Andrew Hinton <ug60axh@cs.bham.ac.uk> (University of Birmingham)
|
|
// * Mark Kattenbelt <mark.kattenbelt@comlab.ox.ac.uk> (University of Oxford, formerly University of Birmingham)
|
|
// * Dave Parker <david.parker@comlab.ox.ac.uk> (University of Oxford, formerly 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 userinterface.simulator;
|
|
|
|
import java.util.*;
|
|
import javax.swing.table.AbstractTableModel;
|
|
|
|
import simulator.PathFull;
|
|
import userinterface.simulator.SimulationView.*;
|
|
import userinterface.util.GUIGroupedTableModel;
|
|
import parser.ast.*;
|
|
|
|
public class GUISimulatorPathTableModel extends AbstractTableModel implements GUIGroupedTableModel, Observer
|
|
{
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
private GUISimulator simulator;
|
|
private SimulationView view;
|
|
|
|
private boolean pathActive;
|
|
private ModulesFile parsedModel;
|
|
private PathFull path;
|
|
|
|
private RewardStructureValue rewardStructureValue;
|
|
private VariableValue variableValue;
|
|
private TimeValue timeValue;
|
|
private ActionValue actionValue;
|
|
|
|
public GUISimulatorPathTableModel(GUISimulator simulator, SimulationView view)
|
|
{
|
|
this.simulator = simulator;
|
|
this.view = view;
|
|
this.view.addObserver(this);
|
|
|
|
rewardStructureValue = view.new RewardStructureValue(null, null);
|
|
variableValue = view.new VariableValue(null, null);
|
|
}
|
|
|
|
public void setPathActive(boolean pathActive)
|
|
{
|
|
this.pathActive = pathActive;
|
|
}
|
|
|
|
public void setPath(PathFull path)
|
|
{
|
|
this.path = path;
|
|
}
|
|
|
|
public void setParsedModel(ModulesFile parsedModel)
|
|
{
|
|
this.parsedModel = parsedModel;
|
|
}
|
|
|
|
public boolean canShowTime()
|
|
{
|
|
return parsedModel.getModelType().continuousTime();
|
|
}
|
|
|
|
public int getGroupCount()
|
|
{
|
|
if (!pathActive) {
|
|
return 0;
|
|
} else {
|
|
int groupCount = 0;
|
|
|
|
if (view.showActions() || view.showSteps()) {
|
|
groupCount++;
|
|
}
|
|
|
|
if (canShowTime() && (view.showTime() || view.showCumulativeTime())) {
|
|
groupCount++;
|
|
}
|
|
|
|
ArrayList<Variable> vars = view.getVisibleVariables();
|
|
Set<String> varNames = new HashSet<String>();
|
|
|
|
for (Variable variable : vars) {
|
|
varNames.add(variable.getName());
|
|
}
|
|
|
|
for (int g = 0; g < parsedModel.getNumGlobals(); g++) {
|
|
if (varNames.contains(parsedModel.getGlobal(g).getName())) {
|
|
groupCount++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (int m = 0; m < parsedModel.getNumModules(); m++) {
|
|
Module module = parsedModel.getModule(m);
|
|
for (int v = 0; v < module.getNumDeclarations(); v++) {
|
|
if (varNames.contains(module.getDeclaration(v).getName())) {
|
|
groupCount++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (view.getVisibleRewardColumns().size() > 0) {
|
|
groupCount++;
|
|
}
|
|
|
|
return groupCount;
|
|
}
|
|
}
|
|
|
|
public void update(Observable o, Object arg)
|
|
{
|
|
if (o == view) {
|
|
fireTableStructureChanged();
|
|
|
|
//Sort out the minimum widths for each column
|
|
simulator.sortOutColumnSizes();
|
|
}
|
|
}
|
|
|
|
public String getGroupName(int groupIndex)
|
|
{
|
|
if (!pathActive) {
|
|
return "";
|
|
} else {
|
|
int groupCount = 0;
|
|
|
|
if (view.showActions() || view.showSteps()) {
|
|
if (groupCount == groupIndex) {
|
|
return "Step";
|
|
}
|
|
|
|
groupCount++;
|
|
}
|
|
|
|
if (canShowTime() && (view.showTime() || view.showCumulativeTime())) {
|
|
if (groupCount == groupIndex) {
|
|
return "Time";
|
|
}
|
|
|
|
groupCount++;
|
|
}
|
|
|
|
if (view.getVisibleVariables().size() > 0) {
|
|
ArrayList<Variable> vars = view.getVisibleVariables();
|
|
Set<String> varNames = new HashSet<String>();
|
|
|
|
for (Variable variable : vars) {
|
|
varNames.add(variable.getName());
|
|
}
|
|
|
|
for (int g = 0; g < parsedModel.getNumGlobals(); g++) {
|
|
if (varNames.contains(parsedModel.getGlobal(g).getName())) {
|
|
if (groupCount == groupIndex) {
|
|
return "Globals";
|
|
}
|
|
|
|
groupCount++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (int m = 0; m < parsedModel.getNumModules(); m++) {
|
|
Module module = parsedModel.getModule(m);
|
|
for (int v = 0; v < module.getNumDeclarations(); v++) {
|
|
if (varNames.contains(module.getDeclaration(v).getName())) {
|
|
if (groupCount == groupIndex) {
|
|
return "" + parsedModel.getModuleName(m) + "";
|
|
}
|
|
|
|
groupCount++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add state and transitions rewards for each reward structure.
|
|
if (view.getVisibleRewardColumns().size() > 0) {
|
|
if (groupCount == groupIndex) {
|
|
return "Rewards";
|
|
}
|
|
|
|
groupCount++;
|
|
}
|
|
|
|
return "Undefined Group";
|
|
}
|
|
}
|
|
|
|
public String getGroupToolTip(int groupIndex)
|
|
{
|
|
ArrayList<Variable> vars = view.getVisibleVariables();
|
|
Set<String> varNames = new HashSet<String>();
|
|
|
|
for (Variable variable : vars) {
|
|
varNames.add(variable.getName());
|
|
}
|
|
|
|
int groupCount = 0;
|
|
|
|
if (view.showActions() || view.showSteps()) {
|
|
if (groupCount == groupIndex) {
|
|
return null;
|
|
}
|
|
|
|
groupCount++;
|
|
}
|
|
|
|
if (canShowTime() && (view.showTime() || view.showCumulativeTime())) {
|
|
if (groupCount == groupIndex) {
|
|
return null;
|
|
}
|
|
|
|
groupCount++;
|
|
}
|
|
|
|
for (int g = 0; g < parsedModel.getNumGlobals(); g++) {
|
|
if (varNames.contains(parsedModel.getGlobal(g).getName())) {
|
|
if (groupCount == groupIndex) {
|
|
return "Global variables";
|
|
}
|
|
|
|
groupCount++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (int m = 0; m < parsedModel.getNumModules(); m++) {
|
|
Module module = parsedModel.getModule(m);
|
|
for (int v = 0; v < module.getNumDeclarations(); v++) {
|
|
if (varNames.contains(module.getDeclaration(v).getName())) {
|
|
if (groupCount == groupIndex) {
|
|
return "Variables of module \"" + parsedModel.getModuleName(m) + "\"";
|
|
}
|
|
|
|
groupCount++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add state and transitions rewards for each reward structure.
|
|
if (view.getVisibleRewardColumns().size() > 0) {
|
|
if (groupCount == groupIndex) {
|
|
return "State, transition and cumulative rewards";
|
|
}
|
|
|
|
groupCount++;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public int getLastColumnOfGroup(int groupIndex)
|
|
{
|
|
int stepStart = 0;
|
|
int timeStart = stepStart + (view.showActions() ? 1 : 0) + (view.showSteps() ? 1 : 0);
|
|
int varStart = timeStart + (canShowTime() && view.showCumulativeTime() ? 1 : 0) + (canShowTime() && view.showTime() ? 1 : 0);
|
|
int rewardStart = varStart + view.getVisibleVariables().size();
|
|
|
|
int groupCount = 0;
|
|
|
|
if (view.showActions() || view.showSteps()) {
|
|
if (groupCount == groupIndex) {
|
|
if (view.showActions() && view.showSteps())
|
|
return stepStart + 1;
|
|
else
|
|
return stepStart;
|
|
}
|
|
|
|
groupCount++;
|
|
}
|
|
|
|
if (canShowTime() && (view.showCumulativeTime() || view.showTime())) {
|
|
if (groupCount == groupIndex) {
|
|
if (view.showCumulativeTime() && view.showTime())
|
|
return timeStart + 1;
|
|
else
|
|
return timeStart;
|
|
}
|
|
|
|
groupCount++;
|
|
}
|
|
|
|
if (view.getVisibleVariables().size() > 0) {
|
|
int visVarCount = 0;
|
|
|
|
ArrayList<Variable> vars = view.getVisibleVariables();
|
|
Set<String> varNames = new HashSet<String>();
|
|
|
|
for (Variable variable : vars) {
|
|
varNames.add(variable.getName());
|
|
}
|
|
|
|
boolean atLeastOneGlobal = false;
|
|
|
|
for (int g = 0; g < parsedModel.getNumGlobals(); g++) {
|
|
boolean contained = varNames.contains(parsedModel.getGlobal(g).getName());
|
|
|
|
if (!atLeastOneGlobal && contained) {
|
|
atLeastOneGlobal = true;
|
|
}
|
|
|
|
if (contained)
|
|
visVarCount++;
|
|
}
|
|
|
|
if (atLeastOneGlobal && groupCount == groupIndex) {
|
|
return varStart + visVarCount - 1;
|
|
}
|
|
|
|
if (atLeastOneGlobal) {
|
|
groupCount++;
|
|
}
|
|
|
|
for (int m = 0; m < parsedModel.getNumModules(); m++) {
|
|
Module module = parsedModel.getModule(m);
|
|
boolean atLeastOne = false;
|
|
|
|
for (int v = 0; v < module.getNumDeclarations(); v++) {
|
|
boolean contained = varNames.contains(module.getDeclaration(v).getName());
|
|
if (!atLeastOne && contained) {
|
|
atLeastOne = true;
|
|
}
|
|
|
|
if (contained)
|
|
visVarCount++;
|
|
}
|
|
|
|
if (atLeastOne && groupCount == groupIndex) {
|
|
return varStart + visVarCount - 1;
|
|
}
|
|
|
|
if (atLeastOne) {
|
|
groupCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add state and transitions rewards for each reward structure.
|
|
if (view.getVisibleRewardColumns().size() > 0) {
|
|
if (groupCount == groupIndex) {
|
|
return rewardStart + view.getVisibleRewardColumns().size() - 1;
|
|
}
|
|
|
|
groupCount++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Returns the number of columns.
|
|
* @see javax.swing.table.TableModel#getColumnCount()
|
|
*/
|
|
public int getColumnCount()
|
|
{
|
|
if (!pathActive) {
|
|
return 0;
|
|
} else {
|
|
int colCount = 0;
|
|
|
|
colCount += (view.showActions() ? 1 : 0);
|
|
colCount += (view.showSteps() ? 1 : 0);
|
|
colCount += (canShowTime() && view.showCumulativeTime() ? 1 : 0) + (canShowTime() && view.showTime() ? 1 : 0);
|
|
colCount += view.getVisibleVariables().size();
|
|
colCount += view.getVisibleRewardColumns().size();
|
|
|
|
return colCount;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the number of rows.
|
|
* @see javax.swing.table.TableModel#getRowCount()
|
|
*/
|
|
public int getRowCount()
|
|
{
|
|
// Return current path size if there is an active path.
|
|
return (pathActive ? path.size() + 1 : 0);
|
|
}
|
|
|
|
public boolean shouldColourRow(int row)
|
|
{
|
|
int selection = simulator.getStateLabelList().getSelectedIndex();
|
|
if (selection != -1) {
|
|
GUISimLabelList.SimLabel label = (GUISimLabelList.SimLabel) simulator.getStateLabelList().getModel().getElementAt(selection);
|
|
if (row == getRowCount() - 1) {
|
|
if (label.getResult() == 1)
|
|
return true;
|
|
} else {
|
|
if (label.getResult(row) == 1)
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public String getColumnName(int columnIndex)
|
|
{
|
|
if (pathActive) {
|
|
int actionStart = 0;
|
|
int stepStart = actionStart + (view.showActions() ? 1 : 0);
|
|
int cumulativeTimeStart = stepStart + (view.showSteps() ? 1 : 0);
|
|
int timeStart = cumulativeTimeStart + (canShowTime() && view.showCumulativeTime() ? 1 : 0);
|
|
int varStart = timeStart + (canShowTime() && view.showTime() ? 1 : 0);
|
|
int rewardStart = varStart + view.getVisibleVariables().size();
|
|
|
|
// The step column
|
|
if (actionStart <= columnIndex && columnIndex < stepStart) {
|
|
return "Action";
|
|
} else if (stepStart <= columnIndex && columnIndex < cumulativeTimeStart) {
|
|
return "#";
|
|
} else if (cumulativeTimeStart <= columnIndex && columnIndex < timeStart) {
|
|
return "Time (+)";
|
|
} else if (timeStart <= columnIndex && columnIndex < varStart) {
|
|
return "Time";
|
|
}
|
|
// A variable column
|
|
else if (varStart <= columnIndex && columnIndex < rewardStart) {
|
|
return ((Variable) view.getVisibleVariables().get(columnIndex - varStart)).toString();
|
|
}
|
|
|
|
else if (rewardStart <= columnIndex) {
|
|
return ((RewardStructureColumn) view.getVisibleRewardColumns().get(columnIndex - rewardStart)).getColumnName();
|
|
}
|
|
}
|
|
return "Undefined Column";
|
|
}
|
|
|
|
public String getColumnToolTip(int columnIndex)
|
|
{
|
|
if (pathActive) {
|
|
int actionStart = 0;
|
|
int stepStart = actionStart + (view.showActions() ? 1 : 0);
|
|
int cumulativeTimeStart = stepStart + (view.showSteps() ? 1 : 0);
|
|
int timeStart = cumulativeTimeStart + (canShowTime() && view.showCumulativeTime() ? 1 : 0);
|
|
int varStart = timeStart + (canShowTime() && view.showTime() ? 1 : 0);
|
|
int rewardStart = varStart + view.getVisibleVariables().size();
|
|
|
|
// The step column
|
|
if (actionStart <= columnIndex && columnIndex < stepStart) {
|
|
return "Module name or [action] label";
|
|
} else if (stepStart <= columnIndex && columnIndex < cumulativeTimeStart) {
|
|
return "Index of state in path";
|
|
} else if (cumulativeTimeStart <= columnIndex && columnIndex < timeStart) {
|
|
return "Cumulative time";
|
|
} else if (timeStart <= columnIndex && columnIndex < varStart) {
|
|
return "Time spent in state";
|
|
}
|
|
// A variable column
|
|
else if (varStart <= columnIndex && columnIndex < rewardStart) {
|
|
return "Values of variable \"" + ((Variable) view.getVisibleVariables().get(columnIndex - varStart)).toString() + "\"";
|
|
}
|
|
|
|
else if (rewardStart <= columnIndex) {
|
|
RewardStructureColumn column = ((RewardStructureColumn) view.getVisibleRewardColumns().get(columnIndex - rewardStart));
|
|
String rewardName = column.getRewardStructure().getColumnName();
|
|
|
|
if (column.isStateReward())
|
|
return "State reward of reward structure " + rewardName;
|
|
if (column.isTransitionReward())
|
|
return "Transition reward of reward structure " + rewardName;
|
|
if (column.isCumulativeReward())
|
|
return "Cumulative reward of reward structure " + rewardName;
|
|
}
|
|
}
|
|
return "Undefined Column";
|
|
}
|
|
|
|
public Object getValueAt(int rowIndex, int columnIndex)
|
|
{
|
|
if (pathActive) {
|
|
int actionStart = 0;
|
|
int stepStart = actionStart + (view.showActions() ? 1 : 0);
|
|
int cumulativeTimeStart = stepStart + (view.showSteps() ? 1 : 0);
|
|
int timeStart = cumulativeTimeStart + (canShowTime() && view.showCumulativeTime() ? 1 : 0);
|
|
int varStart = timeStart + (canShowTime() && view.showTime() ? 1 : 0);
|
|
int rewardStart = varStart + view.getVisibleVariables().size();
|
|
|
|
// The action column
|
|
if (actionStart <= columnIndex && columnIndex < stepStart) {
|
|
actionValue = view.new ActionValue(rowIndex == 0 ? "" : path.getModuleOrAction(rowIndex - 1));
|
|
actionValue.setActionValueUnknown(false);
|
|
return actionValue;
|
|
}
|
|
// The step column
|
|
else if (stepStart <= columnIndex && columnIndex < cumulativeTimeStart) {
|
|
return "" + rowIndex;
|
|
}
|
|
// Cumulative time column
|
|
else if (cumulativeTimeStart <= columnIndex && columnIndex < timeStart) {
|
|
timeValue = view.new TimeValue(path.getCumulativeTime(rowIndex), true);
|
|
timeValue.setTimeValueUnknown(rowIndex > path.size()); // Never unknown
|
|
return timeValue;
|
|
}
|
|
// Time column
|
|
else if (timeStart <= columnIndex && columnIndex < varStart) {
|
|
timeValue = view.new TimeValue(path.getTime(rowIndex), false);
|
|
timeValue.setTimeValueUnknown(rowIndex >= path.size());
|
|
return timeValue;
|
|
}
|
|
// A variable column
|
|
else if (varStart <= columnIndex && columnIndex < rewardStart) {
|
|
Variable var = view.getVisibleVariables().get(columnIndex - varStart);
|
|
Object result = path.getState(rowIndex).varValues[var.getIndex()];
|
|
variableValue.setVariable(var);
|
|
variableValue.setValue(result);
|
|
variableValue.setChanged(rowIndex == 0 || !path.getState(rowIndex - 1).varValues[var.getIndex()].equals(result));
|
|
return variableValue;
|
|
}
|
|
// A reward column
|
|
else if (rewardStart <= columnIndex) {
|
|
RewardStructureColumn rewardColumn = (RewardStructureColumn) view.getVisibleRewardColumns().get(columnIndex - rewardStart);
|
|
rewardStructureValue.setRewardStructureColumn(rewardColumn);
|
|
rewardStructureValue.setRewardValueUnknown(false);
|
|
// A state reward column
|
|
if (rewardColumn.isStateReward()) {
|
|
double value = path.getStateReward(rowIndex, rewardColumn.getRewardStructure().getIndex());
|
|
rewardStructureValue.setChanged(rowIndex == 0
|
|
|| value != path.getStateReward(rowIndex - 1, rewardColumn.getRewardStructure().getIndex()));
|
|
rewardStructureValue.setRewardValue(new Double(value));
|
|
rewardStructureValue.setRewardValueUnknown(rowIndex > path.size()); // Never unknown
|
|
}
|
|
// A transition reward column
|
|
else if (rewardColumn.isTransitionReward()) {
|
|
double value = path.getTransitionReward(rowIndex, rewardColumn.getRewardStructure().getIndex());
|
|
rewardStructureValue.setChanged(rowIndex == 0
|
|
|| value != path.getTransitionReward(rowIndex - 1, rewardColumn.getRewardStructure().getIndex()));
|
|
rewardStructureValue.setRewardValue(new Double(value));
|
|
rewardStructureValue.setRewardValueUnknown(rowIndex >= path.size());
|
|
}
|
|
// A cumulative reward column
|
|
else {
|
|
double value = path.getCumulativeReward(rowIndex, rewardColumn.getRewardStructure().getIndex());
|
|
rewardStructureValue.setChanged(rowIndex == 0
|
|
|| value != (path.getCumulativeReward(rowIndex - 1, rewardColumn.getRewardStructure().getIndex())));
|
|
rewardStructureValue.setRewardValue(new Double(value));
|
|
rewardStructureValue.setRewardValueUnknown(rowIndex > path.size()); // Never unknown
|
|
}
|
|
return rewardStructureValue;
|
|
}
|
|
}
|
|
|
|
return "Undefined value";
|
|
}
|
|
|
|
/**
|
|
* Method is called when a new path is created.
|
|
* The structure of the path may be for a different model etc.
|
|
*/
|
|
public void restartPathTable()
|
|
{
|
|
view.refreshToDefaultView(pathActive, parsedModel);
|
|
}
|
|
|
|
/**
|
|
* Method is called whenever a path is modified.
|
|
*/
|
|
public void updatePathTable()
|
|
{
|
|
fireTableDataChanged();
|
|
}
|
|
|
|
public boolean isPathLooping()
|
|
{
|
|
return path.isLooping();
|
|
}
|
|
|
|
public int getLoopStart()
|
|
{
|
|
return path.loopStart();
|
|
}
|
|
|
|
public int getLoopEnd()
|
|
{
|
|
return path.loopEnd();
|
|
}
|
|
|
|
public SimulationView getView()
|
|
{
|
|
return view;
|
|
}
|
|
|
|
public void setView(SimulationView view)
|
|
{
|
|
this.view.deleteObserver(this);
|
|
this.view = view;
|
|
this.view.addObserver(this);
|
|
}
|
|
}
|