generated from michael/webpack-base
NEATBrain
This commit is contained in:
parent
74eb95364e
commit
52691ff9c0
@ -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.*/
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user