From 985e7a27c3c551e9bc7b80252d8af26992702c76 Mon Sep 17 00:00:00 2001 From: Manuel Raimann Date: Fri, 10 Apr 2020 23:43:07 +0200 Subject: [PATCH 1/3] adding output to input connections in Hopfield network --- src/architecture/architect.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/architecture/architect.js b/src/architecture/architect.js index 06a6c6d60..5b51aef6e 100644 --- a/src/architecture/architect.js +++ b/src/architecture/architect.js @@ -489,6 +489,7 @@ const architect = { const output = new Group(size, 'output'); input.connect(output, methods.connection.ALL_TO_ALL); + output.connect(input, methods.connection.ALL_TO_ALL); output.set({ squash: methods.activation.STEP, From 5379083cccffcd8ed4a821c6f4a69effa9f62d08 Mon Sep 17 00:00:00 2001 From: Manuel Raimann Date: Fri, 10 Apr 2020 23:54:03 +0200 Subject: [PATCH 2/3] renaming ALL_TO_ALL to ALL_TO_ALL_FORWARD --- src/architecture/group.js | 8 +++--- src/architecture/layer.js | 32 +++++++++++------------ src/architecture/layer.js.old | 28 ++++++++++---------- src/methods/connection.js | 8 +++--- test/units/architecture/group.test.js | 10 +++---- test/units/architecture/layer.test.js | 14 +++++----- test/units/architecture/layer.test.js.old | 10 +++---- 7 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/architecture/group.js b/src/architecture/group.js index 1be750017..c505b7d57 100644 --- a/src/architecture/group.js +++ b/src/architecture/group.js @@ -135,7 +135,7 @@ function Group(size) { * let A = new Group(4); * let B = new Group(5); * - * A.connect(B, methods.connection.ALL_TO_ALL); // specifying a method is optional + * A.connect(B, methods.connection.ALL_TO_ALL_FORWARD); // specifying a method is optional */ self.connect = function(target, method, weight) { const self_targeted = target.nodes ? self.nodes == target.nodes : false; @@ -147,8 +147,8 @@ function Group(size) { if (config.warnings) console.warn('No group connection specified, using ONE_TO_ONE'); method = methods.connection.ONE_TO_ONE; } else { - if (config.warnings) console.warn('No group connection specified, using ALL_TO_ALL'); - method = methods.connection.ALL_TO_ALL; + if (config.warnings) console.warn('No group connection specified, using ALL_TO_ALL_FORWARD'); + method = methods.connection.ALL_TO_ALL_FORWARD; } } @@ -193,7 +193,7 @@ function Group(size) { const connection = source_nodes[i].connect(target_nodes[i], weight); new_connections.push(connection); } - // else (ALL_TO_ELSE or ALL_TO_ALL) + // else (ALL_TO_ELSE or ALL_TO_ALL_FORWARD) else { for (let j = 0; j < source_nodes.length; j++) { // create the connection diff --git a/src/architecture/layer.js b/src/architecture/layer.js index 29f0b38e6..d74113bc7 100644 --- a/src/architecture/layer.js +++ b/src/architecture/layer.js @@ -107,16 +107,16 @@ class Layer extends Group { }); // Set up internal connections - memory_cell.connect(input_gate, methods.connection.ALL_TO_ALL); - memory_cell.connect(forget_gate, methods.connection.ALL_TO_ALL); - memory_cell.connect(output_gate, methods.connection.ALL_TO_ALL); + memory_cell.connect(input_gate, methods.connection.ALL_TO_ALL_FORWARD); + memory_cell.connect(forget_gate, methods.connection.ALL_TO_ALL_FORWARD); + memory_cell.connect(output_gate, methods.connection.ALL_TO_ALL_FORWARD); const forget_connections = memory_cell.connect(memory_cell, methods.connection.ONE_TO_ONE); - const output_connections = memory_cell.connect(output_block, methods.connection.ALL_TO_ALL); + const output_connections = memory_cell.connect(output_block, methods.connection.ALL_TO_ALL_FORWARD); - input_group.connect(memory_cell, methods.connection.ALL_TO_ALL); - input_group.connect(output_gate, methods.connection.ALL_TO_ALL), - input_group.connect(forget_gate, methods.connection.ALL_TO_ALL); - const input_gate_connections = input_group.connect(input_gate, methods.connection.ALL_TO_ALL); + input_group.connect(memory_cell, methods.connection.ALL_TO_ALL_FORWARD); + input_group.connect(output_gate, methods.connection.ALL_TO_ALL_FORWARD), + input_group.connect(forget_gate, methods.connection.ALL_TO_ALL_FORWARD); + const input_gate_connections = input_group.connect(input_gate, methods.connection.ALL_TO_ALL_FORWARD); // Set up gates @@ -186,27 +186,27 @@ class Layer extends Group { }); // Initial input forwarding - input_group.connect(update_gate, methods.connection.ALL_TO_ALL), - input_group.connect(reset_gate, methods.connection.ALL_TO_ALL), - input_group.connect(memory_cell, methods.connection.ALL_TO_ALL); + input_group.connect(update_gate, methods.connection.ALL_TO_ALL_FORWARD), + input_group.connect(reset_gate, methods.connection.ALL_TO_ALL_FORWARD), + input_group.connect(memory_cell, methods.connection.ALL_TO_ALL_FORWARD); // Update gate calculation - previous_output.connect(update_gate, methods.connection.ALL_TO_ALL); + previous_output.connect(update_gate, methods.connection.ALL_TO_ALL_FORWARD); // Inverse update gate calculation update_gate.connect(inverse_update_gate, methods.connection.ONE_TO_ONE, 1); // Reset gate calculation - previous_output.connect(reset_gate, methods.connection.ALL_TO_ALL); + previous_output.connect(reset_gate, methods.connection.ALL_TO_ALL_FORWARD); // Memory calculation - const reset = previous_output.connect(memory_cell, methods.connection.ALL_TO_ALL); + const reset = previous_output.connect(memory_cell, methods.connection.ALL_TO_ALL_FORWARD); reset_gate.gate(reset, methods.gating.OUTPUT); // gate // Output calculation - const update1 = previous_output.connect(output_group, methods.connection.ALL_TO_ALL); - const update2 = memory_cell.connect(output_group, methods.connection.ALL_TO_ALL); + const update1 = previous_output.connect(output_group, methods.connection.ALL_TO_ALL_FORWARD); + const update2 = memory_cell.connect(output_group, methods.connection.ALL_TO_ALL_FORWARD); update_gate.gate(update1, methods.gating.OUTPUT); inverse_update_gate.gate(update2, methods.gating.OUTPUT); diff --git a/src/architecture/layer.js.old b/src/architecture/layer.js.old index 65ca4f950..762e1cf69 100644 --- a/src/architecture/layer.js.old +++ b/src/architecture/layer.js.old @@ -196,7 +196,7 @@ function Layer() { self.input = function(from, method, weight) { if(from instanceof Layer) from = from.output; - method = method || methods.connection.ALL_TO_ALL; + method = method || methods.connection.ALL_TO_ALL_FORWARD; return from.connect(block, method, weight); }; @@ -230,7 +230,7 @@ Layer.Dense = function(size) { layer.input = function(from, method, weight) { if(from instanceof Layer) from = from.output; - method = method || methods.connection.ALL_TO_ALL; + method = method || methods.connection.ALL_TO_ALL_FORWARD; let returned_connections = []; // this if was added later because .from was being called @@ -287,11 +287,11 @@ Layer.LSTM = function(size) { }); // Set up internal connections - memory_cell.connect(input_gate, methods.connection.ALL_TO_ALL); - memory_cell.connect(forget_gate, methods.connection.ALL_TO_ALL); - memory_cell.connect(output_gate, methods.connection.ALL_TO_ALL); + memory_cell.connect(input_gate, methods.connection.ALL_TO_ALL_FORWARD); + memory_cell.connect(forget_gate, methods.connection.ALL_TO_ALL_FORWARD); + memory_cell.connect(output_gate, methods.connection.ALL_TO_ALL_FORWARD); const forget = memory_cell.connect(memory_cell, methods.connection.ONE_TO_ONE); - const output = memory_cell.connect(output_block, methods.connection.ALL_TO_ALL); + const output = memory_cell.connect(output_block, methods.connection.ALL_TO_ALL_FORWARD); // Set up gates forget_gate.gate(forget, methods.gating.SELF); @@ -305,7 +305,7 @@ Layer.LSTM = function(size) { layer.input = function(from, method, weight) { if(from instanceof Layer) from = from.output; - method = method || methods.connection.ALL_TO_ALL; + method = method || methods.connection.ALL_TO_ALL_FORWARD; const input = from.connect(memory_cell, method, weight); @@ -370,22 +370,22 @@ Layer.GRU = function(size) { }); // Update gate calculation - previous_output.connect(update_gate, methods.connection.ALL_TO_ALL); + previous_output.connect(update_gate, methods.connection.ALL_TO_ALL_FORWARD); // Inverse update gate calculation update_gate.connect(inverse_update_gate, methods.connection.ONE_TO_ONE, 1); // Reset gate calculation - previous_output.connect(reset_gate, methods.connection.ALL_TO_ALL); + previous_output.connect(reset_gate, methods.connection.ALL_TO_ALL_FORWARD); // Memory calculation - const reset = previous_output.connect(memory_cell, methods.connection.ALL_TO_ALL); + const reset = previous_output.connect(memory_cell, methods.connection.ALL_TO_ALL_FORWARD); reset_gate.gate(reset, methods.gating.OUTPUT); // gate // Output calculation - const update1 = previous_output.connect(output, methods.connection.ALL_TO_ALL); - const update2 = memory_cell.connect(output, methods.connection.ALL_TO_ALL); + const update1 = previous_output.connect(output, methods.connection.ALL_TO_ALL_FORWARD); + const update2 = memory_cell.connect(output, methods.connection.ALL_TO_ALL_FORWARD); update_gate.gate(update1, methods.gating.OUTPUT); inverse_update_gate.gate(update2, methods.gating.OUTPUT); @@ -401,7 +401,7 @@ Layer.GRU = function(size) { layer.input = function(from, method, weight) { if (from instanceof Layer) from = from.output; - method = method || methods.connection.ALL_TO_ALL; + method = method || methods.connection.ALL_TO_ALL_FORWARD; const connections = [ from.connect(updateGate, method, weight), @@ -464,7 +464,7 @@ Layer.Memory = function(size, memory) { layer.input = function(from, method, weight) { if (from instanceof Layer) from = from.output; - method = method || methods.connection.ALL_TO_ALL; + method = method || methods.connection.ALL_TO_ALL_FORWARD; if (from.nodes.length !== layer.nodes[layer.nodes.length - 1].nodes.length) throw new Error('Previous layer size must be same as memory size'); diff --git a/src/methods/connection.js b/src/methods/connection.js index 93ff56552..7cc4c5eb8 100644 --- a/src/methods/connection.js +++ b/src/methods/connection.js @@ -14,14 +14,14 @@ * let A = new Group(4); * let B = new Group(5); * -* A.connect(B, methods.connection.ALL_TO_ALL); // specifying a method is optional +* A.connect(B, methods.connection.ALL_TO_ALL_FORWARD); // specifying a method is optional * * @example Group connection with itself * let { methods, Group } = require("@liquid-carrot/carrot"); * * let A = new Group(4); * -* A.connect(A, methods.connection.ALL_TO_ALL); +* A.connect(A, methods.connection.ALL_TO_ALL_FORWARD); */ const connection = { /** @@ -37,9 +37,9 @@ const connection = { * let A = new Group(4); * let B = new Group(5); * - * A.connect(B, methods.connection.ALL_TO_ALL); // specifying a method is optional + * A.connect(B, methods.connection.ALL_TO_ALL_FORWARD); // specifying a method is optional */ - ALL_TO_ALL: { + ALL_TO_ALL_FORWARD: { name: 'OUTPUT', }, /** diff --git a/test/units/architecture/group.test.js b/test/units/architecture/group.test.js index b70989d6a..cd3e449bb 100644 --- a/test/units/architecture/group.test.js +++ b/test/units/architecture/group.test.js @@ -232,19 +232,19 @@ describe("Group", function() { // connect(target, methods.connection[any_method_here]), <- no weight // connect(target, methods.connection.ONE_TO_ONE, weight), // connect(target, methods.connection.ALL_TO_ELSE, weight), - // connect(target, methods.connection.ALL_TO_ALL, weight) - it("group.connect(target, methods.connection.ALL_TO_ALL) => {Connection[]}", function() { + // connect(target, methods.connection.ALL_TO_ALL_FORWARD, weight) + it("group.connect(target, methods.connection.ALL_TO_ALL_FORWARD) => {Connection[]}", function() { let { main_group, other_group } = createRandomGroups(true); - main_group.connect(other_group, methods.connection.ALL_TO_ALL); + main_group.connect(other_group, methods.connection.ALL_TO_ALL_FORWARD); main_group.nodes.forEach(node => { expect(node.outgoing.length).equal(other_group.nodes.length); }); }) - it("group.connect(target, methods.connection.ALL_TO_ALL, weight) => {Connection[]}", function() { + it("group.connect(target, methods.connection.ALL_TO_ALL_FORWARD, weight) => {Connection[]}", function() { let { main_group, other_group } = createRandomGroups(true); const weight = Math.random(); - main_group.connect(other_group, methods.connection.ALL_TO_ALL, weight); + main_group.connect(other_group, methods.connection.ALL_TO_ALL_FORWARD, weight); main_group.nodes.forEach(node => { expect(node.outgoing.length).equal(other_group.nodes.length); diff --git a/test/units/architecture/layer.test.js b/test/units/architecture/layer.test.js index c225ad865..3d5687650 100644 --- a/test/units/architecture/layer.test.js +++ b/test/units/architecture/layer.test.js @@ -231,19 +231,19 @@ describe("Layer", function() { // connect(target, methods.connection[any_method_here]), <- no weight // connect(target, methods.connection.ONE_TO_ONE, weight), // connect(target, methods.connection.ALL_TO_ELSE, weight), - // connect(target, methods.connection.ALL_TO_ALL, weight) - it("layer.connect(target, methods.connection.ALL_TO_ALL) => {Connection[]}", function() { + // connect(target, methods.connection.ALL_TO_ALL_FORWARD, weight) + it("layer.connect(target, methods.connection.ALL_TO_ALL_FORWARD) => {Connection[]}", function() { let { main_layer, other_layer } = createRandomLayers(true); - main_layer.connect(other_layer, methods.connection.ALL_TO_ALL); + main_layer.connect(other_layer, methods.connection.ALL_TO_ALL_FORWARD); main_layer.nodes.forEach(node => { expect(node.outgoing.length).equal(other_layer.nodes.length); }); }) - it("layer.connect(target, methods.connection.ALL_TO_ALL, weight) => {Connection[]}", function() { + it("layer.connect(target, methods.connection.ALL_TO_ALL_FORWARD, weight) => {Connection[]}", function() { let { main_layer, other_layer } = createRandomLayers(true); const weight = Math.random(); - main_layer.connect(other_layer, methods.connection.ALL_TO_ALL, weight); + main_layer.connect(other_layer, methods.connection.ALL_TO_ALL_FORWARD, weight); main_layer.nodes.forEach(node => { expect(node.outgoing.length).equal(other_layer.nodes.length); @@ -413,8 +413,8 @@ describe("Layer", function() { const input_connections_weight = Math.random(); const output_connections_weight = Math.random(); - group_for_input.connect(main_created_layer, methods.connection.ALL_TO_ALL, input_connections_weight); - main_created_layer.connect(group_for_output, methods.connection.ALL_TO_ALL, output_connections_weight); + group_for_input.connect(main_created_layer, methods.connection.ALL_TO_ALL_FORWARD, input_connections_weight); + main_created_layer.connect(group_for_output, methods.connection.ALL_TO_ALL_FORWARD, output_connections_weight); const chain_input = Array(10).fill(0).map(() => Math.random()); diff --git a/test/units/architecture/layer.test.js.old b/test/units/architecture/layer.test.js.old index f3665f367..ed4fdd2a7 100644 --- a/test/units/architecture/layer.test.js.old +++ b/test/units/architecture/layer.test.js.old @@ -232,19 +232,19 @@ describe("Layer", function() { // connect(target, methods.connection[any_method_here]), <- no weight // connect(target, methods.connection.ONE_TO_ONE, weight), // connect(target, methods.connection.ALL_TO_ELSE, weight), - // connect(target, methods.connection.ALL_TO_ALL, weight) - it("layer.connect(target, methods.connection.ALL_TO_ALL) => {Connection[]}", function() { + // connect(target, methods.connection.ALL_TO_ALL_FORWARD, weight) + it("layer.connect(target, methods.connection.ALL_TO_ALL_FORWARD) => {Connection[]}", function() { let { main_layer, other_layer } = createRandomLayers(true); - main_layer.connect(other_layer, methods.connection.ALL_TO_ALL); + main_layer.connect(other_layer, methods.connection.ALL_TO_ALL_FORWARD); main_layer.nodes.forEach(node => { expect(node.outgoing.length).equal(other_layer.nodes.length); }); }) - it("layer.connect(target, methods.connection.ALL_TO_ALL, weight) => {Connection[]}", function() { + it("layer.connect(target, methods.connection.ALL_TO_ALL_FORWARD, weight) => {Connection[]}", function() { let { main_layer, other_layer } = createRandomLayers(true); const weight = Math.random(); - main_layer.connect(other_layer, methods.connection.ALL_TO_ALL, weight); + main_layer.connect(other_layer, methods.connection.ALL_TO_ALL_FORWARD, weight); main_layer.nodes.forEach(node => { expect(node.outgoing.length).equal(other_layer.nodes.length); From 503e3677c706ca954d039523900cf7f793270c1a Mon Sep 17 00:00:00 2001 From: Manuel Raimann Date: Sat, 11 Apr 2020 00:10:41 +0200 Subject: [PATCH 3/3] adding "type" param to group and set all it's node with it, if given --- src/architecture/group.js | 43 ++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/architecture/group.js b/src/architecture/group.js index c505b7d57..b85090de6 100644 --- a/src/architecture/group.js +++ b/src/architecture/group.js @@ -4,24 +4,25 @@ const config = require('../config'); const Node = require('./node'); /** -* A group instance denotes a group of nodes. Beware: once a group has been used to construct a network, the groups will fall apart into individual nodes. They are purely for the creation and development of networks. -* -* @constructs Group -* -* @param {number} [size=0] Amount of nodes to build group with -* -* @prop {Nodes[]} [nodes=[]] All nodes within the group -* @prop {Connection[]} [incoming=[]] Incoming connections -* @prop {Connection[]} [outgoing=[]] Outgoing connections -* @prop {Connection[]} [connections_self=[]] Self connections -* -* @example -* let { Group } = require("@liquid-carrot/carrot"); -* -* // A group with 5 nodes -* let A = new Group(5); -*/ -function Group(size) { + * A group instance denotes a group of nodes. Beware: once a group has been used to construct a network, the groups will fall apart into individual nodes. They are purely for the creation and development of networks. + * + * @constructs Group + * + * @param {number} [size=0] Amount of nodes to build group with + * + * @param {String} type the type of nodes inside the group + * @prop {Nodes[]} [nodes=[]] All nodes within the group + * @prop {Connection[]} [incoming=[]] Incoming connections + * @prop {Connection[]} [outgoing=[]] Outgoing connections + * @prop {Connection[]} [connections_self=[]] Self connections + * + * @example + * let { Group } = require("@liquid-carrot/carrot"); + * + * // A group with 5 nodes + * let A = new Group(5); + */ +function Group(size,type) { const self = this; // Important: @@ -32,7 +33,11 @@ function Group(size) { self.outgoing = []; for (let index = 0; index < size; index++) { - self.nodes.push(new Node()); + const node = new Node(); + if(type) { + node.type = type; + } + self.nodes.push(node); } /**