def decode(dna: DNASequence) -> float: r = (-1.0, 0.0, 1.0) while not dna.finish: c = dna.any(_SELECT_FIRST_HALF, _SELECT_SECOND_HALF, _INCREASE_RANGE, _SELECT_RANGE_START, _SELECT_RANGE_CENTER, _SELECT_RANGE_END) if c == _SELECT_FIRST_HALF: r = (r[0], r[0] + (r[1] - r[0]) * 0.5, r[1]) continue elif c == _SELECT_SECOND_HALF: r = (r[1], r[1] + (r[2] - r[1]) * 0.5, r[2]) continue elif c == _INCREASE_RANGE: r = (r[0] * 2, r[1], r[2] * 2) continue elif c == _SELECT_RANGE_START: return r[0] elif c == _SELECT_RANGE_CENTER: return r[1] elif c == _SELECT_RANGE_END: return r[2] else: break return r[1]
def assemble(dna: DNASequence, network: NeuralNetwork): connections = [] while not dna.finish: c = dna.any(DNASequences.NEURON_CREATE_LAYER, DNASequences.NEURON_CREATE, DNASequences.NEURON_CREATE_LINK) if c == DNASequences.NEURON_CREATE_LAYER: # skip layer creation if previous empty if network.layers and not network.layers[-1].neurons: continue network.layers.append(NeuralNetworkLayer(0)) elif c == DNASequences.NEURON_CREATE: if not network.layers: continue current_layer = network.layers[-1] bias = float_decode(dna) neuron = NeuralNetworkNeuron(current_layer) neuron.bias = bias current_layer.neurons.append(neuron) elif c == DNASequences.NEURON_CREATE_LINK: if not network.layers or not network.layers[-1].neurons: continue neuron = network.layers[-1].neurons[-1] link_data = float_decode(dna) weight = float_decode(dna) connections.append(NeuronDNAConnection(neuron, link_data, weight)) while not network.layers[-1].neurons: del network.layers[-1] network.outputs = network.layers[-1] layers = list() layers.append(network.input) layers.extend(network.layers) for connection in connections: neuron = connection.neuron # type: NeuralNetworkNeuron layer_index = layers.index(neuron.layer) link_neuron_address, link_layer_address = math.modf(connection.link_data) layer_index -= math.trunc(link_layer_address + __ROUND_VALUE) + 1 if len(layers) >= layer_index < 0: continue link_layer = layers[layer_index] # type: NeuralNetworkLayer link_neuron_index = (len(link_layer.neurons)-1) * (link_neuron_address / __NEURON_INDEX_REMAP) neuron.add_connection(link_layer.neurons[math.trunc(link_neuron_index + __ROUND_VALUE)], connection.weight)