Add neat arena

This commit is contained in:
Peter Stockings
2026-01-12 08:58:45 +11:00
parent e9cb8b52df
commit 840e597413
39 changed files with 5717 additions and 193 deletions

View File

@@ -0,0 +1,70 @@
import EvolutionWorker from './evolution.worker?worker';
import type { Population, Individual } from './evolution';
import type { EvolutionConfig } from './types';
export class WorkerPool {
private workers: Worker[] = [];
private poolSize: number;
constructor(size: number = navigator.hardwareConcurrency || 4) {
this.poolSize = size;
for (let i = 0; i < size; i++) {
this.workers.push(new EvolutionWorker());
}
}
terminate() {
this.workers.forEach(w => w.terminate());
this.workers = [];
}
async evaluateParallel(population: Population, config: EvolutionConfig): Promise<Population> {
// Split individuals into chunks
const chunkSize = Math.ceil(population.individuals.length / this.poolSize);
const chunks: Individual[][] = [];
for (let i = 0; i < population.individuals.length; i += chunkSize) {
chunks.push(population.individuals.slice(i, i + chunkSize));
}
// Dispatch chunks to workers
const promises = chunks.map((chunk, index) => {
return new Promise<Individual[]>((resolve, reject) => {
const worker = this.workers[index];
// One-time listener for this request
const handler = (e: MessageEvent) => {
if (e.data.type === 'EVAL_RESULT') {
worker.removeEventListener('message', handler);
resolve(e.data.payload);
} else if (e.data.type === 'ERROR') {
worker.removeEventListener('message', handler);
reject(e.data.payload);
}
};
worker.addEventListener('message', handler);
worker.postMessage({
type: 'EVALUATE_ONLY',
payload: {
individuals: chunk,
config
}
});
});
});
// Wait for all chunks
const results = await Promise.all(promises);
// Merge results
const mergedIndividuals = results.flat();
// Reconstruct population with evaluated individuals
return {
...population,
individuals: mergedIndividuals
};
}
}