diff --git a/src/site/snake/brain-neat.ts b/src/site/snake/brain-neat.ts index dff28ab..7db3b3e 100644 --- a/src/site/snake/brain-neat.ts +++ b/src/site/snake/brain-neat.ts @@ -382,11 +382,11 @@ export function chooseSurvivors(population: Population, fitness: Map) { ... } interface CrossConfig { - reenable_rate: number; + reenable_rate: number; } export function crossGenomes(mom: Genome, dad: Genome, fitness: Map, config: CrossConfig) { - const { reenable_rate } = config; - - const alignment = alignGenomes(mom, dad); + const { reenable_rate } = config; + + const alignment = alignGenomes(mom, dad); + + const crossed: Genome = []; + + // matching + for (const { mom: momGene, dad: dadGene } of alignment.matching) { + const newWeight = Math.random() < 0.5 ? momGene.data.weight : dadGene.data.weight; + const wasDisabled = !momGene.data.enabled || !dadGene.data.enabled; + const newEnabled = !wasDisabled || Math.random() < reenable_rate; + const newGene = { ...momGene, data: { ...momGene.data, weight: newWeight, enabled: newEnabled } }; + crossed.push(newGene); + } + + // disjoint + const momFitness = fitness.get(mom)!; + const dadFitness = fitness.get(dad)!; + const mostFit = momFitness === dadFitness ? 'equal' : momFitness > dadFitness ? 'mom' : 'dad'; + for (const { mom: momGene, dad: dadGene } of alignment.disjoint) { + if (momGene === null) crossed.push(dadGene as Gene); + else if (dadGene === null) crossed.push(momGene); + else if (mostFit === 'mom') crossed.push(momGene); + else if (mostFit === 'dad') crossed.push(dadGene); + // both are equally fit - select at random + else if (Math.random() < 0.5) crossed.push(momGene); + else crossed.push(dadGene); + } + + // excess + for (const { mom: momGene, dad: dadGene } of alignment.excess) { + if (momGene === null) crossed.push(dadGene as Gene); + else if (dadGene === null) crossed.push(momGene as Gene); + else throw Error(`invalid excess alignment: alignment=${JSON.stringify(alignment)}`); + } + + return crossed; } export function mutateAssign(gene: Gene, newWeight: number): Gene {