7 Commits

Author SHA1 Message Date
lieght
2f161bcc0a Small thread count fix 2026-01-22 13:38:19 +01:00
lieght
ccdca4f0ea Added thread test 2026-01-22 12:30:42 +01:00
lieght
b5bd4adf91 AI wait fixes 2026-01-22 11:10:55 +01:00
lieght
f37c578a35 name fixes 2026-01-22 11:04:08 +01:00
lieght
eb1784550f Data collection fixes 2026-01-22 10:56:55 +01:00
lieght
e8f66a62f0 AI data now correct 2026-01-22 10:44:54 +01:00
lieght
4926bd161e m4 nu 8 threads 2026-01-22 10:29:22 +01:00
4 changed files with 102 additions and 44 deletions

View File

@@ -8,15 +8,24 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MCTSAI3 extends MCTSAI {
private static final int THREADS = 8;
private static final ExecutorService threadPool = Executors.newFixedThreadPool(THREADS);
private final int threads;
private final ExecutorService threadPool;
public MCTSAI3(int milliseconds) {
threads = 8;
threadPool = Executors.newFixedThreadPool(8);
super(milliseconds);
}
public MCTSAI3(int milliseconds, int threads) {
this.threads = threads;
threadPool = Executors.newFixedThreadPool(threads);
super(milliseconds);
}
public MCTSAI3(MCTSAI3 other) {
threads = 8;
threadPool = Executors.newFixedThreadPool(8);
super(other);
}
@@ -31,12 +40,12 @@ public class MCTSAI3 extends MCTSAI {
final long endTime = System.nanoTime() + milliseconds * 1_000_000L;
for (int i = 0; i < THREADS; i++) {
for (int i = 0; i < threads; i++) {
threadPool.submit(() -> iterate(root, endTime));
}
try {
threadPool.awaitTermination(milliseconds + 50, TimeUnit.MILLISECONDS);
threadPool.awaitTermination(milliseconds, TimeUnit.MILLISECONDS);
lastIterations = root.visits.get();

View File

@@ -8,21 +8,29 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MCTSAI4 extends MCTSAI {
private static final int THREADS = Runtime.getRuntime().availableProcessors();
private static final ExecutorService threadPool = Executors.newFixedThreadPool(THREADS);
private final int threads;
private final ExecutorService threadPool;
private Node root;
public MCTSAI4(int milliseconds) {
threads = 8;
threadPool = Executors.newFixedThreadPool(8);
super(milliseconds);
this.root = null;
}
public MCTSAI4(int milliseconds, int threads) {
this.threads = threads;
threadPool = Executors.newFixedThreadPool(threads);
super(milliseconds);
this.root = null;
}
public MCTSAI4(MCTSAI4 other) {
threads = 8;
threadPool = Executors.newFixedThreadPool(8);
super(other);
this.root = other.root;
}
@@ -37,12 +45,12 @@ public class MCTSAI4 extends MCTSAI {
final long endTime = System.nanoTime() + milliseconds * 1_000_000L;
for (int i = 0; i < THREADS; i++) {
for (int i = 0; i < threads; i++) {
threadPool.submit(() -> iterate(root, endTime));
}
try {
threadPool.awaitTermination(milliseconds + 50, TimeUnit.MILLISECONDS);
threadPool.awaitTermination(milliseconds, TimeUnit.MILLISECONDS);
lastIterations = root.visits.get();

View File

@@ -23,27 +23,48 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.DecimalFormat;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class AITest {
private static String fileName = "gameDataThreads.csv";
private static List<Matchup> matchupList = new ArrayList<Matchup>();
private static List<AIData> dataList = new ArrayList<AIData>();
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
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");
var versions = new ArtificialPlayer[6];
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 V3T128");
for (int i = 0; i < versions.length; i++) {
for (int j = i + 1; j < versions.length; j++) {
@@ -77,8 +98,8 @@ public class AITest {
}
public void playGame(Matchup m) {
long millisecondscounterAI1 = 0L;
long millisecondscounterAI2 = 0L;
long nanocounterAI1 = 0L;
long nanocounterAI2 = 0L;
List<Integer> iterationsAI1 = new ArrayList<>();
List<Integer> iterationsAI2 = new ArrayList<>();
final BitboardReversi match = new BitboardReversi();
@@ -91,19 +112,21 @@ public class AITest {
final long startTime = System.nanoTime();
final long move = players[currentAI].getMove(match);
final long endTime = System.nanoTime();
if (players[currentAI].getAi() instanceof MCTSAI) {
final int lastIterations = ((MCTSAI) players[currentAI].getAi()).getLastIterations();
if (currentAI == 0) {
iterationsAI1.add(lastIterations);
millisecondscounterAI1 += (endTime - startTime);
nanocounterAI1 += (endTime - startTime);
} else {
iterationsAI2.add(lastIterations);
millisecondscounterAI2 += (endTime - startTime);
nanocounterAI2 += (endTime - startTime);
}
}
match.play(move);
}
generateMatchData(m.getPlayer1().getName(), m.getPlayer2().getName(), match, iterationsAI1, iterationsAI2, millisecondscounterAI1, millisecondscounterAI2);
generateMatchData(m.getPlayer1().getName(), m.getPlayer2().getName(), match, iterationsAI1, iterationsAI2, nanocounterAI1, nanocounterAI2);
}
public void generateMatchData(
@@ -114,8 +137,8 @@ public class AITest {
List<Integer> iterationsAI1,
List<Integer> iterationsAI2,
long millisecondscounterAI1,
long millisecondscounterAI2
long nanocounterAI1,
long nanocounterAI2
) {
try {
@@ -127,26 +150,32 @@ public class AITest {
var ai220 = iterationsAI2.subList(10, 19);
var ai230 = iterationsAI2.subList(20, iterationsAI2.size());
writeGamesToCSV("gameData.csv", new GameData(
writeGamesToCSV(fileName, new GameData(
AI1,
AI2,
getWinnerForMatch(AI1, AI2, match),
match.getAmountOfTurns(),
iterationsAI1.stream().mapToInt(Integer::intValue).sum(),
iterationsAI1.stream().mapToLong(Integer::longValue).sum(),
ai110.stream().mapToLong(Integer::longValue).sum(),
ai120.stream().mapToLong(Integer::longValue).sum(),
ai130.stream().mapToLong(Integer::longValue).sum(),
iterationsAI1.stream().mapToDouble(Integer::doubleValue).sum() / iterationsAI1.size(),
ai110.stream().mapToDouble(Integer::doubleValue).sum() / ai110.size(),
ai120.stream().mapToDouble(Integer::doubleValue).sum() / ai120.size(),
ai130.stream().mapToDouble(Integer::doubleValue).sum() / ai130.size(),
iterationsAI2.stream().mapToInt(Integer::intValue).sum(),
ai210.stream().mapToLong(Integer::longValue).sum(),
ai220.stream().mapToLong(Integer::longValue).sum(),
ai230.stream().mapToLong(Integer::longValue).sum(),
iterationsAI2.stream().mapToDouble(Integer::doubleValue).sum() / iterationsAI2.size(),
ai210.stream().mapToDouble(Integer::doubleValue).sum() / ai210.size(),
ai220.stream().mapToDouble(Integer::doubleValue).sum() / ai220.size(),
ai230.stream().mapToDouble(Integer::doubleValue).sum() / ai230.size(),
millisecondscounterAI1,
millisecondscounterAI2,
nanocounterAI1,
nanocounterAI2,
LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"))
));
} catch (IOException e) {
@@ -255,7 +284,7 @@ public class AITest {
final BufferedReader reader = new BufferedReader(new FileReader(filepath))
) {
if (reader.readLine() == null || reader.readLine().isBlank()) {
writer.write("Black,White,Winner,Turns Played,Black iterations,Black average iterations,Black average iterations 0-10,Black average iterations 11-20,Black average iterations 21-30,White iterations,White average iterations,White average iterations 0-10,White average iterations 11-20,White average iterations 21-30,Total Time AI1,Total Time AI2,Time");
writer.write("Black,White,Winner,Turns Played,Black total iterations,Black total iterations 0-10,Black total iterations 11-20,Black total iterations 21-30,Black average iterations,Black average iterations 0-10,Black average iterations 11-20,Black average iterations 21-30,White total iterations,White total iterations 0-10,White total iterations 11-20,White total iterations 21-30,White average iterations,White average iterations 0-10,White average iterations 11-20,White average iterations 21-30,Total Time AI1,Total Time AI2,Time");
writer.newLine();
}
@@ -265,17 +294,23 @@ public class AITest {
gameData.winner() + "," +
gameData.turns() + "," +
gameData.AI1totalIterations() + "," +
BigDecimal.valueOf(gameData.AI1averageIterations()).setScale(2, RoundingMode.DOWN) + "," +
BigDecimal.valueOf(gameData.AI1averageIterations10()).setScale(2, RoundingMode.DOWN) + "," +
BigDecimal.valueOf(gameData.AI1averageIterations20()).setScale(2, RoundingMode.DOWN) + "," +
BigDecimal.valueOf(gameData.AI1averageIterations30()).setScale(2, RoundingMode.DOWN) + "," +
gameData.AI1totalIterations10() + "," +
gameData.AI1totalIterations20() + "," +
gameData.AI1totalIterations30() + "," +
BigDecimal.valueOf(gameData.AI1averageIterations()).setScale(2, RoundingMode.HALF_EVEN) + "," +
BigDecimal.valueOf(gameData.AI1averageIterations10()).setScale(2, RoundingMode.HALF_EVEN) + "," +
BigDecimal.valueOf(gameData.AI1averageIterations20()).setScale(2, RoundingMode.HALF_EVEN) + "," +
BigDecimal.valueOf(gameData.AI1averageIterations30()).setScale(2, RoundingMode.HALF_EVEN) + "," +
gameData.AI2totalIterations() + "," +
BigDecimal.valueOf(gameData.AI2averageIterations()).setScale(2, RoundingMode.DOWN) + "," +
BigDecimal.valueOf(gameData.AI2averageIterations10()).setScale(2, RoundingMode.DOWN) + "," +
BigDecimal.valueOf(gameData.AI2averageIterations20()).setScale(2, RoundingMode.DOWN) + "," +
BigDecimal.valueOf(gameData.AI2averageIterations30()).setScale(2, RoundingMode.DOWN) + "," +
(gameData.millisecondsAI1() / 1_000_000L) + "," +
(gameData.millisecondsAI2() / 1_000_000L) + "," +
gameData.AI2totalIterations10() + "," +
gameData.AI2totalIterations20() + "," +
gameData.AI2totalIterations30() + "," +
BigDecimal.valueOf(gameData.AI2averageIterations()).setScale(2, RoundingMode.HALF_EVEN) + "," +
BigDecimal.valueOf(gameData.AI2averageIterations10()).setScale(2, RoundingMode.HALF_EVEN) + "," +
BigDecimal.valueOf(gameData.AI2averageIterations20()).setScale(2, RoundingMode.HALF_EVEN) + "," +
BigDecimal.valueOf(gameData.AI2averageIterations30()).setScale(2, RoundingMode.HALF_EVEN) + "," +
(gameData.nanoAI1() / 1_000_000L) + "," +
(gameData.nanoAI2() / 1_000_000L) + "," +
gameData.time());
writer.newLine();
}

View File

@@ -6,20 +6,26 @@ public record GameData(
String winner,
int turns,
int AI1totalIterations,
long AI1totalIterations,
long AI1totalIterations10,
long AI1totalIterations20,
long AI1totalIterations30,
double AI1averageIterations,
double AI1averageIterations10,
double AI1averageIterations20,
double AI1averageIterations30,
int AI2totalIterations,
long AI2totalIterations,
long AI2totalIterations10,
long AI2totalIterations20,
long AI2totalIterations30,
double AI2averageIterations,
double AI2averageIterations10,
double AI2averageIterations20,
double AI2averageIterations30,
long millisecondsAI1,
long millisecondsAI2,
long nanoAI1,
long nanoAI2,
String time
) {}