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:
2019-12-22 17:06:54 +01:00
parent 34e7e3fdd6
commit b1246f62cc
14 changed files with 337 additions and 155 deletions
+79 -13
View File
@@ -3,26 +3,37 @@ package core.controller;
import core.DiscreteActionSpace;
import core.Environment;
import core.ListDiscreteActionSpace;
import core.algo.EpisodicLearning;
import core.algo.Learning;
import core.algo.Method;
import core.algo.mc.MonteCarloOnPolicyEGreedy;
import core.gui.LearningView;
import core.gui.View;
import core.listener.LearningListener;
import core.listener.ViewListener;
import core.policy.EpsilonPolicy;
import javax.swing.*;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RLController<A extends Enum> implements ViewListener {
public class RLController<A extends Enum> implements ViewListener, LearningListener {
protected Environment<A> environment;
protected Learning<A> learning;
protected DiscreteActionSpace<A> discreteActionSpace;
protected View<A> view;
protected LearningView learningView;
private int delay;
private int nrOfEpisodes;
private Method method;
private int prevDelay;
private boolean fastLearning;
private boolean currentlyLearning;
private ExecutorService learningExecutor;
private List<Double> latestRewardsHistory;
public RLController(){
learningExecutor = Executors.newSingleThreadExecutor();
}
public void start(){
@@ -39,20 +50,37 @@ public class RLController<A extends Enum> implements ViewListener {
default:
throw new RuntimeException("Undefined method");
}
/*
not using SwingUtilities here on purpose to ensure the view is fully
initialized and can be passed as LearningListener.
*/
view = new View<>(learning, environment, this);
learning.addListener(view);
learning.learn(nrOfEpisodes);
SwingUtilities.invokeLater(()->{
learningView = new View<>(learning, environment, this);
learning.addListener(this);
});
if(learning instanceof EpisodicLearning){
learningExecutor.submit(()->((EpisodicLearning) learning).learn(nrOfEpisodes));
}else{
learningExecutor.submit(()->learning.learn());
}
}
/*************************************************
* VIEW LISTENERS *
*************************************************/
@Override
public void onLearnMoreEpisodes(int nrOfEpisodes){
if(!currentlyLearning){
if(learning instanceof EpisodicLearning){
learningExecutor.submit(()->((EpisodicLearning) learning).learn(nrOfEpisodes));
}else{
throw new RuntimeException("Triggering onLearnMoreEpisodes on non-episodic learning!");
}
}
}
@Override
public void onEpsilonChange(float epsilon) {
if(learning.getPolicy() instanceof EpsilonPolicy){
((EpsilonPolicy<A>) learning.getPolicy()).setEpsilon(epsilon);
SwingUtilities.invokeLater(() -> view.updateLearningInfoPanel());
SwingUtilities.invokeLater(() -> learningView.updateLearningInfoPanel());
}else{
System.out.println("Trying to call inEpsilonChange on non-epsilon policy");
}
@@ -65,12 +93,12 @@ public class RLController<A extends Enum> implements ViewListener {
private void changeLearningDelay(int delay){
learning.setDelay(delay);
SwingUtilities.invokeLater(() -> view.updateLearningInfoPanel());
SwingUtilities.invokeLater(() -> learningView.updateLearningInfoPanel());
}
@Override
public void onFastLearnChange(boolean fastLearn) {
view.setDrawEveryStep(!fastLearn);
this.fastLearning = fastLearn;
if(fastLearn){
prevDelay = learning.getDelay();
changeLearningDelay(0);
@@ -79,6 +107,45 @@ public class RLController<A extends Enum> implements ViewListener {
}
}
/*************************************************
* LEARNING LISTENERS *
*************************************************/
@Override
public void onLearningStart() {
currentlyLearning = true;
}
@Override
public void onLearningEnd() {
currentlyLearning = false;
SwingUtilities.invokeLater(()-> learningView.updateRewardGraph(latestRewardsHistory));
}
@Override
public void onEpisodeEnd(List<Double> rewardHistory) {
latestRewardsHistory = rewardHistory;
SwingUtilities.invokeLater(() ->{
if(!fastLearning){
learningView.updateRewardGraph(latestRewardsHistory);
}
learningView.updateLearningInfoPanel();
});
}
@Override
public void onEpisodeStart() {
}
@Override
public void onStepEnd() {
if(!fastLearning){
SwingUtilities.invokeLater(() -> learningView.repaintEnvironment());
}
}
public RLController<A> setMethod(Method method){
this.method = method;
return this;
@@ -102,5 +169,4 @@ public class RLController<A extends Enum> implements ViewListener {
this.nrOfEpisodes = nrOfEpisodes;
return this;
}
}