generated from michael/webpack-base
add crossGenomes implementation
This commit is contained in:
parent
566759e781
commit
465ac4b9dd
@ -382,11 +382,11 @@ export function chooseSurvivors(population: Population, fitness: Map<Genome, num
|
||||
return survivors;
|
||||
}
|
||||
|
||||
interface BreedingConfig {
|
||||
interface MateChoiceConfig {
|
||||
asexual_rate: number;
|
||||
interspecies_rate: number;
|
||||
}
|
||||
export function chooseMate(genome: Genome, population: Population, config: BreedingConfig) {
|
||||
export function chooseMate(genome: Genome, population: Population, config: MateChoiceConfig) {
|
||||
const { asexual_rate, interspecies_rate } = config;
|
||||
|
||||
if (Math.random() < asexual_rate) return genome;
|
||||
@ -421,12 +421,46 @@ export function chooseMate(genome: Genome, population: Population, config: Breed
|
||||
|
||||
// TODO: function crossGenomes(mom: Genome, dad: Genome, fitness: Map<Genome, number>) { ... }
|
||||
interface CrossConfig {
|
||||
reenable_rate: number;
|
||||
reenable_rate: number;
|
||||
}
|
||||
export function crossGenomes(mom: Genome, dad: Genome, fitness: Map<Genome, number>, 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user