diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..a1757ae --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 3126fcf..d223ea5 100644 --- a/build.gradle +++ b/build.gradle @@ -13,4 +13,6 @@ repositories { dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' + compileOnly 'org.projectlombok:lombok:1.18.10' + annotationProcessor 'org.projectlombok:lombok:1.18.10' } diff --git a/src/main/java/core/Action.java b/src/main/java/core/Action.java new file mode 100644 index 0000000..86c7c18 --- /dev/null +++ b/src/main/java/core/Action.java @@ -0,0 +1,8 @@ +package core; + +public interface Action { + int getIndex(); + String toString(); + int hashCode(); + boolean equals(Object obj); +} diff --git a/src/main/java/core/ActionSpace.java b/src/main/java/core/ActionSpace.java new file mode 100644 index 0000000..79c05bb --- /dev/null +++ b/src/main/java/core/ActionSpace.java @@ -0,0 +1,9 @@ +package core; + +import java.util.Set; + +public interface ActionSpace { + Set getAllActions(); + int getNumberOfAction(); + void addAction(DiscreteAction a); +} diff --git a/src/main/java/core/DiscreteAction.java b/src/main/java/core/DiscreteAction.java new file mode 100644 index 0000000..6413ce8 --- /dev/null +++ b/src/main/java/core/DiscreteAction.java @@ -0,0 +1,36 @@ +package core; + +public class DiscreteAction implements Action{ + private A action; + + public DiscreteAction(A action){ + this.action = action; + } + + @Override + public int getIndex(){ + return action.ordinal(); + } + + @Override + public String toString(){ + return action.toString(); + } + + @Override + public int hashCode() { + return getIndex(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + + return getIndex() == ((DiscreteAction) obj).getIndex(); + } +} diff --git a/src/main/java/core/DiscreteActionSpace.java b/src/main/java/core/DiscreteActionSpace.java new file mode 100644 index 0000000..d457aa7 --- /dev/null +++ b/src/main/java/core/DiscreteActionSpace.java @@ -0,0 +1,28 @@ +package core; + +import java.util.HashSet; +import java.util.Set; + +public class DiscreteActionSpace implements ActionSpace{ + private Set actions; + + public DiscreteActionSpace(){ + actions = new HashSet<>(); + } + + @Override + public void addAction(DiscreteAction action){ + actions.add(action); + } + + @Override + public int getNumberOfAction(){ + return actions.size(); + } + + + @Override + public Set getAllActions(){ + return actions; + } +} diff --git a/src/main/java/core/Observation.java b/src/main/java/core/Observation.java new file mode 100644 index 0000000..3dede06 --- /dev/null +++ b/src/main/java/core/Observation.java @@ -0,0 +1,4 @@ +package core; + +public interface Observation { +} diff --git a/src/main/java/core/RNG.java b/src/main/java/core/RNG.java new file mode 100644 index 0000000..c0b2e52 --- /dev/null +++ b/src/main/java/core/RNG.java @@ -0,0 +1,19 @@ +package core; + +import java.util.Random; + +public class RNG { + private static final Random rng; + private static final int SEED = 123; + static { + rng = new Random(SEED); + } + + public static Random getRandom() { + return rng; + } + + public static void reseed(){ + rng.setSeed(SEED); + } +} diff --git a/src/main/java/core/State.java b/src/main/java/core/State.java new file mode 100644 index 0000000..5acb4f0 --- /dev/null +++ b/src/main/java/core/State.java @@ -0,0 +1,7 @@ +package core; + +public interface State { + String toString(); + int hashCode(); + boolean equals(Object obj); +} diff --git a/src/main/java/core/StateActionHashTable.java b/src/main/java/core/StateActionHashTable.java new file mode 100644 index 0000000..4adda2f --- /dev/null +++ b/src/main/java/core/StateActionHashTable.java @@ -0,0 +1,66 @@ +package core; + +import java.util.HashMap; +import java.util.Map; + +/** + * Premise: All states have the complete action space + */ +public class StateActionHashTable implements StateActionTable { + + private final Map> table; + private ActionSpace actionSpace; + + public StateActionHashTable(ActionSpace actionSpace){ + table = new HashMap<>(); + this.actionSpace = actionSpace; + } + + /* + If the state is not present in the table at the time of + calling this method the DEFAULT_VALUE gets returned BUT + no the missing state is not inserted into the table! + + Inserting of missing states is ONLY done in "setValue()" + method. + */ + @Override + public double getValue(State state, Action action) { + final Map actionValues = table.get(state); + if (actionValues != null) { + return actionValues.get(action); + } + return DEFAULT_VALUE; + } + + /* + Update the value of an action for a specific state. + If the state is not present in the table yet, + it will get stored in combination with every action + from the action space initialized with the default value. + */ + @Override + public void setValue(State state, Action action, double value) { + final Map actionValues; + if (table.containsKey(state)) { + actionValues = table.get(state); + } else { + actionValues = createDefaultActionValues(); + table.put(state, actionValues); + } + actionValues.put(action, value); + } + + @Override + public Map getActionValues(State state) { + return null; + } + + private Map createDefaultActionValues(){ + final Map defaultActionValues = new HashMap<>(); + for(Action action: actionSpace.getAllActions()){ + defaultActionValues.put(action, DEFAULT_VALUE); + } + return defaultActionValues; + } +} diff --git a/src/main/java/core/StateActionTable.java b/src/main/java/core/StateActionTable.java new file mode 100644 index 0000000..7fecafb --- /dev/null +++ b/src/main/java/core/StateActionTable.java @@ -0,0 +1,12 @@ +package core; + +import java.util.Map; + +public interface StateActionTable { + double DEFAULT_VALUE = 0.0; + + double getValue(State state, Action action); + void setValue(State state, Action action, double value); + + Map getActionValues(State state); +} diff --git a/src/main/java/core/StepResult.java b/src/main/java/core/StepResult.java new file mode 100644 index 0000000..f515ee6 --- /dev/null +++ b/src/main/java/core/StepResult.java @@ -0,0 +1,15 @@ +package core; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class StepResult { + private Observation observation; + private double reward; + private boolean done; + private String info; +} diff --git a/src/main/java/evironment/antGame/AntAction.java b/src/main/java/evironment/antGame/AntAction.java new file mode 100644 index 0000000..aeb5217 --- /dev/null +++ b/src/main/java/evironment/antGame/AntAction.java @@ -0,0 +1,10 @@ +package evironment.antGame; + +public enum AntAction { + MOVE_UP, + MOVE_RIGHT, + MOVE_DOWN, + MOVE_LEFT, + PICK_UP, + DROP_DOWN, +} diff --git a/src/main/java/evironment/antGame/AntObservation.java b/src/main/java/evironment/antGame/AntObservation.java new file mode 100644 index 0000000..fa4413e --- /dev/null +++ b/src/main/java/evironment/antGame/AntObservation.java @@ -0,0 +1,6 @@ +package evironment.antGame; + +import core.Observation; + +public class AntObservation implements Observation { +} diff --git a/src/main/java/evironment/antGame/AntState.java b/src/main/java/evironment/antGame/AntState.java new file mode 100644 index 0000000..a9f2181 --- /dev/null +++ b/src/main/java/evironment/antGame/AntState.java @@ -0,0 +1,7 @@ +package evironment.antGame; + +import core.State; + +// somewhat the "brain" of the agent, current known setting of the environment +public class AntState implements State { +} diff --git a/src/main/java/evironment/antGame/AntWorld.java b/src/main/java/evironment/antGame/AntWorld.java new file mode 100644 index 0000000..a6cfda4 --- /dev/null +++ b/src/main/java/evironment/antGame/AntWorld.java @@ -0,0 +1,28 @@ +package evironment.antGame; + +import core.DiscreteAction; +import core.Observation; +import core.RNG; +import core.StepResult; + +public class AntWorld { + private Grid grid; + + public AntWorld(int width, int height, double foodDensity){ + grid = new Grid(width, height, foodDensity); + } + + public AntWorld(){ + this(30, 30, 0.1); + } + + public StepResult step(DiscreteAction action){ + Observation observation = new AntObservation(); + return new StepResult(observation, 0.0, false, ""); + } + + public void reset(){ + RNG.reseed(); + grid.initCells(); + } +} diff --git a/src/main/java/evironment/antGame/Cell.java b/src/main/java/evironment/antGame/Cell.java new file mode 100644 index 0000000..836d1ee --- /dev/null +++ b/src/main/java/evironment/antGame/Cell.java @@ -0,0 +1,23 @@ +package evironment.antGame; + +public class Cell { + private CellType type; + private int food; + + public Cell(CellType cellType, int foodAmount){ + type = cellType; + food = foodAmount; + } + + public Cell(CellType cellType){ + this(cellType, 0); + } + + public void setFoodCount(int amount){ + food = amount; + } + + public int getFoodCount(){ + return food; + } +} diff --git a/src/main/java/evironment/antGame/CellType.java b/src/main/java/evironment/antGame/CellType.java new file mode 100644 index 0000000..1cb1ad3 --- /dev/null +++ b/src/main/java/evironment/antGame/CellType.java @@ -0,0 +1,8 @@ +package evironment.antGame; + +public enum CellType { + START, + FREE, + OBSTACLE, + FOOD, +} diff --git a/src/main/java/evironment/antGame/Grid.java b/src/main/java/evironment/antGame/Grid.java new file mode 100644 index 0000000..409a4e4 --- /dev/null +++ b/src/main/java/evironment/antGame/Grid.java @@ -0,0 +1,51 @@ +package evironment.antGame; + +import core.RNG; + +import java.awt.*; + +public class Grid { + private int width; + private int height; + private double foodDensity; + private Point start; + private Cell[][] grid; + + public Grid(int width, int height, double foodDensity){ + this.width = width; + this.height = height; + this.foodDensity = foodDensity; + + grid = new Cell[width][height]; + } + + public void initCells(){ + for(int x = 0; x < width; ++x){ + for(int y = 0; y < height; ++y){ + if( RNG.getRandom().nextDouble() < foodDensity){ + grid[x][y] = new Cell(CellType.FOOD, 1); + }else{ + grid[x][y] = new Cell(CellType.FREE); + } + } + } + start = new Point(RNG.getRandom().nextInt(width), RNG.getRandom().nextInt(height)); + grid[start.x][start.y] = new Cell(CellType.START); + } + + public Point getStartPoint(){ + return start; + } + + public Cell[][] getGrid(){ + return grid; + } + + public int getWidth(){ + return width; + } + public int getHeight(){ + return height; + } + +}