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

//==============================================================================
//
// 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);
}
}