NEATBrain

This commit is contained in:
Michael Peters 2024-08-28 21:12:32 -07:00
parent 74eb95364e
commit 52691ff9c0
2 changed files with 11 additions and 12 deletions

View File

@ -419,7 +419,6 @@ export function chooseMate(genome: Genome, population: Population, config: MateC
return genome;
}
// TODO: function crossGenomes(mom: Genome, dad: Genome, fitness: Map<Genome, number>) { ... }
interface CrossConfig {
reenable_rate: number;
}
@ -600,7 +599,7 @@ export function activate(n: number) {
return 1 / (1 + Math.exp(-4.9 * n));
}
export class Organism {
export class NEATBrain {
genome: Genome;
network: Network<Node<GeneData>>;
order: NodeID[];
@ -614,7 +613,7 @@ export class Organism {
static fromGenome(genome: Genome) {
const network = edgesToNodes(genome);
const order = topoSort(network);
return new Organism(genome, network, order);
return new NEATBrain(genome, network, order);
}
/** given per-node input activations, computes downstream activations in-place.*/

View File

@ -12,7 +12,7 @@ import {
mutateNewConn,
mutateNewNode,
mutatePerturb,
Organism,
NEATBrain,
Population,
resetGlobalIDs,
} from '../site/snake/brain-neat';
@ -191,7 +191,7 @@ function testChooseSurvivors() {
fitness.set(genomeF, 1); // adj = 1/1 = 1.00
// (1 - 4/6) = 2/6 survive by fitness alone
// top organism (champion) from all species with at least 3 organisms should always survive
// 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);
@ -274,17 +274,17 @@ function testCrossGenomes() {
assert(crossed[0]!.data.enabled === true);
assert(crossed[1]!.data.innovation === 2);
assert(crossed[1]!.data.weight === 0 || crossed[0]!.data.weight === 1);
assert(crossed[1]!.data.weight === 0 || crossed[1]!.data.weight === 1);
assert(crossed[1]!.data.enabled === true); // always re-enabled insce reenable_rate=1
assert(crossed[2]!.data.innovation === 3);
assert(crossed[2]!.data.weight === 3 || crossed[0]!.data.weight === 2);
assert(crossed[2]!.data.weight === 3 || crossed[2]!.data.weight === 2);
assert(crossed[3]!.data.innovation === 4);
assert(crossed[3]!.data.weight === 9);
assert(crossed[4]!.data.innovation === 5);
assert(crossed[4]!.data.weight === 5 || crossed[0]!.data.weight === 3);
assert(crossed[4]!.data.weight === 5 || crossed[4]!.data.weight === 3);
assert(crossed[4]!.data.enabled === true); // always re-enabled since reenable_rate = 1
// disjoint
@ -398,7 +398,7 @@ function testFindAcyclicNewConns() {
}
addTest(testFindAcyclicNewConns);
function testOrganismThink() {
function testNEATBrainThink() {
const genome = [
{ src_id: 'A', dst_id: 'C', data: { innovation: 1, weight: 0.3, enabled: true } },
{ src_id: 'B', dst_id: 'C', data: { innovation: 2, weight: 0.5, enabled: false } },
@ -416,13 +416,13 @@ function testOrganismThink() {
activations.set('A', expectedA);
activations.set('B', expectedB);
const organism = Organism.fromGenome(genome);
const brain = NEATBrain.fromGenome(genome);
organism.think(activations);
brain.think(activations);
assert(activations.get('A')! === expectedA);
assert(activations.get('B')! === expectedB);
assert(activations.get('C')! === expectedC);
assert(activations.get('D')! === expectedD);
}
addTest(testOrganismThink);
addTest(testNEATBrainThink);