package mdps; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; import java.awt.GridLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; /** * This class displays a given value function in a panel. * * I've included a main method to illustrate how the class is used - you will need to create two other classes * (QLearningGUI and ValueIterationGUI) that incorporate this panel along with buttons and input * widgets controlling how many steps of Q Learning or iterations of Value Iteration are executed between * displays. * * Values are draw in shades of green (positive values) and red (negative values) scaled according to the * maximum value in any state. * * @author pippin * */ public class ValueFunctionPanel extends JPanel { Gridworld gridworld; QValueFunction valueFunc; private JLabel[][] labels; public ValueFunctionPanel(Gridworld gridworld, QValueFunction valueFunc) { super(); this.gridworld = gridworld; this.valueFunc = valueFunc; // labels in a grid - each label corresponds to a state. boolean[][] wallMatrix = gridworld.getWallMatrix(); setLayout(new GridLayout(wallMatrix.length, wallMatrix[0].length)); labels = new JLabel[wallMatrix.length][wallMatrix[0].length]; for (int i = 0; i < wallMatrix.length; i++) { for (int j = 0; j < wallMatrix[0].length; j++) { labels[i][j] = new JLabel(" "); add(labels[i][j]); } } } public double maxCurrentValue() { if (valueFunc == null) return 1.0; double max = Double.MIN_VALUE; for (int i = 0; i < gridworld.numStates(); i++) { for (int j = 0; j < gridworld.numActions(); j++) { if (valueFunc.getValue(i, j) > max) max = valueFunc.getValue(i, j); } } return max; } @Override public void paint(Graphics graphics) { boolean[][] wallMatrix = gridworld.getWallMatrix(); double maxValue = maxCurrentValue(); for (int i = 0; i < wallMatrix.length; i++) { for (int j = 0; j < wallMatrix[0].length; j++) { labels[i][j].setText(" "); labels[i][j].setOpaque(true); if (!wallMatrix[i][j]) { float value; if (valueFunc != null) { // scale the value value = (float) (valueFunc.getValue(gridworld.getStateId(i, j))/maxValue); if (value > 0) // positive values are green labels[i][j].setBackground(new Color(1-value, (float)1-(value/2), 1-value)); else // negative values are red labels[i][j].setBackground(new Color((float)1+(value/2), 1+value, 1+value)); } } else { // walls/obstacles are black labels[i][j].setText("W"); labels[i][j].setBackground(new Color(0,0,0)); } } } super.paint(graphics); } public static void main(String[] args) { if (args.length < 1) { System.out.println("One argument is required: the filename for the Gridworld text file."); return; } JFrame frame = new JFrame("Null Value Function Demo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Gridworld gridworld = new Gridworld(args[0]); frame.getContentPane().add(new ValueFunctionPanel(gridworld, null), BorderLayout.CENTER); frame.pack(); frame.setVisible(true); } }