'use strict'; const DEFAULT_WEIGHT_MAX = 4; const graph_proto = { connect: function(source, sink, weight) { return network_connect(this, source, sink, weight); }, }; export function network(input_count, internal_count, output_count, weight_max = 4) { const count = input_count + internal_count + output_count; const n = Object.create(graph_proto); n.input_count = input_count; n.output_count = output_count; n.adjacency = new Array(count).fill([]); n.weight = []; return Object.freeze(n); } function is_input(n, index) { return index < n.input_count; } function is_output(n, index) { return index >= (n.adjacency.length - n.output_count); } function network_connect(n, source, sink, weight) { if (is_input(n, sink)) { // inputs cannot be sinks throw new Error("attempt to use input as sink"); } if (is_output(n, source)) { // outputs cannot be sources throw new Error("attempt to use output as source"); } const nn = Object.create(graph_proto); nn.input_count = n.input_count; nn.output_count = n.output_count; nn.adjacency = n.adjacency.map((row, i) => { if (i === source && i === sink) { // self-loop return [...row, 2]; } else if (i === source) { return [...row, 1]; } else if (i === sink) { return [...row, -1]; } else { return [...row, 0]; } }); nn.weight = [...n.weight, weight]; return Object.freeze(nn); }