generated from michael/webpack-base
adjust chooseSurvivors -> chooseByFertility to also give the champions
This commit is contained in:
parent
21bf8f781e
commit
4d2e5b4b44
@ -348,12 +348,12 @@ export function initialSpeciate(
|
||||
return population;
|
||||
}
|
||||
|
||||
interface SurvivorsConfig {
|
||||
survival_threshold: number;
|
||||
interface FertilityConfig {
|
||||
fertile_threshold: number;
|
||||
champion_min_species_size: number;
|
||||
}
|
||||
export function chooseSurvivors(population: Population, fitness: Map<Genome, number>, config: SurvivorsConfig) {
|
||||
const { survival_threshold, champion_min_species_size } = config;
|
||||
export function chooseByFertility(population: Population, fitness: Map<Genome, number>, config: FertilityConfig) {
|
||||
const { fertile_threshold, champion_min_species_size } = config;
|
||||
|
||||
const species = mapInvert(population);
|
||||
|
||||
@ -364,22 +364,22 @@ export function chooseSurvivors(population: Population, fitness: Map<Genome, num
|
||||
return [k, v / speciesSize];
|
||||
});
|
||||
|
||||
const survivors = new Set<Genome>();
|
||||
const fertile = new Set<Genome>();
|
||||
|
||||
// add sufficiently fit organisms
|
||||
const genomes: Genome[] = Array.from(population.keys());
|
||||
const survival_idx = Math.floor(genomes.length * survival_threshold);
|
||||
const survival_idx = Math.floor(genomes.length * fertile_threshold);
|
||||
genomes.sort((a, b) => adjFitness.get(a)! - adjFitness.get(b)!);
|
||||
genomes.slice(survival_idx).forEach(o => survivors.add(o));
|
||||
genomes.slice(survival_idx).forEach(o => fertile.add(o));
|
||||
|
||||
// add species champions
|
||||
const champions = mapMap(species, (k, v) => [k, keyMax(v, o => adjFitness.get(o)!)]);
|
||||
for (const [sid, c] of champions.entries()) {
|
||||
if (species.get(sid)!.size < champion_min_species_size) continue;
|
||||
survivors.add(c);
|
||||
fertile.add(c);
|
||||
}
|
||||
|
||||
return survivors;
|
||||
return { fertile, champions };
|
||||
}
|
||||
|
||||
interface MateChoiceConfig {
|
||||
@ -594,6 +594,26 @@ export function mutate(genome: Genome, config: MutateConfig): Genome {
|
||||
return newGenome;
|
||||
}
|
||||
|
||||
interface NextGenerationConfig {
|
||||
fc: FertilityConfig;
|
||||
}
|
||||
export function computeNextGeneration(
|
||||
population: Population,
|
||||
fitness: Map<Genome, number>,
|
||||
config: NextGenerationConfig,
|
||||
) {
|
||||
const { fc } = config;
|
||||
|
||||
const { fertile, champions } = chooseByFertility(population, fitness, fc);
|
||||
|
||||
// TODO: only copy over champions, the rest mate to produce the population
|
||||
const nextGeneration = new Map(Array.from(fertile).map(s => [s, population.get(s)!]));
|
||||
const species = mapInvert(nextGeneration);
|
||||
const reps = mapMap(species, (sid, genomes) => [sid, genomes.values().next().value]);
|
||||
|
||||
// TODO: update chooseSurvivors so champions get copied over
|
||||
}
|
||||
|
||||
export function activate(n: number) {
|
||||
// modified sigmoid function from NEAT paper
|
||||
return 1 / (1 + Math.exp(-4.9 * n));
|
||||
|
@ -2,7 +2,7 @@ import {
|
||||
activate,
|
||||
alignGenomes,
|
||||
chooseMate,
|
||||
chooseSurvivors,
|
||||
chooseByFertility,
|
||||
compatibilityDistance,
|
||||
crossGenomes,
|
||||
findAcyclicNewConns,
|
||||
@ -192,11 +192,11 @@ function testChooseSurvivors() {
|
||||
|
||||
// (1 - 4/6) = 2/6 survive by fitness alone
|
||||
// top genome (champion) from all species with at least 3 genomes should always survive
|
||||
const sc = { survival_threshold: 4 / 6, champion_min_species_size: 3 };
|
||||
const survivors = chooseSurvivors(population, fitness, sc);
|
||||
const sc = { fertile_threshold: 4 / 6, champion_min_species_size: 3 };
|
||||
const { fertile, champions } = chooseByFertility(population, fitness, sc);
|
||||
|
||||
assertSetEqual(
|
||||
survivors,
|
||||
fertile,
|
||||
new Set([
|
||||
genomeB, // champion of species 1
|
||||
genomeD, // #2 fitness
|
||||
@ -204,6 +204,10 @@ function testChooseSurvivors() {
|
||||
// genomeF not included since species is not large enough to have a champion
|
||||
]),
|
||||
);
|
||||
assert(champions.size === 3);
|
||||
assert(champions.get(1)! === genomeB);
|
||||
assert(champions.get(2)! === genomeE);
|
||||
assert(champions.get(3)! === genomeF);
|
||||
}
|
||||
addTest(testChooseSurvivors);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user