add features to gui to control learning and moving learning listener interface to controller
- Add metric to display episodes per second - view not implementing learning listener anymore, controller does. Controller is controlling all view actions based upon learning events. Reacts to view events via viewListener - add executor service for learning task - using instance of to distinguish between episodic learning and td learning - add feature to trigger more episodes - add checkboxes for smoothing graph, displaying last 100 rewards only and drawing environment - remove history panel from antworld gui
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
package core.gui;
|
||||
|
||||
import core.Util;
|
||||
import core.algo.Episodic;
|
||||
import core.algo.EpisodicLearning;
|
||||
import core.algo.Learning;
|
||||
import core.listener.ViewListener;
|
||||
import core.policy.EpsilonPolicy;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class LearningInfoPanel extends JPanel {
|
||||
private Learning learning;
|
||||
@@ -18,6 +21,11 @@ public class LearningInfoPanel extends JPanel {
|
||||
private JSlider delaySlider;
|
||||
private JButton toggleFastLearningButton;
|
||||
private boolean fastLearning;
|
||||
private JCheckBox smoothGraphCheckbox;
|
||||
private JCheckBox last100Checkbox;
|
||||
private JCheckBox drawEnvironmentCheckbox;
|
||||
private JTextField learnMoreEpisodesInput;
|
||||
private JButton learnMoreEpisodesButton;
|
||||
|
||||
public LearningInfoPanel(Learning learning, ViewListener viewListener){
|
||||
this.learning = learning;
|
||||
@@ -47,11 +55,37 @@ public class LearningInfoPanel extends JPanel {
|
||||
fastLearning = !fastLearning;
|
||||
delaySlider.setEnabled(!fastLearning);
|
||||
epsilonSlider.setEnabled(!fastLearning);
|
||||
drawEnvironmentCheckbox.setSelected(!fastLearning);
|
||||
viewListener.onFastLearnChange(fastLearning);
|
||||
});
|
||||
smoothGraphCheckbox = new JCheckBox("Smoothen Graph");
|
||||
smoothGraphCheckbox.setSelected(false);
|
||||
last100Checkbox = new JCheckBox("Only show last 100 Rewards");
|
||||
last100Checkbox.setSelected(true);
|
||||
drawEnvironmentCheckbox = new JCheckBox("Update Environment");
|
||||
drawEnvironmentCheckbox.setSelected(true);
|
||||
|
||||
add(delayLabel);
|
||||
add(delaySlider);
|
||||
add(toggleFastLearningButton);
|
||||
|
||||
if(learning instanceof EpisodicLearning) {
|
||||
learnMoreEpisodesInput = new JTextField();
|
||||
learnMoreEpisodesInput.setMaximumSize(new Dimension(200,20));
|
||||
learnMoreEpisodesButton = new JButton("Learn More Episodes");
|
||||
learnMoreEpisodesButton.addActionListener(e -> {
|
||||
if (Util.isNumeric(learnMoreEpisodesInput.getText())) {
|
||||
viewListener.onLearnMoreEpisodes(Integer.parseInt(learnMoreEpisodesInput.getText()));
|
||||
} else {
|
||||
learnMoreEpisodesInput.setText("");
|
||||
}
|
||||
});
|
||||
add(learnMoreEpisodesInput);
|
||||
add(learnMoreEpisodesButton);
|
||||
}
|
||||
add(drawEnvironmentCheckbox);
|
||||
add(smoothGraphCheckbox);
|
||||
add(last100Checkbox);
|
||||
refreshLabels();
|
||||
setVisible(true);
|
||||
}
|
||||
@@ -60,14 +94,29 @@ public class LearningInfoPanel extends JPanel {
|
||||
policyLabel.setText("Policy: " + learning.getPolicy().getClass());
|
||||
discountLabel.setText("Discount factor: " + learning.getDiscountFactor());
|
||||
if(learning instanceof Episodic){
|
||||
episodeLabel.setText("Episode: " + ((Episodic)(learning)).getCurrentEpisode());
|
||||
episodeLabel.setText("Episode: " + ((Episodic)(learning)).getCurrentEpisode() +
|
||||
"\t Episodes to go: " + ((Episodic)(learning)).getEpisodesToGo() +
|
||||
"\t Eps/Sec: " + ((Episodic)(learning)).getEpisodesPerSecond());
|
||||
}
|
||||
if (learning.getPolicy() instanceof EpsilonPolicy) {
|
||||
epsilonLabel.setText("Exploration (Epsilon): " + ((EpsilonPolicy) learning.getPolicy()).getEpsilon());
|
||||
epsilonSlider.setValue((int)(((EpsilonPolicy) learning.getPolicy()).getEpsilon() * 100));
|
||||
}
|
||||
delayLabel.setText("Delay (ms): " + learning.getDelay());
|
||||
delaySlider.setValue(learning.getDelay());
|
||||
if(delaySlider.isEnabled()){
|
||||
delaySlider.setValue(learning.getDelay());
|
||||
}
|
||||
toggleFastLearningButton.setText(fastLearning ? "Disable fast-learning" : "Enable fast-learning");
|
||||
}
|
||||
|
||||
protected boolean isSmoothenGraphSelected() {
|
||||
return smoothGraphCheckbox.isSelected();
|
||||
}
|
||||
protected boolean isLast100Selected(){
|
||||
return last100Checkbox.isSelected();
|
||||
}
|
||||
|
||||
protected boolean isDrawEnvironmentSelected(){
|
||||
return drawEnvironmentCheckbox.isSelected();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package core.gui;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface LearningView {
|
||||
void repaintEnvironment();
|
||||
void updateLearningInfoPanel();
|
||||
void updateRewardGraph(final List<Double> rewardHistory);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package core.gui;
|
||||
import core.Environment;
|
||||
import core.algo.Learning;
|
||||
import core.listener.ViewListener;
|
||||
import core.listener.LearningListener;
|
||||
import javafx.util.Pair;
|
||||
import lombok.Getter;
|
||||
import org.knowm.xchart.QuickChart;
|
||||
import org.knowm.xchart.XChartPanel;
|
||||
@@ -12,8 +12,9 @@ import org.knowm.xchart.XYChart;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class View<A extends Enum> implements LearningListener {
|
||||
public class View<A extends Enum> implements LearningView{
|
||||
private Learning<A> learning;
|
||||
private Environment<A> environment;
|
||||
@Getter
|
||||
@@ -25,14 +26,12 @@ public class View<A extends Enum> implements LearningListener {
|
||||
private JFrame environmentFrame;
|
||||
private XChartPanel<XYChart> rewardChartPanel;
|
||||
private ViewListener viewListener;
|
||||
private boolean drawEveryStep;
|
||||
|
||||
public View(Learning<A> learning, Environment<A> environment, ViewListener viewListener) {
|
||||
this.learning = learning;
|
||||
this.environment = environment;
|
||||
this.viewListener = viewListener;
|
||||
drawEveryStep = true;
|
||||
SwingUtilities.invokeLater(this::initMainFrame);
|
||||
initMainFrame();
|
||||
}
|
||||
|
||||
private void initMainFrame() {
|
||||
@@ -92,46 +91,62 @@ public class View<A extends Enum> implements LearningListener {
|
||||
};
|
||||
}
|
||||
|
||||
public void setDrawEveryStep(boolean drawEveryStep){
|
||||
this.drawEveryStep = drawEveryStep;
|
||||
}
|
||||
public void updateRewardGraph(final List<Double> rewardHistory) {
|
||||
List<Integer> xValues;
|
||||
List<Double> yValues;
|
||||
if(learningInfoPanel.isLast100Selected()){
|
||||
yValues = new CopyOnWriteArrayList<>(rewardHistory.subList(rewardHistory.size() - Math.min(rewardHistory.size(), 100), rewardHistory.size()));
|
||||
xValues = new CopyOnWriteArrayList<>();
|
||||
for(int i = rewardHistory.size() - Math.min(rewardHistory.size(), 100); i <rewardHistory.size(); ++i){
|
||||
xValues.add(i);
|
||||
}
|
||||
}else{
|
||||
if(learningInfoPanel.isSmoothenGraphSelected()){
|
||||
Pair<List<Integer>, List<Double>> XYvalues = smoothenGraph(rewardHistory);
|
||||
xValues = XYvalues.getKey();
|
||||
yValues = XYvalues.getValue();
|
||||
}else{
|
||||
xValues = null;
|
||||
yValues = rewardHistory;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateRewardGraph(List<Double> rewardHistory) {
|
||||
rewardChart.updateXYSeries("rewardHistory", null, rewardHistory, null);
|
||||
rewardChart.updateXYSeries("rewardHistory", xValues, yValues, null);
|
||||
rewardChartPanel.revalidate();
|
||||
rewardChartPanel.repaint();
|
||||
}
|
||||
|
||||
private Pair<List<Integer>, List<Double>> smoothenGraph(List<Double> original){
|
||||
int totalXPoints = 100;
|
||||
|
||||
List<Integer> xValues = new CopyOnWriteArrayList<>();
|
||||
List<Double> tmp = new CopyOnWriteArrayList<>();
|
||||
int meanBatch = original.size() / totalXPoints;
|
||||
if(meanBatch < 1){
|
||||
meanBatch = 1;
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
int batchIdx = 0;
|
||||
double batchSum = 0;
|
||||
for(Double x: original) {
|
||||
++idx;
|
||||
batchSum += x;
|
||||
if (idx == 1 || ++batchIdx % meanBatch == 0) {
|
||||
tmp.add(batchSum / meanBatch);
|
||||
xValues.add(idx);
|
||||
batchSum = 0;
|
||||
}
|
||||
}
|
||||
return new Pair<>(xValues, tmp);
|
||||
}
|
||||
|
||||
public void updateLearningInfoPanel() {
|
||||
this.learningInfoPanel.refreshLabels();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEpisodeEnd(List<Double> rewardHistory) {
|
||||
SwingUtilities.invokeLater(() ->{
|
||||
if(drawEveryStep){
|
||||
updateRewardGraph(rewardHistory);
|
||||
}
|
||||
updateLearningInfoPanel();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEpisodeStart() {
|
||||
if(drawEveryStep) {
|
||||
SwingUtilities.invokeLater(this::repaintEnvironment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStepEnd() {
|
||||
if(drawEveryStep){
|
||||
SwingUtilities.invokeLater(this::repaintEnvironment);
|
||||
}
|
||||
}
|
||||
|
||||
private void repaintEnvironment(){
|
||||
if (environmentFrame != null) {
|
||||
public void repaintEnvironment(){
|
||||
if (environmentFrame != null && learningInfoPanel.isDrawEnvironmentSelected()) {
|
||||
environmentFrame.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user