mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 10:54:51 +00:00
Compare commits
9 Commits
319eaa33b1
...
Developmen
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea32598d4c | ||
|
|
40e1c3b124 | ||
|
|
22a73fc50a | ||
|
|
af9a316639 | ||
|
|
8508377cb4 | ||
|
|
97276c7e80 | ||
|
|
11eda3c8b5 | ||
|
|
039c0393c8 | ||
|
|
429e5bc90b |
@@ -1,23 +1,9 @@
|
|||||||
package org.toop;
|
package org.toop;
|
||||||
|
|
||||||
import org.toop.app.App;
|
import org.toop.app.App;
|
||||||
import org.toop.framework.game.games.reversi.BitboardReversi;
|
|
||||||
import org.toop.framework.game.players.ArtificialPlayer;
|
|
||||||
import org.toop.game.players.ai.MCTSAI;
|
|
||||||
import org.toop.game.players.ai.RandomAI;
|
|
||||||
import org.toop.game.players.ai.mcts.MCTSAI1;
|
|
||||||
import org.toop.game.players.ai.mcts.MCTSAI2;
|
|
||||||
import org.toop.game.players.ai.mcts.MCTSAI3;
|
|
||||||
import org.toop.game.players.ai.mcts.MCTSAI4;
|
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
public final class Main {
|
public final class Main {
|
||||||
static void main(String[] args) {
|
static void main(String[] args) {
|
||||||
App.run(args);
|
App.run(args);
|
||||||
|
|
||||||
// final ExecutorService executor = Executors.newFixedThreadPool(1);
|
|
||||||
// executor.execute(() -> testAIs(25));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ public final class Server {
|
|||||||
|
|
||||||
Player[] players = new Player[2];
|
Player[] players = new Player[2];
|
||||||
|
|
||||||
players[userStartingTurn] = new ArtificialPlayer(new MCTSAI3(1000), user);
|
players[userStartingTurn] = new ArtificialPlayer(new MCTSAI3(1000, 8), user);
|
||||||
players[opponentStartingTurn] = new OnlinePlayer(response.opponent());
|
players[opponentStartingTurn] = new OnlinePlayer(response.opponent());
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public class LocalMultiplayerView extends ViewWidget {
|
|||||||
if (information.players[1].isHuman) {
|
if (information.players[1].isHuman) {
|
||||||
players[1] = new LocalPlayer(information.players[1].name);
|
players[1] = new LocalPlayer(information.players[1].name);
|
||||||
} else {
|
} else {
|
||||||
players[1] = new ArtificialPlayer(new MCTSAI4(100), "MCTS V4 AI");
|
players[1] = new ArtificialPlayer(new MCTSAI4(100, 8), "MCTS V4 AI");
|
||||||
}
|
}
|
||||||
if (AppSettings.getSettings().getTutorialFlag() && AppSettings.getSettings().getFirstReversi()) {
|
if (AppSettings.getSettings().getTutorialFlag() && AppSettings.getSettings().getFirstReversi()) {
|
||||||
new ShowEnableTutorialWidget(
|
new ShowEnableTutorialWidget(
|
||||||
|
|||||||
195
game/src/main/java/org/toop/game/players/ai/MCTSAI2.java
Normal file
195
game/src/main/java/org/toop/game/players/ai/MCTSAI2.java
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
package org.toop.game.players.ai;
|
||||||
|
|
||||||
|
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
||||||
|
import org.toop.framework.gameFramework.model.player.AbstractAI;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class MCTSAI2 extends AbstractAI {
|
||||||
|
private static class Node {
|
||||||
|
public TurnBasedGame state;
|
||||||
|
|
||||||
|
public long move;
|
||||||
|
public long unexpandedMoves;
|
||||||
|
|
||||||
|
public Node parent;
|
||||||
|
|
||||||
|
public Node[] children;
|
||||||
|
public int expanded;
|
||||||
|
|
||||||
|
public float value;
|
||||||
|
public int visits;
|
||||||
|
|
||||||
|
public Node(TurnBasedGame state, Node parent, long move) {
|
||||||
|
final long legalMoves = state.getLegalMoves();
|
||||||
|
|
||||||
|
this.state = state;
|
||||||
|
|
||||||
|
this.move = move;
|
||||||
|
this.unexpandedMoves = legalMoves;
|
||||||
|
|
||||||
|
this.parent = parent;
|
||||||
|
|
||||||
|
this.children = new Node[Long.bitCount(legalMoves)];
|
||||||
|
this.expanded = 0;
|
||||||
|
|
||||||
|
this.value = 0.0f;
|
||||||
|
this.visits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node(TurnBasedGame state) {
|
||||||
|
this(state, null, 0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFullyExpanded() {
|
||||||
|
return expanded == children.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float calculateUCT(int parentVisits) {
|
||||||
|
final float exploitation = value / visits;
|
||||||
|
final float exploration = 1.41f * (float)(Math.sqrt(Math.log(parentVisits) / visits));
|
||||||
|
|
||||||
|
return exploitation + exploration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node bestUCTChild() {
|
||||||
|
Node highestUCTChild = null;
|
||||||
|
float highestUCT = Float.NEGATIVE_INFINITY;
|
||||||
|
|
||||||
|
for (int i = 0; i < expanded; i++) {
|
||||||
|
final float childUCT = children[i].calculateUCT(visits);
|
||||||
|
|
||||||
|
if (childUCT > highestUCT) {
|
||||||
|
highestUCTChild = children[i];
|
||||||
|
highestUCT = childUCT;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return highestUCTChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Random random;
|
||||||
|
private final int milliseconds;
|
||||||
|
|
||||||
|
public MCTSAI2(int milliseconds) {
|
||||||
|
this.random = new Random();
|
||||||
|
this.milliseconds = milliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MCTSAI2(MCTSAI2 other) {
|
||||||
|
this.random = other.random;
|
||||||
|
this.milliseconds = other.milliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MCTSAI2 deepCopy() {
|
||||||
|
return new MCTSAI2(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getMove(TurnBasedGame game) {
|
||||||
|
final Node root = new Node(game, null, 0L);
|
||||||
|
|
||||||
|
final long endTime = System.nanoTime() + milliseconds * 1_000_000L;
|
||||||
|
|
||||||
|
while (System.nanoTime() < endTime) {
|
||||||
|
Node leaf = selection(root);
|
||||||
|
leaf = expansion(leaf);
|
||||||
|
final float value = simulation(leaf);
|
||||||
|
backPropagation(leaf, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Node mostVisitedChild = mostVisitedChild(root);
|
||||||
|
|
||||||
|
return mostVisitedChild != null? mostVisitedChild.move : 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node mostVisitedChild(Node root) {
|
||||||
|
Node mostVisitedChild = null;
|
||||||
|
int mostVisited = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < root.expanded; i++) {
|
||||||
|
if (root.children[i].visits > mostVisited) {
|
||||||
|
mostVisitedChild = root.children[i];
|
||||||
|
mostVisited = root.children[i].visits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mostVisitedChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node selection(Node root) {
|
||||||
|
while (root.isFullyExpanded() && !root.state.isTerminal()) {
|
||||||
|
root = root.bestUCTChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node expansion(Node leaf) {
|
||||||
|
if (leaf.unexpandedMoves == 0L) {
|
||||||
|
return leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
final long unexpandedMove = leaf.unexpandedMoves & -leaf.unexpandedMoves;
|
||||||
|
|
||||||
|
final TurnBasedGame copiedState = leaf.state.deepCopy();
|
||||||
|
copiedState.play(unexpandedMove);
|
||||||
|
|
||||||
|
final Node expandedChild = new Node(copiedState, leaf, unexpandedMove);
|
||||||
|
|
||||||
|
leaf.children[leaf.expanded] = expandedChild;
|
||||||
|
leaf.expanded++;
|
||||||
|
|
||||||
|
leaf.unexpandedMoves &= ~unexpandedMove;
|
||||||
|
|
||||||
|
return expandedChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float simulation(Node leaf) {
|
||||||
|
final TurnBasedGame copiedState = leaf.state.deepCopy();
|
||||||
|
final int playerIndex = 1 - copiedState.getCurrentTurn();
|
||||||
|
|
||||||
|
while (!copiedState.isTerminal()) {
|
||||||
|
final long legalMoves = copiedState.getLegalMoves();
|
||||||
|
final long randomMove = randomSetBit(legalMoves);
|
||||||
|
|
||||||
|
copiedState.play(randomMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copiedState.getWinner() == playerIndex) {
|
||||||
|
return 1.0f;
|
||||||
|
} else if (copiedState.getWinner() >= 0) {
|
||||||
|
return -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void backPropagation(Node leaf, float value) {
|
||||||
|
while (leaf != null) {
|
||||||
|
leaf.value += value;
|
||||||
|
leaf.visits++;
|
||||||
|
|
||||||
|
value = -value;
|
||||||
|
leaf = leaf.parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long randomSetBit(long value) {
|
||||||
|
if (0L == value) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int bitCount = Long.bitCount(value);
|
||||||
|
final int randomBitCount = random.nextInt(bitCount);
|
||||||
|
|
||||||
|
for (int i = 0; i < randomBitCount; i++) {
|
||||||
|
value &= value - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value & -value;
|
||||||
|
}
|
||||||
|
}
|
||||||
258
game/src/main/java/org/toop/game/players/ai/MCTSAI3.java
Normal file
258
game/src/main/java/org/toop/game/players/ai/MCTSAI3.java
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
package org.toop.game.players.ai;
|
||||||
|
|
||||||
|
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
||||||
|
import org.toop.framework.gameFramework.model.player.AbstractAI;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class MCTSAI3 extends AbstractAI {
|
||||||
|
private static class Node {
|
||||||
|
public TurnBasedGame state;
|
||||||
|
|
||||||
|
public long move;
|
||||||
|
public long unexpandedMoves;
|
||||||
|
|
||||||
|
public Node parent;
|
||||||
|
|
||||||
|
public Node[] children;
|
||||||
|
public int expanded;
|
||||||
|
|
||||||
|
public float value;
|
||||||
|
public int visits;
|
||||||
|
|
||||||
|
public Node(TurnBasedGame state, Node parent, long move) {
|
||||||
|
final long legalMoves = state.getLegalMoves();
|
||||||
|
|
||||||
|
this.state = state;
|
||||||
|
|
||||||
|
this.move = move;
|
||||||
|
this.unexpandedMoves = legalMoves;
|
||||||
|
|
||||||
|
this.parent = parent;
|
||||||
|
|
||||||
|
this.children = new Node[Long.bitCount(legalMoves)];
|
||||||
|
this.expanded = 0;
|
||||||
|
|
||||||
|
this.value = 0.0f;
|
||||||
|
this.visits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node(TurnBasedGame state) {
|
||||||
|
this(state, null, 0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFullyExpanded() {
|
||||||
|
return expanded == children.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float calculateUCT(int parentVisits) {
|
||||||
|
final float exploitation = value / visits;
|
||||||
|
final float exploration = 1.41f * (float)(Math.sqrt(Math.log(parentVisits) / visits));
|
||||||
|
|
||||||
|
return exploitation + exploration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node bestUCTChild() {
|
||||||
|
Node highestUCTChild = null;
|
||||||
|
float highestUCT = Float.NEGATIVE_INFINITY;
|
||||||
|
|
||||||
|
for (int i = 0; i < expanded; i++) {
|
||||||
|
final float childUCT = children[i].calculateUCT(visits);
|
||||||
|
|
||||||
|
if (childUCT > highestUCT) {
|
||||||
|
highestUCTChild = children[i];
|
||||||
|
highestUCT = childUCT;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return highestUCTChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Random random;
|
||||||
|
|
||||||
|
private Node root;
|
||||||
|
private final int milliseconds;
|
||||||
|
|
||||||
|
public MCTSAI3(int milliseconds) {
|
||||||
|
this.random = new Random();
|
||||||
|
|
||||||
|
this.root = null;
|
||||||
|
this.milliseconds = milliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MCTSAI3(MCTSAI3 other) {
|
||||||
|
this.random = other.random;
|
||||||
|
|
||||||
|
this.root = other.root;
|
||||||
|
this.milliseconds = other.milliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MCTSAI3 deepCopy() {
|
||||||
|
return new MCTSAI3(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getMove(TurnBasedGame game) {
|
||||||
|
detectRoot(game);
|
||||||
|
|
||||||
|
final long endTime = System.nanoTime() + milliseconds * 1_000_000L;
|
||||||
|
|
||||||
|
while (System.nanoTime() < endTime) {
|
||||||
|
Node leaf = selection(root);
|
||||||
|
leaf = expansion(leaf);
|
||||||
|
final float value = simulation(leaf);
|
||||||
|
backPropagation(leaf, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Node mostVisitedChild = mostVisitedChild(root);
|
||||||
|
final long move = mostVisitedChild != null? mostVisitedChild.move : 0L;
|
||||||
|
|
||||||
|
newRoot(move);
|
||||||
|
|
||||||
|
return move;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node mostVisitedChild(Node root) {
|
||||||
|
Node mostVisitedChild = null;
|
||||||
|
int mostVisited = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < root.expanded; i++) {
|
||||||
|
if (root.children[i].visits > mostVisited) {
|
||||||
|
mostVisitedChild = root.children[i];
|
||||||
|
mostVisited = root.children[i].visits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mostVisitedChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void detectRoot(TurnBasedGame game) {
|
||||||
|
if (root == null) {
|
||||||
|
root = new Node(game.deepCopy());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final long[] currentBoards = game.getBoard();
|
||||||
|
final long[] rootBoards = root.state.getBoard();
|
||||||
|
|
||||||
|
boolean detected = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < rootBoards.length; i++) {
|
||||||
|
if (rootBoards[i] != currentBoards[i]) {
|
||||||
|
detected = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < root.expanded; i++) {
|
||||||
|
final Node child = root.children[i];
|
||||||
|
|
||||||
|
final long[] childBoards = child.state.getBoard();
|
||||||
|
|
||||||
|
detected = true;
|
||||||
|
|
||||||
|
for (int j = 0; j < childBoards.length; j++) {
|
||||||
|
if (childBoards[j] != currentBoards[j]) {
|
||||||
|
detected = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detected) {
|
||||||
|
root = child;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
root = new Node(game.deepCopy());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void newRoot(long move) {
|
||||||
|
for (final Node child : root.children) {
|
||||||
|
if (child.move == move) {
|
||||||
|
root = child;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node selection(Node root) {
|
||||||
|
while (root.isFullyExpanded() && !root.state.isTerminal()) {
|
||||||
|
root = root.bestUCTChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node expansion(Node leaf) {
|
||||||
|
if (leaf.unexpandedMoves == 0L) {
|
||||||
|
return leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
final long unexpandedMove = leaf.unexpandedMoves & -leaf.unexpandedMoves;
|
||||||
|
|
||||||
|
final TurnBasedGame copiedState = leaf.state.deepCopy();
|
||||||
|
copiedState.play(unexpandedMove);
|
||||||
|
|
||||||
|
final Node expandedChild = new Node(copiedState, leaf, unexpandedMove);
|
||||||
|
|
||||||
|
leaf.children[leaf.expanded] = expandedChild;
|
||||||
|
leaf.expanded++;
|
||||||
|
|
||||||
|
leaf.unexpandedMoves &= ~unexpandedMove;
|
||||||
|
|
||||||
|
return expandedChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float simulation(Node leaf) {
|
||||||
|
final TurnBasedGame copiedState = leaf.state.deepCopy();
|
||||||
|
final int playerIndex = 1 - copiedState.getCurrentTurn();
|
||||||
|
|
||||||
|
while (!copiedState.isTerminal()) {
|
||||||
|
final long legalMoves = copiedState.getLegalMoves();
|
||||||
|
final long randomMove = randomSetBit(legalMoves);
|
||||||
|
|
||||||
|
copiedState.play(randomMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copiedState.getWinner() == playerIndex) {
|
||||||
|
return 1.0f;
|
||||||
|
} else if (copiedState.getWinner() >= 0) {
|
||||||
|
return -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void backPropagation(Node leaf, float value) {
|
||||||
|
while (leaf != null) {
|
||||||
|
leaf.value += value;
|
||||||
|
leaf.visits++;
|
||||||
|
|
||||||
|
value = -value;
|
||||||
|
leaf = leaf.parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long randomSetBit(long value) {
|
||||||
|
if (0L == value) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int bitCount = Long.bitCount(value);
|
||||||
|
final int randomBitCount = random.nextInt(bitCount);
|
||||||
|
|
||||||
|
for (int i = 0; i < randomBitCount; i++) {
|
||||||
|
value &= value - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value & -value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package org.toop.game.players.ai.mcts;
|
|||||||
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
||||||
import org.toop.game.players.ai.MCTSAI;
|
import org.toop.game.players.ai.MCTSAI;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -11,22 +12,18 @@ public class MCTSAI3 extends MCTSAI {
|
|||||||
private final int threads;
|
private final int threads;
|
||||||
private final ExecutorService threadPool;
|
private final ExecutorService threadPool;
|
||||||
|
|
||||||
public MCTSAI3(int milliseconds) {
|
|
||||||
threads = 8;
|
|
||||||
threadPool = Executors.newFixedThreadPool(8);
|
|
||||||
super(milliseconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MCTSAI3(int milliseconds, int threads) {
|
public MCTSAI3(int milliseconds, int threads) {
|
||||||
this.threads = threads;
|
|
||||||
threadPool = Executors.newFixedThreadPool(threads);
|
|
||||||
super(milliseconds);
|
super(milliseconds);
|
||||||
|
|
||||||
|
this.threads = threads;
|
||||||
|
this.threadPool = Executors.newFixedThreadPool(threads);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MCTSAI3(MCTSAI3 other) {
|
public MCTSAI3(MCTSAI3 other) {
|
||||||
threads = 8;
|
|
||||||
threadPool = Executors.newFixedThreadPool(8);
|
|
||||||
super(other);
|
super(other);
|
||||||
|
|
||||||
|
this.threads = other.threads;
|
||||||
|
this.threadPool = other.threadPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -40,12 +37,21 @@ public class MCTSAI3 extends MCTSAI {
|
|||||||
|
|
||||||
final long endTime = System.nanoTime() + milliseconds * 1_000_000L;
|
final long endTime = System.nanoTime() + milliseconds * 1_000_000L;
|
||||||
|
|
||||||
|
final CountDownLatch latch = new CountDownLatch(threads);
|
||||||
|
|
||||||
for (int i = 0; i < threads; i++) {
|
for (int i = 0; i < threads; i++) {
|
||||||
threadPool.submit(() -> iterate(root, endTime));
|
threadPool.submit(() -> {
|
||||||
|
try {
|
||||||
|
iterate(root, endTime);
|
||||||
|
} finally {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
threadPool.awaitTermination(milliseconds, TimeUnit.MILLISECONDS);
|
final long remaining = endTime - System.nanoTime();
|
||||||
|
latch.await(remaining, TimeUnit.NANOSECONDS);
|
||||||
|
|
||||||
lastIterations = root.visits.get();
|
lastIterations = root.visits.get();
|
||||||
|
|
||||||
@@ -59,14 +65,12 @@ public class MCTSAI3 extends MCTSAI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Void iterate(Node root, long endTime) {
|
private void iterate(Node root, long endTime) {
|
||||||
while (Float.isNaN(root.solved) && System.nanoTime() < endTime) {
|
while (Float.isNaN(root.solved) && System.nanoTime() < endTime) {
|
||||||
Node leaf = selection(root);
|
Node leaf = selection(root);
|
||||||
leaf = expansion(leaf);
|
leaf = expansion(leaf);
|
||||||
final int value = simulation(leaf);
|
final int value = simulation(leaf);
|
||||||
backPropagation(leaf, value);
|
backPropagation(leaf, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ package org.toop.game.players.ai.mcts;
|
|||||||
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
||||||
import org.toop.game.players.ai.MCTSAI;
|
import org.toop.game.players.ai.MCTSAI;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -13,25 +14,18 @@ public class MCTSAI4 extends MCTSAI {
|
|||||||
|
|
||||||
private Node root;
|
private Node root;
|
||||||
|
|
||||||
public MCTSAI4(int milliseconds) {
|
|
||||||
threads = 8;
|
|
||||||
threadPool = Executors.newFixedThreadPool(8);
|
|
||||||
super(milliseconds);
|
|
||||||
this.root = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MCTSAI4(int milliseconds, int threads) {
|
public MCTSAI4(int milliseconds, int threads) {
|
||||||
this.threads = threads;
|
|
||||||
threadPool = Executors.newFixedThreadPool(threads);
|
|
||||||
super(milliseconds);
|
super(milliseconds);
|
||||||
this.root = null;
|
|
||||||
|
this.threads = threads;
|
||||||
|
this.threadPool = Executors.newFixedThreadPool(threads);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MCTSAI4(MCTSAI4 other) {
|
public MCTSAI4(MCTSAI4 other) {
|
||||||
threads = 8;
|
|
||||||
threadPool = Executors.newFixedThreadPool(8);
|
|
||||||
super(other);
|
super(other);
|
||||||
this.root = other.root;
|
|
||||||
|
this.threads = other.threads;
|
||||||
|
this.threadPool = other.threadPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -45,12 +39,21 @@ public class MCTSAI4 extends MCTSAI {
|
|||||||
|
|
||||||
final long endTime = System.nanoTime() + milliseconds * 1_000_000L;
|
final long endTime = System.nanoTime() + milliseconds * 1_000_000L;
|
||||||
|
|
||||||
|
final CountDownLatch latch = new CountDownLatch(threads);
|
||||||
|
|
||||||
for (int i = 0; i < threads; i++) {
|
for (int i = 0; i < threads; i++) {
|
||||||
threadPool.submit(() -> iterate(root, endTime));
|
threadPool.submit(() -> {
|
||||||
|
try {
|
||||||
|
iterate(root, endTime);
|
||||||
|
} finally {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
threadPool.awaitTermination(milliseconds, TimeUnit.MILLISECONDS);
|
final long remaining = endTime - System.nanoTime();
|
||||||
|
latch.await(remaining, TimeUnit.NANOSECONDS);
|
||||||
|
|
||||||
lastIterations = root.visits.get();
|
lastIterations = root.visits.get();
|
||||||
|
|
||||||
@@ -68,14 +71,12 @@ public class MCTSAI4 extends MCTSAI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Void iterate(Node root, long endTime) {
|
private void iterate(Node root, long endTime) {
|
||||||
while (Float.isNaN(root.solved) && System.nanoTime() < endTime) {
|
while (Float.isNaN(root.solved) && System.nanoTime() < endTime) {
|
||||||
Node leaf = selection(root);
|
Node leaf = selection(root);
|
||||||
leaf = expansion(leaf);
|
leaf = expansion(leaf);
|
||||||
final int value = simulation(leaf);
|
final int value = simulation(leaf);
|
||||||
backPropagation(leaf, value);
|
backPropagation(leaf, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,44 +30,20 @@ import java.util.List;
|
|||||||
|
|
||||||
public class AITest {
|
public class AITest {
|
||||||
|
|
||||||
private static String fileName = "gameDataThreads.csv";
|
private static String fileName = "gameData.csv";
|
||||||
|
|
||||||
private static List<Matchup> matchupList = new ArrayList<Matchup>();
|
private static List<Matchup> matchupList = new ArrayList<Matchup>();
|
||||||
private static List<AIData> dataList = new ArrayList<AIData>();
|
private static List<AIData> dataList = new ArrayList<AIData>();
|
||||||
private static List<GameData> gameDataList = new ArrayList<GameData>();
|
private static List<GameData> gameDataList = new ArrayList<GameData>();
|
||||||
|
|
||||||
// @BeforeAll
|
|
||||||
// public static void init() {
|
|
||||||
//
|
|
||||||
// var versions = new ArtificialPlayer[4];
|
|
||||||
// versions[0] = new ArtificialPlayer(new MCTSAI1(10), "MCTS V1");
|
|
||||||
// versions[1] = new ArtificialPlayer(new MCTSAI2(10), "MCTS V2");
|
|
||||||
// versions[2] = new ArtificialPlayer(new MCTSAI3(10), "MCTS V3");
|
|
||||||
// versions[3] = new ArtificialPlayer(new MCTSAI4(10), "MCTS V4");
|
|
||||||
//
|
|
||||||
// for (int i = 0; i < versions.length; i++) {
|
|
||||||
// for (int j = i + 1; j < versions.length; j++) {
|
|
||||||
// final int playerIndex1 = i % versions.length;
|
|
||||||
// final int playerIndex2 = j % versions.length;
|
|
||||||
// addMatch(versions[playerIndex1], versions[playerIndex2]);
|
|
||||||
// addMatch(versions[playerIndex2], versions[playerIndex1]); // home vs away system
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void init() {
|
public static void init() {
|
||||||
|
|
||||||
var versions = new ArtificialPlayer[9];
|
var versions = new ArtificialPlayer[4];
|
||||||
versions[0] = new ArtificialPlayer(new MCTSAI3(10, 1), "MCTS V3T1");
|
versions[0] = new ArtificialPlayer(new MCTSAI1(10), "MCTS V1");
|
||||||
versions[1] = new ArtificialPlayer(new MCTSAI3(10, 2), "MCTS V3T2");
|
versions[1] = new ArtificialPlayer(new MCTSAI2(10), "MCTS V2");
|
||||||
versions[2] = new ArtificialPlayer(new MCTSAI3(10, 4), "MCTS V3T4");
|
versions[2] = new ArtificialPlayer(new MCTSAI3(10, 8), "MCTS V3");
|
||||||
versions[3] = new ArtificialPlayer(new MCTSAI3(10, 8), "MCTS V3T8");
|
versions[3] = new ArtificialPlayer(new MCTSAI4(10, 8), "MCTS V4");
|
||||||
versions[4] = new ArtificialPlayer(new MCTSAI3(10, 16), "MCTS V3T16");
|
|
||||||
versions[5] = new ArtificialPlayer(new MCTSAI3(10, 128), "MCTS V3T128");
|
|
||||||
versions[6] = new ArtificialPlayer(new MCTSAI3(10, 256), "MCTS V3T256");
|
|
||||||
versions[7] = new ArtificialPlayer(new MCTSAI3(10, 512), "MCTS V3T512");
|
|
||||||
versions[8] = new ArtificialPlayer(new MCTSAI3(10, 1024), "MCTS V3T1024");
|
|
||||||
|
|
||||||
for (int i = 0; i < versions.length; i++) {
|
for (int i = 0; i < versions.length; i++) {
|
||||||
for (int j = i + 1; j < versions.length; j++) {
|
for (int j = i + 1; j < versions.length; j++) {
|
||||||
@@ -79,6 +55,32 @@ public class AITest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @BeforeAll
|
||||||
|
// public static void init() {
|
||||||
|
//
|
||||||
|
// var versions = new ArtificialPlayer[11];
|
||||||
|
// versions[0] = new ArtificialPlayer(new MCTSAI3(10, 1), "MCTS V3T1");
|
||||||
|
// versions[1] = new ArtificialPlayer(new MCTSAI3(10, 2), "MCTS V3T2");
|
||||||
|
// versions[2] = new ArtificialPlayer(new MCTSAI3(10, 4), "MCTS V3T4");
|
||||||
|
// versions[3] = new ArtificialPlayer(new MCTSAI3(10, 8), "MCTS V3T8");
|
||||||
|
// versions[4] = new ArtificialPlayer(new MCTSAI3(10, 16), "MCTS V3T16");
|
||||||
|
// versions[5] = new ArtificialPlayer(new MCTSAI3(10, 128), "MCTS V3T32");
|
||||||
|
// versions[6] = new ArtificialPlayer(new MCTSAI3(10, 256), "MCTS V3T64");
|
||||||
|
// versions[7] = new ArtificialPlayer(new MCTSAI3(10, 128), "MCTS V3T128");
|
||||||
|
// versions[8] = new ArtificialPlayer(new MCTSAI3(10, 256), "MCTS V3T256");
|
||||||
|
// versions[9] = new ArtificialPlayer(new MCTSAI3(10, 512), "MCTS V3T512");
|
||||||
|
// versions[10] = new ArtificialPlayer(new MCTSAI3(10, 1024), "MCTS V3T1024");
|
||||||
|
//
|
||||||
|
// for (int i = 0; i < versions.length; i++) {
|
||||||
|
// for (int j = i + 1; j < versions.length; j++) {
|
||||||
|
// final int playerIndex1 = i % versions.length;
|
||||||
|
// final int playerIndex2 = j % versions.length;
|
||||||
|
// addMatch(versions[playerIndex1], versions[playerIndex2]);
|
||||||
|
// addMatch(versions[playerIndex2], versions[playerIndex1]); // home vs away system
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
public static void addMatch(ArtificialPlayer v1, ArtificialPlayer v2) {
|
public static void addMatch(ArtificialPlayer v1, ArtificialPlayer v2) {
|
||||||
matchupList.add(new Matchup(v1, v2));
|
matchupList.add(new Matchup(v1, v2));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user