From 6aae1f6fb4cf289ecf5ed318b34c0e7df62bbf83 Mon Sep 17 00:00:00 2001 From: sanine-a Date: Tue, 1 Aug 2023 17:03:28 -0500 Subject: add mutation_type and mutate() --- package.json | 3 ++- src/genome/genome.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++ src/genome/genome.test.js | 20 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/genome/genome.js create mode 100644 src/genome/genome.test.js diff --git a/package.json b/package.json index d4ad737..2621654 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,8 @@ "jest": "^29.5.0" }, "scripts": { - "test": "NODE_OPTIONS=--experimental-vm-modules jest" + "test": "NODE_OPTIONS=--experimental-vm-modules jest", + "wtest": "test.bat" }, "type": "module" } diff --git a/src/genome/genome.js b/src/genome/genome.js new file mode 100644 index 0000000..16de162 --- /dev/null +++ b/src/genome/genome.js @@ -0,0 +1,49 @@ +'use strict'; + + +export const mutation_type = Object.freeze({ + none: 'none', + source: 'source', + sink: 'sink', + weight: 'weight', +}); + + +function positive(x) { + if (x < 0) { + return 0; + } else { + return x; + } +} + + +export function mutate(gene, type, value) { + const [ source, sink, weight ] = gene; + + switch(type) { + case mutation_type.none: + return [...gene]; + + case mutation_type.source: + if (value <= 0.5) { + return [ positive(source-1), sink, weight ]; + } else { + return [ source+1, sink, weight ]; + } + + case mutation_type.sink: + if (value <= 0.5) { + return [ source, positive(sink-1), weight ]; + } else { + return [ source, sink+1, weight ]; + } + + case mutation_type.weight: + const w = (8*value) - 4; + return [ source, sink, w ]; + + default: + throw new Error(`unknown mutation type: '${type}'`); + }; +} diff --git a/src/genome/genome.test.js b/src/genome/genome.test.js new file mode 100644 index 0000000..853d103 --- /dev/null +++ b/src/genome/genome.test.js @@ -0,0 +1,20 @@ +'use strict'; + +import { mutation_type, mutate } from './genome'; + + +test('basic gene mutations', () => { + expect(mutate([0, 1, 2], mutation_type.none, 0)).toEqual([0, 1, 2]); + + expect(mutate([0, 1, 2], mutation_type.source, 0.2)).toEqual([0, 1, 2]); + expect(mutate([1, 1, 2], mutation_type.source, 0.2)).toEqual([0, 1, 2]); + expect(mutate([0, 1, 2], mutation_type.source, 0.8)).toEqual([1, 1, 2]); + + expect(mutate([0, 1, 2], mutation_type.sink, 0.2)).toEqual([0, 0, 2]); + expect(mutate([0, 1, 2], mutation_type.sink, 0.8)).toEqual([0, 2, 2]); + expect(mutate([0, 0, 2], mutation_type.sink, 0.2)).toEqual([0, 0, 2]); + + expect(mutate([0, 1, 2], mutation_type.weight, 0.5)).toEqual([0, 1, 0]); + expect(mutate([0, 1, 2], mutation_type.weight, 0.0)).toEqual([0, 1, -4]); + expect(mutate([0, 1, 2], mutation_type.weight, 1.0)).toEqual([0, 1, 4]); +}); -- cgit v1.2.1