Skip to content

Commit

Permalink
Modify network.mutate to consistently return network irrespective of …
Browse files Browse the repository at this point in the history
…succesful mutation
  • Loading branch information
christianechevarria committed Jan 5, 2020
1 parent 6fc1abd commit 85c8000
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 95 deletions.
153 changes: 72 additions & 81 deletions src/architecture/network.js
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,7 @@ function Network(input_size, output_size, options) {
* myNetwork = myNetwork.mutate(mutation.ADD_GATE) // returns a mutated network with an added gate
*
* @todo Create a comprehensive logging system
* @todo Create an ID tracking scheme for gating
* @todo Make node management order agnostic by tracking input / outputs better
* @todo Add standalone node id population synchronization capabilities
* @todo Add tests for ADD_SELF_CONN
Expand All @@ -883,15 +884,24 @@ function Network(input_size, output_size, options) {

const { maxNodes, maxConns, maxGates } = options || {}

// Utility Functions

// Logging utility, to be expanded upon
const trackMutation = function(name) {
self.mutations.push(name)
const trackMutation = function(name, successful) {
self.mutations.push({
name,
successful
})
}

switch (method.name) {
// Looks for an existing connection and places a node in between
case "ADD_NODE": {
if(self.nodes.length >= maxNodes) return null // Check user constraint
// Check user constraint
if(self.nodes.length >= maxNodes) {
trackMutation(method.name, false) // Add failed mutation to tracking array
return self
}

// Only places nodes where existing connections are
const connection = self.getRandomConnection()
Expand All @@ -918,122 +928,111 @@ function Network(input_size, output_size, options) {
const gater = connection.gater
if (gater != null) self.gate(gater, Math.random() >= 0.5 ? new_connection1 : new_connection2) // Check if the original connection was gated

// Add mutation to tracking array
trackMutation(method.name)

// Add successful mutation to tracking array
trackMutation(method.name, true)
return self
}
case "SUB_NODE": {
const possible = self.possible(method)
if (possible) {
self.remove(_.sample(possible))

// Add mutation to tracking array
trackMutation(method.name)

// Add successful mutation to tracking array
trackMutation(method.name, true)
return self
}

// Add attempted mutation to tracking array
trackMutation(method.name + " (attempted)")

return null
// Add failed mutation to tracking array
trackMutation(method.name, false)
return self
}
case "ADD_SELF_CONN": // same code as ADD_CONN, differences dictated by self.possible
case "ADD_BACK_CONN": // same code as ADD_CONN, differences dictated by self.possible
case "ADD_CONN": {
if(self.connections.length >= maxConns) return null // Check user constraint
// Check user constraint
if(self.connections.length >= maxConns) {
trackMutation(method.name, false) // Add failed mutation to tracking array
return self
}

const possible = self.possible(method)
if (possible) {
const pair = possible[Math.floor(Math.random() * possible.length)]
self.connect(pair[0], pair[1], undefined, { connIds: self.connIds })

// Add mutation to tracking array
trackMutation(method.name)

// Add succesful mutation to tracking array
trackMutation(method.name, true)
return self
}

// Add attempted mutation to tracking array
trackMutation(method.name + " (attempted)")

return null
trackMutation(method.name, false) // Add failed mutation to tracking array
return self
}
case "REMOVE_CONN": // alias for sub_conn
case "SUB_CONN": {
const possible = self.possible(method)
if (possible) {
const chosen = _.sample(possible)
const chosen = possible[Math.floor(Math.random() * possible.length)]
self.disconnect(chosen.from, chosen.to)

// Add mutation to tracking array
trackMutation(method.name)

// Add succesful mutation to tracking array
trackMutation(method.name, true)
return self
}

// Add attempted mutation to tracking array
trackMutation(method.name + " (attempted)")

return null
trackMutation(method.name, false) // Add failed mutation to tracking array
return self
}
case "MOD_WEIGHT": {
const chosen_connection = self.getRandomConnection() // get a random connection to modify weight
chosen_connection.weight += Math.random() * (method.max - method.min) + method.min

// Add mutation to tracking array
trackMutation(method.name)

// Add succesful mutation to tracking array
trackMutation(method.name, true)
return self
}
case "MOD_BIAS": {
if (self.nodes.length <= self.input_size) return null;
// Has no effect on input nodes, so they (should be) excluded, TODO -- remove this ordered array of: input, output, hidden nodes assumption...
const node_to_mutate = self.nodes[Math.floor(Math.random() * (self.nodes.length - self.input_size) + self.input_size)]
node_to_mutate.mutate(method)

// Add mutation to tracking array
trackMutation(method.name)

// Add succesful mutation to tracking array
trackMutation(method.name, true)
return self
}
case "MOD_ACTIVATION": {
const possible = self.possible(method)
if (possible) {
_.sample(possible).mutate(method) // Mutate a random node out of filtered collection, MOD_ACTIVATION is a neuron-level concern

// Add mutation to tracking array
trackMutation(method.name)

// Add succesful mutation to tracking array
trackMutation(method.name, true)
return self
}

// Add attempted mutation to tracking array
trackMutation(method.name + " (attempted)")

return null
trackMutation(method.name, false) // Add failed mutation to tracking array
return self
}
case "SUB_SELF_CONN": {
const possible = self.possible(method)
if (possible) {
const chosen_connection = possible[Math.floor(Math.random() * possible.length)];
self.disconnect(chosen_connection.from, chosen_connection.to);

// Add mutation to tracking array
trackMutation(method.name)

// Add succesful mutation to tracking array
trackMutation(method.name, true)
return self
}

// Add attempted mutation to tracking array
trackMutation(method.name + " (attempted)")

return null;
trackMutation(method.name, false) // Add failed mutation to tracking array
return self
}
case "ADD_GATE": {
// Check user constraint
if(self.gates.length >= maxGates) return null
if(self.gates.length >= maxGates) {
trackMutation(method.name, false) // Add failed mutation to tracking array
return self
}

const possible = self.possible(method)
if (possible) {
Expand All @@ -1042,49 +1041,40 @@ function Network(input_size, output_size, options) {
const conn = possible[Math.floor(Math.random() * possible.length)]

self.gate(node, conn) // Gate the connection with the node

// Add mutation to tracking array
trackMutation(method.name)


// Add succesful mutation to tracking array
trackMutation(method.name, true)
return self
}

// Add attempted mutation to tracking array
trackMutation(method.name + " (attempted)")

return null
trackMutation(method.name, false) // Add failed mutation to tracking array
return self
}
case "SUB_GATE": {
if (self.possible(method)) {
self.ungate(self.gates[Math.floor(Math.random() * self.gates.length)])

// Add mutation to tracking array
trackMutation(method.name)

// Add succesful mutation to tracking array
trackMutation(method.name, true)
return self
}

// Add attempted mutation to tracking array
trackMutation(method.name + " (attempted)")

return null;
trackMutation(method.name, false) // Add failed mutation to tracking array
return self
}
case "SUB_BACK_CONN": {
const possible = self.possible(method)
if (possible) {
const random_connection = possible[Math.floor(Math.random() * possible.length)]
self.disconnect(random_connection.from, random_connection.to)

// Add mutation to tracking array
trackMutation(method.name)

// Add succesful mutation to tracking array
trackMutation(method.name, true)
return self
}

// Add attempted mutation to tracking array
trackMutation(method.name + " (attempted)")

return null
trackMutation(method.name, false) // Add failed mutation to tracking array
return self
}
case "SWAP_NODES": {
const possible = self.possible(method)
Expand All @@ -1106,16 +1096,13 @@ function Network(input_size, output_size, options) {
node2.bias = bias_temp
node2.squash = squash_temp

// Add mutation to tracking array
trackMutation(method.name)

// Add succesful mutation to tracking array
trackMutation(method.name, true)
return self
}

// Add attempted mutation to tracking array
trackMutation(method.name + " (attempted)")

return null
trackMutation(method.name, false) // Add failed mutation to tracking array
return self
}
}
}
Expand Down Expand Up @@ -1144,8 +1131,12 @@ function Network(input_size, output_size, options) {
const x = Math.floor(Math.random() * possible.length)
const current = possible[x]

if(self.mutate(current, options)) return self
const network = self.mutate(current, options);
const mutations = network.mutations;

// If the last attempted mutation was successful, return the new network
if(mutations[mutations.length-1].successful) return self

possible.splice(x,1)
}

Expand Down
27 changes: 13 additions & 14 deletions test/units/architecture/network.1.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,19 @@ describe('Network', function(){

})

describe('ADD_SELF_CONN', function() {
it('originalNetwork != newNetwork | when mutation possible', function() {

})

})

describe('ADD_BACK_CONN', function() {
it('originalNetwork != newNetwork | when mutation possible', function() {

})
})

describe('MOD_BIAS', function() {
it('originalNetwork != newNetwork | when mutation possible', function() {

Expand Down Expand Up @@ -1383,27 +1396,13 @@ describe('Network', function(){

})

describe('ADD_SELF_CONN', function() {
it('originalNetwork != newNetwork | when mutation possible', function() {

})

})

describe('SUB_SELF_CONN', function() {
it('originalNetwork != newNetwork | when mutation possible', function() {

})

})

describe('ADD_BACK_CONN', function() {
it('originalNetwork != newNetwork | when mutation possible', function() {

})

})

describe('SUB_BACK_CONN', function() {
it('originalNetwork != newNetwork | when mutation possible', function() {

Expand Down

0 comments on commit 85c8000

Please sign in to comment.