Skip to content
This repository has been archived by the owner on Aug 10, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' of github.com:TilBlechschmidt/TreeOptimizationA…
Browse files Browse the repository at this point in the history
…nalysis
  • Loading branch information
TilBlechschmidt committed Dec 20, 2019
2 parents b58fe1d + d4c4df0 commit 7880925
Show file tree
Hide file tree
Showing 29 changed files with 297 additions and 230 deletions.
1 change: 1 addition & 0 deletions TreeEvaluationTool/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ dependencies {

// Use JUnit test framework
testImplementation 'junit:junit:4.12'
testImplementation "org.mockito:mockito-core:1.+"
}

application {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@
import de.nordakademie.treeOptimizationAnalysis.heuristicEvaluations.InARowGameHeuristicEvaluation.PointsCounter.Builder;
import de.nordakademie.treeOptimizationAnalysis.knownReactionPaths.CompressedKnownReactionPath;
import de.nordakademie.treeOptimizationAnalysis.knownReactionPaths.KnownReactionsPath;
import de.nordakademie.treeOptimizationAnalysis.knownReactionPaths.UncompressedKnownReactionsPath;
import de.nordakademie.treeOptimizationAnalysis.traversalIterator.BreadthFirstTreeTraversalIterator;
import de.nordakademie.treeOptimizationAnalysis.traversalIterator.DepthFirstTreeTraversalIterator;
import de.nordakademie.treeOptimizationAnalysis.traversalIterator.TreeTraversalIterator;

import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
Expand All @@ -34,21 +33,20 @@

public class App implements Runnable {
// define Output
private static final String ENTRY_SEPERATOR = "\n";
private static final String FIELD_SEPERATOR = "; ";
private static final String ENTRY_SEPARATOR = "\n";
private static final String FIELD_SEPARATOR = "; ";

// settings
private static final Consumer<String> output = System.out::print;
private static final long TIMEOUT_IN_NANOS = 60l * 1000000000l;
private static final long TIMEOUT_IN_NANOS = 60L * 1000000000L;
private static final int NUMBER_OF_THREADS = Runtime.getRuntime().availableProcessors();

// concurrnecy
private final ExecutorService executor = Executors.newFixedThreadPool(NUMBER_OF_THREADS);

private List<ExitCondition.Factory> exitConditions;
private List<Supplier<TreeTraversalIterator<?>>> treeTraversalIterators;
private List<Game<?>> games;
private List<KnownReactionsPath.Factory> caches;
private final List<ExitCondition.Factory> exitConditions;
private final List<Supplier<TreeTraversalIterator<?>>> treeTraversalIterators;
private final List<Game<?>> games;
private final List<KnownReactionsPath.Factory> caches;



Expand All @@ -58,7 +56,7 @@ public static void main(String[] args) {
BreadthFirstTreeTraversalIterator::new,
DepthFirstTreeTraversalIterator::new
);
List<KnownReactionsPath.Factory> caches = Arrays.asList(
List<KnownReactionsPath.Factory> caches = Collections.singletonList(
CompressedKnownReactionPath.FACTORY
);

Expand All @@ -73,7 +71,7 @@ public static void main(String[] args) {
}
}

List games = Arrays.asList(getChess());
List<Game<?>> games = Collections.singletonList(getChess());

System.out.println(exits.size());
int whatever = exits.size() * iterators.size() * caches.size();
Expand All @@ -83,7 +81,7 @@ public static void main(String[] args) {
new App(exits, iterators, games, caches).run();
}

private static Game getChess() {
private static Game<?> getChess() {
ChessPiece[][] board = {
{rook(PLAYER_1),pawn(PLAYER_1),null,null,null,null,pawn(PLAYER_2),rook(PLAYER_2)},
{knight(PLAYER_1),pawn(PLAYER_1),null,null,null,null,pawn(PLAYER_2),knight(PLAYER_2)},
Expand All @@ -96,24 +94,24 @@ private static Game getChess() {
};
ChessGameState initialBoard = new ChessGameState(board,PLAYER_1);

return new Game(Arrays.<HeuristicEvaluation.Factory<ChessGameState>>asList(ChessHeuristicEvaluation::new), Arrays.asList(initialBoard));
return new Game<>(Collections.<Factory<ChessGameState>>singletonList(ChessHeuristicEvaluation::new), Collections.singletonList(initialBoard));
}

private static Game getInARowGame() {
private static Game<?> getInARowGame() {
InARowGameState ticTacToe = new InARowGameState(3, 3, 3, false, Player.PLAYER_1);
InARowGameState fourWins = new InARowGameState(6, 4, 4, true, Player.PLAYER_1);
List<InARowGameState> games = Arrays.asList(fourWins);
List<InARowGameState> games = Collections.singletonList(fourWins);

HeuristicEvaluation.Factory<InARowGameState> objectsInFrameSquareSum = InARowGameHeuristicEvaluation.factory(LENGTH_BY_OBJECTS_IN_POSSIBLE_BOX.accumulateBy(ACCUMULATE_BY_SQUARE_SUM), 0);

List<HeuristicEvaluation.Factory> heuristics = new ArrayList<>();
List<HeuristicEvaluation.Factory<InARowGameState>> heuristics = new ArrayList<>();
for (Builder pcb : new Builder[] { LENGTH_BY_OBJECTS_IN_POSSIBLE_BOX, LENGTH_BY_CONSECUTIVE }) {
for (BinaryOperator<Integer> acc : new BinaryOperator[] { ACCUMULATE_BY_MAX, ACCUMULATE_BY_SQUARE_SUM }) {
heuristics.add(factory(pcb.accumulateBy(acc),1000));
}
}

return new Game(heuristics, games);
return new Game<>(heuristics, games);
}

public App(List<ExitCondition.Factory> exitConditions, List<Supplier<TreeTraversalIterator<?>>> treeTraversalIterators, List<Game<?>> games, List<KnownReactionsPath.Factory> caches) {
Expand All @@ -133,29 +131,27 @@ public void run() {
private <T extends GameState<T>> void analyze(Game<T> game) {
for (T initialState : game.initialGameStates) {
forEachController(game, Player.PLAYER_1, controller1Fact ->
forEachController(game, PLAYER_2, controller2Fact -> {
executor.execute(() -> {
Controller<T> controller1 = controller1Fact.get();
Controller<T> controller2 = controller2Fact.get();
long start = time();
GameStateTreeNode<T> node = new GameStateTreeNode<>(initialState, null, 0);

while (!node.getState().getGameSituation().isFinal()) {
try {
Controller<T> controller = node.getState().getNextChoice() == Player.PLAYER_1 ? controller1 : controller2;
node = controller.nextMove(node);
} catch (Exception e) {
printMetrics(controller1, controller2, node, initialState, time() - start, e.getClass().getSimpleName() + " during execution: " + e.getLocalizedMessage() + " at " + Arrays.toString(e.getStackTrace()));
return;
}
if (time() - start > TIMEOUT_IN_NANOS) {
printMetrics(controller1, controller2, node, initialState, time() - start, " timed out ");
return;
}
forEachController(game, PLAYER_2, controller2Fact -> executor.execute(() -> {
Controller<T> controller1 = controller1Fact.get();
Controller<T> controller2 = controller2Fact.get();
long start = time();
GameStateTreeNode<T> node = new GameStateTreeNode<>(initialState, null, 0);

while (!node.getState().getGameSituation().isFinal()) {
try {
Controller<T> controller = node.getState().getNextChoice() == Player.PLAYER_1 ? controller1 : controller2;
node = controller.nextMove(node);
} catch (Exception e) {
printMetrics(controller1, controller2, node, initialState, time() - start, e.getClass().getSimpleName() + " during execution: " + e.getLocalizedMessage() + " at " + Arrays.toString(e.getStackTrace()));
return;
}
printMetrics(controller1, controller2, node, initialState, time() - start, null);
});
}));
if (time() - start > TIMEOUT_IN_NANOS) {
printMetrics(controller1, controller2, node, initialState, time() - start, " timed out ");
return;
}
}
printMetrics(controller1, controller2, node, initialState, time() - start, null);
})));
}
}

Expand All @@ -168,7 +164,7 @@ private <T extends GameState<T>> void forEachController(Game<T> game, Player pla
for (Supplier<TreeTraversalIterator<?>> iteratorFactory : treeTraversalIterators) {
for (KnownReactionsPath.Factory cacheFactory : caches) {
for (HeuristicEvaluation.Factory<T> heuristicEvaluationFactory : game.heuristicEvaluations) {
callback.accept(() -> this.<T>createController(exitConditionFactory, iteratorFactory, cacheFactory, heuristicEvaluationFactory, player));
callback.accept(() -> this.createController(exitConditionFactory, iteratorFactory, cacheFactory, heuristicEvaluationFactory, player));
}
}
}
Expand All @@ -179,11 +175,11 @@ private <T extends GameState<T>> Controller<T> createController(
ExitCondition.Factory exitConditionFactory,
Supplier<TreeTraversalIterator<?>> treeTraversalIteratorFactory,
KnownReactionsPath.Factory cacheFactory,
HeuristicEvaluation.Factory<T> heuristicEvaluationFacotry,
HeuristicEvaluation.Factory<T> heuristicEvaluationFactory,
Player player) {
TreeTraversalIterator<T> treeTraversalIterator = (TreeTraversalIterator<T>) treeTraversalIteratorFactory.get();
KnownReactionsPath<T> cache = cacheFactory.<T>create();
HeuristicEvaluation<T> heuristicEvaluation = heuristicEvaluationFacotry.create();
KnownReactionsPath<T> cache = cacheFactory.create();
HeuristicEvaluation<T> heuristicEvaluation = heuristicEvaluationFactory.create();

ExitCondition<T> exitCondition = exitConditionFactory.create(heuristicEvaluation, cache, player);
return new Controller<>(exitCondition, treeTraversalIterator, heuristicEvaluation, cache);
Expand All @@ -192,24 +188,25 @@ private <T extends GameState<T>> Controller<T> createController(
private void printHeaders() {
for (NamedMetric m : NamedMetric.allMetrics) {
output.accept(m.toString());
output.accept(FIELD_SEPERATOR);
output.accept(FIELD_SEPARATOR);
}
output.accept(ENTRY_SEPERATOR);
};
output.accept(ENTRY_SEPARATOR);
}

private void printMetrics(Controller<?> controller1, Controller<?> controller2, GameStateTreeNode<?> finalNode, GameState<?> initialNode, long time, String error) {
synchronized (output) {
for (NamedMetric m : NamedMetric.allMetrics) {
Object val = m.messure(controller1, controller2, finalNode, initialNode, time, error);
Object val = m.measure(controller1, controller2, finalNode, initialNode, time, error);
output.accept(val == null ? " - " : val.toString());
output.accept(FIELD_SEPERATOR);
output.accept(FIELD_SEPARATOR);
}
output.accept(ENTRY_SEPERATOR);
output.accept(ENTRY_SEPARATOR);
}
}

private static class Game<T extends GameState<T>> {
private List<HeuristicEvaluation.Factory<T>> heuristicEvaluations;
private List<T> initialGameStates;
private final List<HeuristicEvaluation.Factory<T>> heuristicEvaluations;
private final List<T> initialGameStates;

public Game(List<HeuristicEvaluation.Factory<T>> heuristicEvaluations, List<T> initialGameStates) {
this.heuristicEvaluations = heuristicEvaluations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
import de.nordakademie.treeOptimizationAnalysis.traversalIterator.TreeTraversalIterator;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;

public class Controller<T extends GameState<T>> {
Expand Down Expand Up @@ -51,7 +49,9 @@ public GameStateTreeNode<T> nextMove(GameStateTreeNode<T> initialNode) {
iterator.push(this.initialNode);
long time = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime();

while (!next()) {
boolean running = true;
while (running) {
running = !next();
}

GameStateTreeNode<T> choice = choice();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class NamedMetric {
allMetrics.addAll(playerMetrics(Player.PLAYER_2));
}

private static final NamedMetric playerMetric (Player player,String name, Function<Controller<?>, Object> metric) {
private static NamedMetric playerMetric (Player player,String name, Function<Controller<?>, Object> metric) {
if(Player.PLAYER_1.equals(player)) {
return new NamedMetric(name + " of Player 1", (c1,c2,r,i,d,e) -> metric.apply(c1));
} else if (Player.PLAYER_2.equals(player)) {
Expand All @@ -68,15 +68,15 @@ private static final NamedMetric playerMetric (Player player,String name, Functi

}

private static final List<NamedMetric> playerMetrics(Player p) {
private static List<NamedMetric> playerMetrics(Player p) {
return Arrays.asList(
playerMetric(p, "expansion strategy", c -> c.getIterator().getClass().getSimpleName()),
playerMetric(p, "cache", c -> c.getCache().getClass().getSimpleName()),
playerMetric(p, "watched nodes", c -> c.getCache().size()),
playerMetric(p, "evaluation stategy", c -> c.getEvaluation()),
playerMetric(p, "evaluation strategy", Controller::getEvaluation),
playerMetric(p, "exit condition type", c -> c.getExitCondition().getClass().getSimpleName()),
playerMetric(p, "exit condition", c -> c.getExitCondition()),
playerMetric(p, "total Speed", c -> c.getTime())
playerMetric(p, "exit condition", Controller::getExitCondition),
playerMetric(p, "total Speed", Controller::getTime)
);
}

Expand Down Expand Up @@ -104,11 +104,11 @@ public NamedMetric(String name, Metric metric) {
}

private interface Metric {
Object messure(Controller<?> controller1, Controller<?> controller2, GameStateTreeNode<?> finalNode, GameState initialNode, long fullTime, String error);
Object measure(Controller<?> controller1, Controller<?> controller2, GameStateTreeNode<?> finalNode, GameState<?> initialNode, long fullTime, String error);
}

public Object messure(Controller<?> controller1, Controller<?> controller2, GameStateTreeNode<?> finalNode, GameState initialNode, long fullTime, String error) {
return metric.messure(controller1,controller2,finalNode,initialNode,fullTime, error);
public Object measure(Controller<?> controller1, Controller<?> controller2, GameStateTreeNode<?> finalNode, GameState<?> initialNode, long fullTime, String error) {
return metric.measure(controller1,controller2,finalNode,initialNode,fullTime, error);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public enum Player {
PLAYER_1(1),
PLAYER_2(2);

private int index;
private final int index;

Player(int index) {
this.index = index;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
import de.nordakademie.treeOptimizationAnalysis.knownReactionPaths.KnownReactionsPath;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

public class AndExitCondition<T extends GameState<T>> implements ExitCondition<T> {
Set<ExitCondition<T>> exitConditions;
final Set<ExitCondition<T>> exitConditions;

public static ExitCondition.Factory factory(ExitCondition.Factory... args) {
return new ExitCondition.Factory() {
Expand All @@ -28,6 +29,10 @@ public <T extends GameState<T>> ExitCondition<T> create(HeuristicEvaluation<T> h
public AndExitCondition(Set<ExitCondition<T>> exitConditions) {
this.exitConditions = exitConditions;
}
@SafeVarargs
public AndExitCondition(ExitCondition<T>... exitConditions) {
this(new HashSet<>(Arrays.asList(exitConditions)));
}

@Override
public boolean shouldBreak(GameStateTreeNode<T> evaluationBase, GameStateTreeNode<T> gameState) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
import de.nordakademie.treeOptimizationAnalysis.knownReactionPaths.KnownReactionsPath;

public class CompareToOtherOptionsByHeuristicExitCondition<T extends GameState<T>> implements ExitCondition<T> {
private double difference;
private KnownReactionsPath<T> cache;
private HeuristicEvaluation<T> heuristicEvaluation;
private Player player;
private final double difference;
private final KnownReactionsPath<T> cache;
private final HeuristicEvaluation<T> heuristicEvaluation;
private final Player player;

public static ExitCondition.Factory factory(double difference) {
return new ExitCondition.Factory() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
import de.nordakademie.treeOptimizationAnalysis.knownReactionPaths.KnownReactionsPath;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

public class OrExitCondition<T extends GameState<T>> implements ExitCondition<T> {
Set<ExitCondition<T>> exitConditions;
final Set<ExitCondition<T>> exitConditions;

public static ExitCondition.Factory factory(ExitCondition.Factory... args) {
return new Factory() {
Expand All @@ -29,6 +30,10 @@ public OrExitCondition(Set<ExitCondition<T>> exitConditions) {
this.exitConditions = exitConditions;
}

@SafeVarargs
public OrExitCondition(ExitCondition<T>... exitConditions) {
this(new HashSet<>(Arrays.asList(exitConditions)));
}
@Override
public boolean shouldBreak(GameStateTreeNode<T> evaluationBase, GameStateTreeNode<T> gameState) {
for(ExitCondition<T> exitCondition:exitConditions) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import de.nordakademie.treeOptimizationAnalysis.knownReactionPaths.KnownReactionsPath;

public class TurnCountingCondition<T extends GameState<T>> implements ExitCondition<T> {
private int turnsLookedForward;
private final int turnsLookedForward;

public static ExitCondition.Factory factory(int turnsLookedForward) {
return new ExitCondition.Factory() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package de.nordakademie.treeOptimizationAnalysis.gamePoints;

public class FixedGamePoints implements GamePoints {
private double player1Score;
private double player2Score;
private final double player1Score;
private final double player2Score;

public FixedGamePoints(double player1Score, double player2Score) {
this.player1Score = player1Score;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ public enum GameSituation implements GamePoints {
TIE(0, 0, true, "Tie"),
RUNNING(-0.1, -0.1, false, "Running");

private double player1Score;
private double player2Score;
private boolean isFinal;
private String description;
private final double player1Score;
private final double player2Score;
private final boolean isFinal;
private final String description;

GameSituation(double player1Score, double player2Score, boolean isFinal, String description) {
this.player1Score = player1Score;
Expand Down
Loading

0 comments on commit 7880925

Please sign in to comment.