From 444b2b5abfbb70473b0785b38eaba1df4197ae69 Mon Sep 17 00:00:00 2001 From: sanine Date: Sun, 12 Nov 2023 05:17:19 -0600 Subject: refactor genome to include size information --- src/genome/genome.js | 95 +++++++++++++++++++++------------------------------- 1 file changed, 39 insertions(+), 56 deletions(-) (limited to 'src/genome/genome.js') diff --git a/src/genome/genome.js b/src/genome/genome.js index bc569ff..20974fc 100644 --- a/src/genome/genome.js +++ b/src/genome/genome.js @@ -5,38 +5,25 @@ import { network } from '../mind/topology.js'; // check if a given genome is valid and compute its size -export function get_size(num_input, num_output, genome) { - const [ max_index, max_weight ] = genome.reduce( - ([max_index, max_weight ], [ source, sink, weight]) => [ - Math.max(max_index, source, sink), - Math.max(max_weight, Math.abs(weight)), - ], - [ 0, 0 ] +export function validate_genome(genome) { + const { n_input, n_internal, n_output } = genome; + console.log(n_input + n_internal); + return genome.genes.reduce( + (acc, [source, sink, weight]) => acc && ( + (source < n_input+n_internal) && + (sink >= n_input) + ), + true ); - - if (max_index < num_input + num_output - 1) { - return -1; - } - else if (max_weight > 4.0) { - return -1; - } - else { - return max_index + 1; - } } - // parse a genome into a useable neural net -export function parse_genome(num_input, num_output, genome) { - const size = get_size(num_input, num_output, genome); - if (size < 0) { - // bad genome - throw new Error('invalid genome sequence!'); - } +export function parse_genome(genome) { + const { n_input, n_internal, n_output } = genome; - const n = genome.reduce( + const n = genome.genes.reduce( (acc, [source, sink, weight]) => acc.connect(source, sink, weight), - network(num_input, size-num_input-num_output, num_output) + network(n_input, n_internal, n_output) ); return n; @@ -100,27 +87,26 @@ export function mut_gene_weight(weight_max, gene, r) { // expand the size of the neural net encoded by the genome // relabels internal indices so that there is one extra internal neuron -export function mut_genome_expand( - [n_input, n_internal, n_output, genome], r -) { - const expand_index = Math.floor(n_internal * r) + n_input; - const new_genome = genome.map(([source, sink, weight]) => [ +export function mut_genome_expand(genome, r) { + const expand_index = Math.floor(genome.n_internal * r) + genome.n_input; + const new_genes = genome.genes.map(([source, sink, weight]) => [ source >= expand_index ? source+1 : source, sink >= expand_index ? sink+1 : sink, weight, ]); - return [ - n_input, n_internal+1, n_output, new_genome, - ]; + return { + ...genome, + n_internal: genome.n_internal+1, + genes: new_genes, + }; } // contract the size of the neural net encoded by the genome // relabels internal indices so that there is one less internal neuron -export function mut_genome_contract( - [n_input, n_internal, n_output, genome], r -) { +export function mut_genome_contract(genome, r) { + const { n_input, n_internal, n_output } = genome; const contract_idx = Math.floor(n_internal * r) + n_input; // decrement sources on the contract index too, to prevent invalid genomes @@ -128,42 +114,39 @@ export function mut_genome_contract( // decrement sinks only after the contract index const new_sink = (sink) => sink > contract_idx ? sink-1 : sink; - const new_genome = genome.map(([source, sink, weight]) => [ + const new_genes = genome.genes.map(([source, sink, weight]) => [ new_source(source), new_sink(sink), weight, ]); - return [ - n_input, n_internal-1, n_output, new_genome - ]; + return { + ...genome, + n_internal: n_internal-1, + genes: new_genes, + }; } // append a newly generated gene to the end of the genome -export function mut_genome_insert( - [n_input, n_internal, n_output, genome], - weight_max, - r1, r2, r3 -) { +export function mut_genome_insert(genome, weight_max, r1=Math.random(), r2=Math.random(), r3=Math.random()) { + const { n_input, n_internal, n_output } = genome; const source = Math.floor((n_input + n_internal) * r1); const sink = Math.floor((n_internal + n_output) * r2) + n_input; const weight = weight_max * ((2*r3)-1); - return [ - n_input, n_internal, n_output, - [...genome, [source, sink, weight]], - ]; + return { + ...genome, + genes: [...genome.genes, [source, sink, weight]], + }; } // delete a gene from the genome -export function mut_genome_delete( - [n_input, n_internal, n_output, genome], r -) { - const del_idx = Math.floor(r * genome.length); - const new_genome = genome.filter((_, idx) => idx != del_idx); - return [n_input, n_internal, n_output, new_genome]; +export function mut_genome_delete(genome, r) { + const del_idx = Math.floor(r * genome.genes.length); + const genes = genome.genes.filter((_, idx) => idx != del_idx); + return { ...genome, genes }; } -- cgit v1.2.1