const activation = require('./activation');
/**
*
* Genetic algorithm mutation methods. Creates variations (mutations) in neural networks which are then selected for better performance.
*
* @namespace mutation
*
* @see {@link https://en.wikipedia.org/wiki/mutation_(genetic_algorithm)|Mutation (genetic algorithms) on Wikipedia}
* @see {@link https://en.wikipedia.org/wiki/Genetic_algorithm#Selection|Selection (genetic algorithms) on Wikipedia}
*
* @example <caption>Mutation methods with networks</caption>
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* // Setting a mutation method for a network
* myNetwork.mutate(methods.mutation.ADD_NODE);
*
* // specifying a list of network mutation methods to use during evolution
* myNetwork.evolve(trainingset, {
* mutation: [methods.mutation.MOD_BIAS, methods.mutation.ADD_NODE]
* }
*
* @example <caption>Using a mutation method with a neuron</caption>
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNode.mutate(methods.mutation.MOD_BIAS);
*/
const mutation = {
/**
* @constant
* @type {object}
* @description Adds a node
* @default
*
* @prop {boolean} randomActivation=true If enabled, sets a random activation function on the newly created node
*
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNetwork.mutate(methods.mutation.ADD_NODE);
*/
ADD_NODE: {
name: 'ADD_NODE',
randomActivation: true,
},
/**
* @constant
* @type {object}
* @description Removes a node
* @default
*
* @prop {boolean} keep_gates=true Ensures replacement node has gated connections if the removed node did.
*
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNetwork.mutate(methods.mutation.SUB_NODE);
*/
SUB_NODE: {
name: 'SUB_NODE',
keep_gates: true,
},
/**
* @constant
* @type {object}
* @description Adds a connection between two nodes
* @default
*
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNetwork.mutate(methods.mutation.ADD_CONN);
*/
ADD_CONN: {
name: 'ADD_CONN',
},
/**
* @constant
* @type {object}
* @description Removes a connection between two nodes
* @default
*
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNetwork.mutate(methods.mutation.SUB_CONN);
*/
SUB_CONN: {
name: 'REMOVE_CONN',
},
/**
* @constant
* @type {object}
* @description Modifies the weight of a connection
* @default
*
* @prop {number} min=-1 lower bound for weight modification
* @prop {number} max=1 higher bound for weight modification
*
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNetwork.mutate(methods.mutation.MOD_WEIGHT);
*/
MOD_WEIGHT: {
name: 'MOD_WEIGHT',
min: -1,
max: 1,
},
/**
* @constant
* @type {object}
* @description Modifies the bias of a node
* @default
*
* @prop {number} min=-1 lower bound for modification of a neuron's bias
* @prop {number} max=1 higher bound for modification of a neuron's bias
*
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* let myNode = new Node();
*
* myNode.mutate(methods.mutation.MOD_BIAS);
*/
MOD_BIAS: {
name: 'MOD_BIAS',
min: -1,
max: 1,
},
/**
* @constant
* @type {object}
* @description Modifies the activation function of a node by randomly picking from the allowed activation methods
* @default
*
* @prop {boolean} mutateOutput=false Change activation function of network output neurons. Enable this to let the network experiment with its output.
* @prop {activation[]} [allowed=[all built-in activation methods]] Mutation methods to randomly select from when mutating
*
* @example <caption>Mutating the activation function of a node</caption>
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* let myNode = new Node();
*
* myNode.mutate(methods.mutation.MOD_ACTIVATION);
*
* @example <caption>Mutating the activation function of a network's nodes</caption>
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* let myNode = new Node();
*
* myNode.mutate(methods.mutation.MOD_ACTIVATION);
*/
MOD_ACTIVATION: {
name: 'MOD_ACTIVATION',
mutateOutput: false,
allowed: [
activation.LOGISTIC,
activation.TANH,
activation.RELU,
activation.IDENTITY,
activation.STEP,
activation.SOFTSIGN,
activation.SINUSOID,
activation.GAUSSIAN,
activation.BENT_IDENTITY,
activation.BIPOLAR,
activation.BIPOLAR_SIGMOID,
activation.HARD_TANH,
activation.ABSOLUTE,
activation.INVERSE,
activation.SELU,
],
},
/**
* @constant
* @type {object}
* @description Adds a self-connection to a node
* @default
*
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNetwork.mutate(methods.mutation.ADD_SELF_CONN);
*/
ADD_SELF_CONN: {
name: 'ADD_SELF_CONN',
},
/**
* @constant
* @type {object}
* @description Removes a self-connection from a node
* @default
*
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNetwork.mutate(methods.mutation.SUB_SELF_CONN);
*/
SUB_SELF_CONN: {
name: 'SUB_SELF_CONN',
},
/**
* @constant
* @type {object}
* @description Makes a node gate a connection
* @default
*
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNetwork.mutate(methods.mutation.ADD_GATE);
*/
ADD_GATE: {
name: 'ADD_GATE',
},
/**
* @constant
* @type {object}
* @description Removes a gate from a connection
* @default
*
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNetwork.mutate(methods.mutation.SUB_GATE);
*/
SUB_GATE: {
name: 'SUB_GATE',
},
/**
* @constant
* @type {object}
* @description Adds a recurrent connection
* @default
*
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNetwork.mutate(methods.mutation.ADD_BACK_CONN);
*/
ADD_BACK_CONN: {
name: 'ADD_BACK_CONN',
},
/**
* @constant
* @type {object}
* @description Removes a recurrent connection
* @default
*
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNetwork.mutate(methods.mutation.SUB_BACK_CONN);
*/
SUB_BACK_CONN: {
name: 'SUB_BACK_CONN',
},
/**
* @constant
* @type {object}
* @description Swaps the bias and squash function between two nodes
* @default
*
* @prop {boolean} mutateOutput=false Swap bias and activation function of network output neurons too. Disable this to keep output of a neural network normalized.
* @example
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* myNetwork.mutate(methods.mutation.SWAP_NODES);
*/
SWAP_NODES: {
name: 'SWAP_NODES',
mutateOutput: false,
},
};
/**
*
* Array of all mutation methods
*
* @constant
* @type {array}
* @default
*
* @example <caption>A group of mutation methods for evolution</caption>
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* network.evolve(trainingset, {
* mutation: methods.mutation.ALL // all mutation methods
* }
*/
mutation.ALL = [
mutation.ADD_NODE,
mutation.SUB_NODE,
mutation.ADD_CONN,
mutation.SUB_CONN,
mutation.MOD_WEIGHT,
mutation.MOD_BIAS,
mutation.MOD_ACTIVATION,
mutation.ADD_GATE,
mutation.SUB_GATE,
mutation.ADD_SELF_CONN,
mutation.SUB_SELF_CONN,
mutation.ADD_BACK_CONN,
mutation.SUB_BACK_CONN,
mutation.SWAP_NODES,
];
/**
*
* Array of all feedforwad mutation methods
*
* @constant
* @type {array}
* @default
*
* @example <caption>A group of mutation methods for evolution</caption>
* let { methods, Network } = require("@liquid-carrot/carrot");
*
* let myNetwork = new Network(5, 10, 5);
*
* network.evolve(trainingset, {
* mutation: methods.mutation.FFW// all feedforward mutation methods
* }
*/
mutation.FFW = [
mutation.ADD_NODE,
mutation.SUB_NODE,
mutation.ADD_CONN,
mutation.SUB_CONN,
mutation.MOD_WEIGHT,
mutation.MOD_BIAS,
mutation.MOD_ACTIVATION,
mutation.SWAP_NODES,
];
module.exports = mutation;