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:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user