All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fathzer.games.perft.ForkJoinPerfT Maven / Gradle / Ivy

The newest version!
package com.fathzer.games.perft;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;

import com.fathzer.games.MoveGenerator;
import com.fathzer.games.MoveGenerator.MoveConfidence;

/** A Perft test based on the fork/join multi-threaded framework.
 * @see PerfTBuilder
 */
class ForkJoinPerfT extends MultiThreadedPerfT {
	@SuppressWarnings({"serial", "java:S1948"})
	private class DivideJob extends RecursiveTask> {
		M move;
		CountTask task;

		DivideJob(M move, CountTask task) {
			this.move = move;
			this.task = task;
		}

		@Override
		public Divide compute() {
			return new Divide<>(move, task.compute());
		}
	}

	@SuppressWarnings({"serial", "java:S1948"})
	private class CountTask extends RecursiveTask {
		private final MoveGenerator board;
		private final int depth;
		private final PerfTResult perftResult;

		CountTask(MoveGenerator board, int depth, PerfTResult result) {
			this.board = board;
			this.depth = depth;
			this.perftResult = result;
		}

		@Override
		protected Long compute() {
			if (isInterrupted() || depth==0) {
				return 1L;
			}
			final List moves = getMoves(board);
			perftResult.addMovesFound(moves.size());
			if (depth==1 && !playLeaves) {
				return (long)moves.size();
			}
			return depth >= 4 ? forkedCount(moves) : count(moves);
		}

		protected long forkedCount(final List moves) {
			final Collection tasks = new ArrayList<>(moves.size());
			for (M move : moves) {
				if (board.makeMove(move, moveType)) {
					perftResult.addMoveMade();
					tasks.add(new CountTask(board.fork(), depth-1, perftResult));
					board.unmakeMove();
				}
			}
			tasks.forEach(RecursiveTask::fork);
			return tasks.stream().mapToLong(ForkJoinTask::join).sum();
		}

		protected long count(final List moves) {
			long count = 0;
			for (M move : moves) {
				if (board.makeMove(move, moveType)) {
					perftResult.addMoveMade();
					count += new CountTask(board, depth-1, perftResult).compute();
					board.unmakeMove();
				}
			}
			return count;
		}
	}

	ForkJoinPerfT(ForkJoinPool exec, MoveGenerator board, int depth, boolean playLeaves, MoveConfidence moveType) {
		super(exec, board, depth, playLeaves, moveType);
	}
	
	@Override
	void compute(List moves) {
		final List jobs = moves.stream().map(move -> getDivideJob(move, result)).filter(Objects::nonNull).toList();
		jobs.stream().forEach(((ForkJoinPool)exec)::submit);
		addDivides(jobs.stream().map(job -> (Future>) job).toList());
	}
	
	private DivideJob getDivideJob(M move, PerfTResult result) {
		if (!board.makeMove(move, moveType)) {
			return null;
		}
		result.addMoveMade();
		final DivideJob job = new DivideJob(move, new CountTask(board.fork(), depth - 1, result));
		board.unmakeMove();
		return job;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy