summaryrefslogtreecommitdiff
path: root/src/genome/genome.js
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2023-11-12 05:17:19 -0600
committersanine <sanine.not@pm.me>2023-11-12 05:17:19 -0600
commit444b2b5abfbb70473b0785b38eaba1df4197ae69 (patch)
tree98eeb63082c679f8944c740f466c1e56aef24aad /src/genome/genome.js
parente3a042a7a5c041dad63255965576346377e4f823 (diff)
refactor genome to include size information
Diffstat (limited to 'src/genome/genome.js')
-rw-r--r--src/genome/genome.js95
1 files changed, 39 insertions, 56 deletions
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 };
}