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

View File

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