From 04b46374c49479fd325e8847aab3c1d8cf97df21 Mon Sep 17 00:00:00 2001 From: Joseph Walton-Rivers <jwalto@essex.ac.uk> Date: Fri, 12 Jun 2015 11:34:30 +0100 Subject: [PATCH] start of stuff --- src/battle/BattleTest.java | 8 +- src/battle/SimpleBattle.java | 12 +-- .../controllers/webpigeon/GaController.java | 18 ++++ .../controllers/webpigeon/GameEvaluator.java | 39 +++++++ .../controllers/webpigeon/StaticEvolver.java | 40 +++++++ src/ga/Eval2.java | 10 ++ src/ga/SimpleRandomHillClimber.java | 2 +- src/ga/SimpleRandomHillClimberEngine.java | 101 ++++++++++++++++++ 8 files changed, 216 insertions(+), 14 deletions(-) create mode 100644 src/battle/controllers/webpigeon/GaController.java create mode 100644 src/battle/controllers/webpigeon/GameEvaluator.java create mode 100644 src/battle/controllers/webpigeon/StaticEvolver.java create mode 100644 src/ga/Eval2.java create mode 100644 src/ga/SimpleRandomHillClimberEngine.java diff --git a/src/battle/BattleTest.java b/src/battle/BattleTest.java index 26608c8..4809ab4 100644 --- a/src/battle/BattleTest.java +++ b/src/battle/BattleTest.java @@ -1,14 +1,8 @@ package battle; -import javax.swing.*; - -import asteroids.Action; import battle.controllers.EmptyController; -import battle.controllers.FireController; import battle.controllers.FireForwardController; -import battle.controllers.RotateAndShoot; -import math.Vector2d; -import utilities.JEasyFrame; +import battle.controllers.webpigeon.StaticEvolver; /** * Created by simon lucas on 10/06/15. diff --git a/src/battle/SimpleBattle.java b/src/battle/SimpleBattle.java index 78e8926..4c4934b 100644 --- a/src/battle/SimpleBattle.java +++ b/src/battle/SimpleBattle.java @@ -60,9 +60,6 @@ public class SimpleBattle { this.p2 = p2; reset(); - stats.add(new PlayerStats(0, 0)); - stats.add(new PlayerStats(0, 0)); - while (!isGameOver()) { update(); } @@ -70,12 +67,15 @@ public class SimpleBattle { return 0; } - protected void reset() { + public void reset() { stats.clear(); objects.clear(); s1 = buildShip(250, 250, 0); s2 = buildShip(300, 300, 1); this.currentTick = 0; + + stats.add(new PlayerStats(0, 0)); + stats.add(new PlayerStats(0, 0)); } protected NeuroShip buildShip(int x, int y, int playerID) { @@ -90,8 +90,8 @@ public class SimpleBattle { // get the actions from each player // apply them to each player's ship, taking actions as necessary - Action a1 = p1.getAction(this, 0); - Action a2 = p2.getAction(this, 1); + Action a1 = p1.getAction(this.clone(), 0); + Action a2 = p2.getAction(this.clone(), 1); update(a1, a2); } diff --git a/src/battle/controllers/webpigeon/GaController.java b/src/battle/controllers/webpigeon/GaController.java new file mode 100644 index 0000000..b6503d7 --- /dev/null +++ b/src/battle/controllers/webpigeon/GaController.java @@ -0,0 +1,18 @@ +package battle.controllers.webpigeon; + +import asteroids.Action; + +/** + * Created by jwalto on 12/06/2015. + */ +public class GaController { + private double[] genome; + + public GaController(double[] genome) { + this.genome = genome; + } + + public Action getMove() { + return new Action(0,0, false); + } +} diff --git a/src/battle/controllers/webpigeon/GameEvaluator.java b/src/battle/controllers/webpigeon/GameEvaluator.java new file mode 100644 index 0000000..5c5bff2 --- /dev/null +++ b/src/battle/controllers/webpigeon/GameEvaluator.java @@ -0,0 +1,39 @@ +package battle.controllers.webpigeon; + +import asteroids.Action; +import battle.SimpleBattle; +import ga.Eval2; + +/** + * Created by jwalto on 12/06/2015. + */ +public class GameEvaluator implements Eval2 { + private SimpleBattle battle; + + public GameEvaluator(SimpleBattle battle, boolean reset) { + this.battle = battle.clone(); + + if (reset) { + this.battle.reset(); + } + } + + @Override + public double pointsDiff(double[] a, double[] b) { + SimpleBattle currBattle = battle.clone(); + currBattle.reset(); + + GaController controller1 = new GaController(a); + GaController controller2 = new GaController(b); + + while(!battle.isGameOver()) { + Action action1 = controller1.getMove(); + Action action2 = controller2.getMove(); + + currBattle.update(action1, action2); + } + + return 0; + } + +} diff --git a/src/battle/controllers/webpigeon/StaticEvolver.java b/src/battle/controllers/webpigeon/StaticEvolver.java new file mode 100644 index 0000000..e421b1b --- /dev/null +++ b/src/battle/controllers/webpigeon/StaticEvolver.java @@ -0,0 +1,40 @@ +package battle.controllers.webpigeon; + + +import asteroids.Action; +import battle.DebugController; +import battle.SimpleBattle; +import battle.controllers.EmptyController; +import ga.SimpleRandomHillClimberEngine; + +import java.awt.*; +import java.util.Arrays; + +/** + * Created by jwalto on 12/06/2015. + */ +public class StaticEvolver { + private GameEvaluator eval; + private SimpleRandomHillClimberEngine rch; + + public StaticEvolver(SimpleBattle battle) { + this.eval = new GameEvaluator(battle, true); + this.rch = new SimpleRandomHillClimberEngine(new double[]{0}, eval); + } + + public double[] getBest() { + return rch.run(100); + } + + public static void main(String[] args) { + SimpleBattle start = new SimpleBattle(); + start.reset(); + + StaticEvolver evo = new StaticEvolver(start); + double[] best = evo.getBest(); + + System.out.println(Arrays.toString(best)); + } + + +} diff --git a/src/ga/Eval2.java b/src/ga/Eval2.java new file mode 100644 index 0000000..70fd0b4 --- /dev/null +++ b/src/ga/Eval2.java @@ -0,0 +1,10 @@ +package ga; + +/** + * Created by jwalto on 12/06/2015. + */ +public interface Eval2 { + + double pointsDiff(double[] a, double[] b); + +} diff --git a/src/ga/SimpleRandomHillClimber.java b/src/ga/SimpleRandomHillClimber.java index 70a3d33..fa1fe3d 100644 --- a/src/ga/SimpleRandomHillClimber.java +++ b/src/ga/SimpleRandomHillClimber.java @@ -1,4 +1,4 @@ -package ea; +package ga; import java.util.Arrays; import java.util.Random; diff --git a/src/ga/SimpleRandomHillClimberEngine.java b/src/ga/SimpleRandomHillClimberEngine.java new file mode 100644 index 0000000..e320fcd --- /dev/null +++ b/src/ga/SimpleRandomHillClimberEngine.java @@ -0,0 +1,101 @@ +package ga; + +import java.util.Arrays; +import java.util.Random; + +public class SimpleRandomHillClimberEngine { + + // Random mutation hill climber + // using a relative (hence co-evolutionary) + // fitness function + static Random random = new Random(); + + double[] bestYet; + Eval2 eval; + + double stepFac = 0.1; + + // set stepAdjust to 1.0 to keep the stepFac fixed + + // on quadratic bowl 1.01 works much better than 1.0 + // which increases the step size every time a mutation + // is successful and decreases it every time it fails + // to improve + // but be careful: could it make things worse in some cases? + double stepAdjust = 1.01; + + // example ready for a minimal version of + // co-evolution + + public static void main(String[] args) { + int nEvals = 1000; + int nDim = 10; + double[] init = randVec(nDim); + SimpleRandomHillClimberEngine evo = new SimpleRandomHillClimberEngine(init, new QuadraticBowl()); + + evo.run(nEvals); + + System.out.println("Best Found: " + Arrays.toString(evo.bestYet)); + System.out.println("Fitness: " + mag2(evo.bestYet)); + + } + + public SimpleRandomHillClimberEngine(double[] bestYet, Eval2 eval) { + this.bestYet = bestYet; + this.eval = eval; + } + + public double[] run(int nEvals) { + for (int i=0; i<nEvals; i++) { + // randomly mutate the best yet + double[] mut = randMut(bestYet, stepFac); + double diff = eval.pointsDiff(bestYet, mut); + + // if it's better then adopt the mutation as the new best + if (diff >= 0) { + bestYet = mut; + // try making it bigger - make even faster progress + } else { + // try making the step size smaller + stepFac /= stepAdjust; + } + System.out.println(i + "\t " + mag2(bestYet)); + } + + return bestYet; + } + + static double[] randVec(int n) { + double[] x = new double[n]; + for (int i=0; i<n; i++) { + x[i] = random.nextGaussian(); + } + return x; + } + + static double[] randMut(double[] v, double stepFac) { + int n = v.length; + double[] x = new double[n]; + for (int i=0; i<n; i++) { + x[i] = v[i] + stepFac * random.nextGaussian(); + } + return x; + } + + static class QuadraticBowl implements Eval2 { + + @Override + public double pointsDiff(double[] a, double[] b) { + // simple example that evaluates quality as being + // the minimum squared magnitude of a vector + return mag2(a) - mag2(b); + } + } + + static double mag2(double[] v) { + // square of the magnitude of the vector + double tot = 0; + for (double x : v) tot += x * x; + return tot; + } +} -- GitLab