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;
|
return survivors;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BreedingConfig {
|
interface MateChoiceConfig {
|
||||||
asexual_rate: number;
|
asexual_rate: number;
|
||||||
interspecies_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;
|
const { asexual_rate, interspecies_rate } = config;
|
||||||
|
|
||||||
if (Math.random() < asexual_rate) return genome;
|
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>) { ... }
|
// TODO: function crossGenomes(mom: Genome, dad: Genome, fitness: Map<Genome, number>) { ... }
|
||||||
interface CrossConfig {
|
interface CrossConfig {
|
||||||
reenable_rate: number;
|
reenable_rate: number;
|
||||||
}
|
}
|
||||||
export function crossGenomes(mom: Genome, dad: Genome, fitness: Map<Genome, number>, config: CrossConfig) {
|
export function crossGenomes(mom: Genome, dad: Genome, fitness: Map<Genome, number>, config: CrossConfig) {
|
||||||
const { reenable_rate } = config;
|
const { reenable_rate } = config;
|
||||||
|
|
||||||
const alignment = alignGenomes(mom, dad);
|
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 {
|
export function mutateAssign(gene: Gene, newWeight: number): Gene {
|
||||||
|
Loading…
Reference in New Issue
Block a user