예제 #1
0
    def create(genome, config):
        """ Receives a genome and returns its phenotype (a RecurrentNetwork). """
        genome_config = config.genome_config
        required = required_for_output(genome_config.input_keys, genome_config.output_keys, genome.connections)

        # Gather inputs and expressed connections.
        node_inputs = {}
        for cg in genome.connections.values():
            if not cg.enabled:
                continue

            i, o = cg.key
            if o not in required and i not in required:
                continue

            if o not in node_inputs:
                node_inputs[o] = [(i, cg.weight)]
            else:
                node_inputs[o].append((i, cg.weight))

        node_evals = []
        for node_key, inputs in node_inputs.items():
            node = genome.nodes[node_key]
            activation_function = genome_config.activation_defs.get(node.activation)
            aggregation_function = genome_config.aggregation_function_defs.get(node.aggregation)
            node_evals.append((node_key, activation_function, aggregation_function, node.bias, node.response, inputs))

        return RecurrentNetwork(genome_config.input_keys, genome_config.output_keys, node_evals)
예제 #2
0
    def create(genome, config):
        """ Receives a genome and returns its phenotype (a neural network). """
        genome_config = config.genome_config
        required = required_for_output(genome_config.input_keys,
                                       genome_config.output_keys,
                                       genome.connections)

        # Gather inputs and expressed connections.
        node_inputs = {}
        for cg in genome.connections.values():
            if not cg.enabled:
                continue

            i, o = cg.key
            if o not in required and i not in required:
                continue

            if o not in node_inputs:
                node_inputs[o] = [(i, cg.weight)]
            else:
                node_inputs[o].append((i, cg.weight))

        neurons = {}
        for node_key in required:
            ng = genome.nodes[node_key]
            inputs = node_inputs.get(node_key, [])
            neurons[node_key] = IZNeuron(ng.bias, ng.a, ng.b, ng.c, ng.d,
                                         inputs)

        genome_config = config.genome_config
        return IZNN(neurons, genome_config.input_keys,
                    genome_config.output_keys)
예제 #3
0
    def create(genome, config, time_constant):
        """ Receives a genome and returns its phenotype (a CTRNN). """
        genome_config = config.genome_config
        required = required_for_output(genome_config.input_keys, genome_config.output_keys, genome.connections)

        # Gather inputs and expressed connections.
        node_inputs = {}
        for cg in itervalues(genome.connections):
            if not cg.enabled:
                continue

            i, o = cg.key
            if o not in required and i not in required:
                continue

            if o not in node_inputs:
                node_inputs[o] = [(i, cg.weight)]
            else:
                node_inputs[o].append((i, cg.weight))

        node_evals = {}
        for node_key, inputs in iteritems(node_inputs):
            node = genome.nodes[node_key]
            activation_function = genome_config.activation_defs.get(node.activation)
            aggregation_function = genome_config.aggregation_function_defs.get(node.aggregation)
            node_evals[node_key] = CTRNNNodeEval(time_constant,
                                                 activation_function,
                                                 aggregation_function,
                                                 node.bias,
                                                 node.response,
                                                 inputs)

        return CTRNN(genome_config.input_keys, genome_config.output_keys, node_evals)
예제 #4
0
def test_fuzz_required():
    for _ in range(1000):
        n_hidden = random.randint(10, 100)
        n_in = random.randint(1, 10)
        n_out = random.randint(1, 10)
        nodes = list(
            set(
                random.randint(0, 1000)
                for _ in range(n_in + n_out + n_hidden)))
        random.shuffle(nodes)

        inputs = nodes[:n_in]
        outputs = nodes[n_in:n_in + n_out]
        connections = []
        for _ in range(n_hidden * 2):
            a = random.choice(nodes)
            b = random.choice(nodes)
            if a == b:
                continue
            if a in inputs and b in inputs:
                continue
            if a in outputs and b in outputs:
                continue
            connections.append((a, b))

        required = required_for_output(inputs, outputs, connections)
        for o in outputs:
            assert o in required
    def map_back_to_genome(self, genome, config, leaf_names, node_names):

        genome_config = config.genome_config
        required = required_for_output(genome_config.input_keys,
                                       genome_config.output_keys,
                                       genome.connections)

        # Gather inputs and expressed connections.
        node_inputs = {i: {} for i in genome_config.output_keys}
        for cg in genome.connections.values():
            if not cg.enabled:
                continue

            i, o = cg.key

            if o not in required and i not in required:
                continue

            if i in genome_config.output_keys:
                continue

            if o not in node_inputs:
                node_inputs[o] = {}

            node_inputs[o][i] = cg

            if i not in node_inputs:
                node_inputs[i] = {}

        nodes = {i: Leaf(i) for i in genome_config.input_keys}

        assert len(leaf_names) == len(genome_config.input_keys)
        leaves = {
            name: nodes[i]
            for name, i in zip(leaf_names, genome_config.input_keys)
        }

        def map_back(idx, current_node):
            if isinstance(current_node, Leaf):
                return
            conns = node_inputs[idx]
            for idx, c in enumerate(current_node.children):
                conns[c.genome_idx].weight = list(current_node.weights)[idx]
                map_back(c.genome_idx, c)
            return

        if (type(self.cppn) != list):
            map_back(self.cppn.genome_idx, self.cppn)
        else:
            for o in self.cppn:
                map_back(o.genome_idx, o)
        return
예제 #6
0
def test_required_for_output():
    inputs = [0, 1]
    outputs = [2]
    connections = [(0, 2), (1, 2)]
    required = required_for_output(inputs, outputs, connections)
    assert {2} == required

    inputs = [0, 1]
    outputs = [2]
    connections = [(0, 3), (1, 4), (3, 2), (4, 2)]
    required = required_for_output(inputs, outputs, connections)
    assert {2, 3, 4} == required

    inputs = [0, 1]
    outputs = [3]
    connections = [(0, 2), (1, 2), (2, 3)]
    required = required_for_output(inputs, outputs, connections)
    assert {2, 3} == required

    inputs = [0, 1]
    outputs = [4]
    connections = [(0, 2), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)]
    required = required_for_output(inputs, outputs, connections)
    assert {2, 3, 4} == required

    inputs = [0, 1]
    outputs = [4]
    connections = [(0, 2), (1, 3), (2, 3), (3, 4), (4, 2)]
    required = required_for_output(inputs, outputs, connections)
    assert {2, 3, 4} == required

    inputs = [0, 1]
    outputs = [4]
    connections = [(0, 2), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4), (2, 5)]
    required = required_for_output(inputs, outputs, connections)
    assert {2, 3, 4} == required
예제 #7
0
def create_cppn(genome,
                config,
                leaf_names,
                node_names,
                output_activation=None):

    genome_config = config.genome_config
    required = required_for_output(genome_config.input_keys,
                                   genome_config.output_keys,
                                   genome.connections)

    # Gather inputs and expressed connections.
    node_inputs = {i: [] for i in genome_config.output_keys}
    for cg in genome.connections.values():
        if not cg.enabled:
            continue

        i, o = cg.key
        if o not in required and i not in required:
            continue

        if i in genome_config.output_keys:
            continue

        if o not in node_inputs:
            node_inputs[o] = [(i, cg.weight)]
        else:
            node_inputs[o].append((i, cg.weight))

        if i not in node_inputs:
            node_inputs[i] = []

    nodes = {i: Leaf(i) for i in genome_config.input_keys}

    assert len(leaf_names) == len(genome_config.input_keys)
    leaves = {
        name: nodes[i]
        for name, i in zip(leaf_names, genome_config.input_keys)
    }

    def build_node(idx):
        if idx in nodes:
            return nodes[idx]
        node = genome.nodes[idx]
        conns = node_inputs[idx]
        children = [build_node(i) for i, w in conns]
        weights = [w for i, w in conns]
        if idx in genome_config.output_keys and output_activation is not None:
            activation = output_activation
        else:
            activation = str_to_activation[node.activation]
        aggregation = str_to_aggregation[node.aggregation]
        nodes[idx] = Node(
            children,
            weights,
            node.response,
            node.bias,
            activation,
            aggregation,
            genome_idx=idx,
            leaves=leaves,
        )
        return nodes[idx]

    for idx in genome_config.output_keys:
        build_node(idx)

    outputs = [nodes[i] for i in genome_config.output_keys]

    for name in leaf_names:
        leaves[name].name = name

    for i, name in zip(genome_config.output_keys, node_names):
        nodes[i].name = name

    return outputs
예제 #8
0
def draw_net(config,
             genome,
             view=False,
             filename=None,
             node_names=None,
             show_disabled=True,
             prune_unused=True,
             node_colors=None,
             fmt='pdf'):
    """ Receives a genome and draws a neural network with arbitrary topology. """

    if node_names is None:
        node_names = {}

    assert type(node_names) is dict

    if node_colors is None:
        node_colors = {}

    assert type(node_colors) is dict

    node_attrs = {
        'shape': 'circle',
        'fontsize': '9',
        'height': '0.2',
        'width': '0.2'
    }

    dot = graphviz.Digraph(format=fmt, node_attr=node_attrs)

    def node_to_string(n):
        try:
            no = genome.nodes[n]
            return '\n'.join(
                [str(n), str(no.activation), '{:0.2f}'.format(no.bias)])
        except KeyError:
            return str(n)

    inputs = set()
    for k in config.genome_config.input_keys:
        inputs.add(k)
        name = node_names.get(k, node_to_string(k))
        input_attrs = {'style': 'filled', 'shape': 'box'}
        input_attrs['fillcolor'] = node_colors.get(k, 'lightgray')
        dot.node(name, _attributes=input_attrs)

    outputs = set()
    for k in config.genome_config.output_keys:
        outputs.add(k)
        name = node_names.get(k, node_to_string(k))
        node_attrs = {'style': 'filled'}
        node_attrs['fillcolor'] = node_colors.get(k, 'lightblue')
        dot.node(name, _attributes=node_attrs)

    from neat.graphs import required_for_output
    required = required_for_output(config.genome_config.input_keys,
                                   config.genome_config.output_keys,
                                   genome.connections)
    required |= inputs
    # print(required)

    if prune_unused:
        connections = set()
        for cg in genome.connections.values():
            # print(cg)
            f, t = cg.key
            if f not in required or t not in required:
                # print('removed')
                continue
            if not cg.enabled and not show_disabled:
                # print('remove')
                continue
            # print('kept')
            connections.add(cg.key)

        # for c in connections:
        #     print(c)

        used_nodes = inputs | outputs
        pending = copy.copy(outputs)
        while pending:
            new_pending = set()
            for a, b in connections:
                if b in used_nodes and b in pending and a not in used_nodes:
                    new_pending.add(a)
                    used_nodes.add(a)
            # print(pending, new_pending)
            pending = new_pending
        # used_nodes = required
    else:
        used_nodes = set(genome.nodes.keys())

    for n in used_nodes:
        if n in inputs or n in outputs:
            continue
        attrs = {'style': 'filled'}
        attrs['fillcolor'] = node_colors.get(n, 'white')
        dot.node(node_to_string(n), _attributes=attrs)

    for cg in genome.connections.values():
        if cg.enabled or show_disabled:
            #if cg.input not in used_nodes or cg.output not in used_nodes:
            #    continue
            input, output = cg.key
            if input not in used_nodes or output not in used_nodes:
                continue
            a = node_names.get(input, node_to_string(input))
            b = node_names.get(output, node_to_string(output))
            style = 'solid' if cg.enabled else 'dotted'
            color = 'green' if cg.weight > 0 else 'red'
            width = str(0.1 + abs(cg.weight / 5.0))
            dot.edge(a,
                     b,
                     _attributes={
                         'style': style,
                         'color': color,
                         'penwidth': width,
                         'label': '{:0.2f}'.format(cg.weight),
                         'fontsize': '9'
                     })

    dot.render(filename, view=view, cleanup=True)

    return dot
예제 #9
0
    def create(genome,
               config,
               batch_size=1,
               activation=sigmoid_activation,
               prune_empty=False,
               use_current_activs=False,
               n_internal_steps=1):
        from neat.graphs import required_for_output

        genome_config = config.genome_config
        required = required_for_output(genome_config.input_keys,
                                       genome_config.output_keys,
                                       genome.connections)
        if prune_empty:
            nonempty = {
                conn.key[1]
                for conn in genome.connections.values() if conn.enabled
            }.union(set(genome_config.input_keys))

        input_keys = list(genome_config.input_keys)
        hidden_keys = [
            k for k in genome.nodes.keys()
            if k not in genome_config.output_keys
        ]
        output_keys = list(genome_config.output_keys)

        hidden_responses = [genome.nodes[k].response for k in hidden_keys]
        output_responses = [genome.nodes[k].response for k in output_keys]

        hidden_biases = [genome.nodes[k].bias for k in hidden_keys]
        output_biases = [genome.nodes[k].bias for k in output_keys]

        if prune_empty:
            for i, key in enumerate(output_keys):
                if key not in nonempty:
                    output_biases[i] = 0.0

        n_inputs = len(input_keys)
        n_hidden = len(hidden_keys)
        n_outputs = len(output_keys)

        input_key_to_idx = {k: i for i, k in enumerate(input_keys)}
        hidden_key_to_idx = {k: i for i, k in enumerate(hidden_keys)}
        output_key_to_idx = {k: i for i, k in enumerate(output_keys)}

        def key_to_idx(key):
            if key in input_keys:
                return input_key_to_idx[key]
            elif key in hidden_keys:
                return hidden_key_to_idx[key]
            elif key in output_keys:
                return output_key_to_idx[key]

        input_to_hidden = ([], [])
        hidden_to_hidden = ([], [])
        output_to_hidden = ([], [])
        input_to_output = ([], [])
        hidden_to_output = ([], [])
        output_to_output = ([], [])

        for conn in genome.connections.values():
            if not conn.enabled:
                continue

            i_key, o_key = conn.key
            if o_key not in required and i_key not in required:
                continue
            if prune_empty and i_key not in nonempty:
                print('Pruned {}'.format(conn.key))
                continue

            i_idx = key_to_idx(i_key)
            o_idx = key_to_idx(o_key)

            if i_key in input_keys and o_key in hidden_keys:
                idxs, vals = input_to_hidden
            elif i_key in hidden_keys and o_key in hidden_keys:
                idxs, vals = hidden_to_hidden
            elif i_key in output_keys and o_key in hidden_keys:
                idxs, vals = output_to_hidden
            elif i_key in input_keys and o_key in output_keys:
                idxs, vals = input_to_output
            elif i_key in hidden_keys and o_key in output_keys:
                idxs, vals = hidden_to_output
            elif i_key in output_keys and o_key in output_keys:
                idxs, vals = output_to_output
            else:
                raise ValueError(
                    'Invalid connection from key {} to key {}'.format(
                        i_key, o_key))

            idxs.append((o_idx, i_idx))  # to, from
            vals.append(conn.weight)

        return RecurrentNet(n_inputs,
                            n_hidden,
                            n_outputs,
                            input_to_hidden,
                            hidden_to_hidden,
                            output_to_hidden,
                            input_to_output,
                            hidden_to_output,
                            output_to_output,
                            hidden_responses,
                            output_responses,
                            hidden_biases,
                            output_biases,
                            batch_size=batch_size,
                            activation=activation,
                            use_current_activs=use_current_activs,
                            n_internal_steps=n_internal_steps)
def create(genome, config, map_size):
    """ Receives a genome and returns its phenotype (a SwitchNeuronNetwork). """
    genome_config = config.genome_config
    required = required_for_output(genome_config.input_keys,
                                   genome_config.output_keys,
                                   genome.connections)

    input_keys = genome_config.input_keys
    output_keys = genome_config.output_keys
    # Gather inputs and expressed connections.
    std_inputs = {}
    mod_inputs = {}
    children = {}
    node_keys = set(genome.nodes.keys())  # + list(genome_config.input_keys[:])

    # Here we populate the children dictionay for each unique not isolated node.
    for n in genome.nodes.keys():
        children[n] = []
        if not genome.nodes[n].is_isolated:
            for _ in range(1, map_size):
                new_idx = max(node_keys) + 1
                children[n].append(new_idx)
                node_keys.add(new_idx)
    # We don't scale the output with the map size to keep passing the parameters of the network easy.
    # This part can be revised in the future
    for n in chain(input_keys, output_keys):
        children[n] = []
    #Iterate over every connection
    for cg in itervalues(genome.connections):
        #If it's not enabled don't include it
        if not cg.enabled:
            continue

        i, o = cg.key
        #If neither node is required for output then skip the connection
        if o not in required and i not in required:
            continue

        #Find the map corresponding to each node of the connection
        in_map = [i] + children[i]
        out_map = [o] + children[o]
        #If the connection is modulatory and the output neuron a switch neuron then the new weights are stored
        #in the mod dictionary. We assume that only switch neurons have a modulatory part.
        if cg.is_mod and genome.nodes[o].is_switch:
            node_inputs = mod_inputs
        else:
            node_inputs = std_inputs
        for n in out_map:
            if n not in node_inputs.keys():
                node_inputs[n] = []

        if len(in_map) == map_size and len(out_map) == map_size:
            # Map to map connectivity
            if cg.one2one:
                # 1-to-1 mapping
                weight = cg.weight
                for i in range(map_size):
                    node_inputs[out_map[i]].append((in_map[i], weight))

            else:
                # 1-to-all
                if not cg.uniform:
                    # Step
                    start = -cg.weight
                    end = cg.weight
                    step = (end - start) / (map_size - 1)
                    for o_n in out_map:
                        s = start
                        for i_n in in_map:
                            node_inputs[o_n].append((i_n, s))
                            s += step
                else:
                    # Uniform
                    for o_n in out_map:
                        for i_n in in_map:
                            node_inputs[o_n].append((i_n, cg.weight))

        else:
            # Map-to-isolated or isolated-to-isolated
            if not cg.uniform:
                # Step
                start = -cg.weight
                end = cg.weight
                step = (end - start) / (map_size - 1)
                for o_n in out_map:
                    s = start
                    for i_n in in_map:
                        node_inputs[o_n].append((i_n, s))
                        s += step
            else:
                # Uniform
                for o_n in out_map:
                    for i_n in in_map:
                        node_inputs[o_n].append((i_n, cg.weight))

    nodes = []

    #Sometimes the output neurons end up not having any connections during the evolutionary process. While we do not
    #desire such networks, we should still allow them to make predictions to avoid fatal errors.
    for okey in output_keys:
        if okey not in node_keys:
            node_keys.add(okey)
            std_inputs[okey] = []

    # While we cannot deduce the order of activations of the neurons due to the fact that we allow for arbitrary connection
    # schemes, we certainly want the output neurons to activate last.
    input_keys = genome_config.input_keys
    output_keys = genome_config.output_keys
    conns = {}
    for k in genome.nodes.keys():
        if k not in std_inputs:
            std_inputs[k] = []
            if k in children:
                for c in children[k]:
                    std_inputs[c] = []
        conns[k] = [i for i, _ in std_inputs[k]]
    sorted_keys = order_of_activation(conns, input_keys, output_keys)

    for node_key in sorted_keys:
        #if the node we are examining is not in our keys set then skip it. It means that it is not required for output.
        if node_key not in node_keys:
            continue

        node = genome.nodes[node_key]
        node_map = [node_key] + children[node_key]
        if node.is_switch:

            #If the node doesn't have any inputs then it is not needed
            if node_key not in std_inputs.keys(
            ) and node_key not in mod_inputs.keys():
                continue
            # if the switch neuron only has modulatory weights then we copy those weights for the standard part as well.
            # this is not the desired behaviour but it is done to avoid errors during forward pass.
            if node_key not in std_inputs.keys(
            ) and node_key in mod_inputs.keys():
                for n in node_map:
                    std_inputs[n] = mod_inputs[n]
            if node_key not in mod_inputs:
                for n in node_map:
                    mod_inputs[n] = []
            for n in node_map:
                nodes.append(SwitchNeuron(n, std_inputs[n], mod_inputs[n]))
            continue
        for n in node_map:
            if n not in std_inputs:
                std_inputs[n] = []

        # Create the standard part dictionary for the neuron
        for n in node_map:
            params = {
                'activation_function':
                genome_config.activation_defs.get(node.activation),
                'integration_function':
                genome_config.aggregation_function_defs.get(node.aggregation),
                'bias':
                node.bias,
                'activity':
                0,
                'output':
                0,
                'weights':
                std_inputs[n]
            }
            nodes.append(Neuron(n, params))

    return SwitchNeuronNetwork(input_keys, output_keys, nodes)
def create(genome, config):
    genome_config = config.genome_config
    required = required_for_output(genome_config.input_keys,
                                   genome_config.output_keys,
                                   genome.connections)
    input_keys = genome_config.input_keys
    output_keys = genome_config.output_keys

    #A dictionary where we keep the modulatory weights for every node
    mod_weights = {}
    #A dictionary where we keep the standard weights for every node
    std_weights = {}
    #Create a set with the keys of the nodes in the network
    keys = set()
    #Iterate over the connections
    for cg in itervalues(genome.connections):
        #if not cg.enabled:
        #    continue

        i, o = cg.key
        #If neither of the nodes in the connection are required for output then skip this connection
        if o not in required and i not in required:
            continue

        if i not in input_keys:
            keys.add(i)
        keys.add(o)
        #In this implementation, only switch neurons have a modulatory part
        if genome.nodes[o].is_switch:
            #Add the weight to the modulatory part of the o node and continue with the next connection
            if cg.is_mod:
                if o not in mod_weights.keys():
                    mod_weights[o] = [(i, cg.weight)]
                else:
                    mod_weights[o].append((i, cg.weight))
                continue
        #If the connection is not modulatory
        #Add the weight to the standard weight of the o node.
        if o not in std_weights.keys():
            std_weights[o] = [(i, cg.weight)]
        else:
            std_weights[o].append((i, cg.weight))
    #Create the array with the network's nodes
    nodes = []

    #Sometimes the output neurons end up not having any connections during the evolutionary process. While we do not
    #desire such networks, we should still allow them to make predictions to avoid fatal errors.
    for okey in output_keys:
        keys.add(okey)

    for k in keys:
        if k not in std_weights:
            std_weights[k] = []

    #While we cannot deduce the order of activations of the neurons due to the fact that we allow for arbitrary connection
    #schemes, we certainly want the output neurons to activate last.
    conns = {}
    for k in keys:
        conns[k] = [i for i, w in std_weights[k]]
    sorted_keys = order_of_activation(conns, input_keys, output_keys)

    #Create the nodes of the network based on the weights dictionaries created above and the genome.
    for node_key in sorted_keys:
        if node_key not in keys:
            continue
        node = genome.nodes[node_key]
        if node.is_switch:
            #If the node doesn't have any connections then it is not needed
            if node_key not in std_weights.keys(
            ) and node_key not in mod_weights.keys():
                continue
            #if the switch neuron only has modulatory weights then we copy those weights for the standard part as well.
            #this is not the desired behaviour but it is done to avoid errors during forward pass.
            if node_key not in std_weights.keys() and node_key in mod_weights:
                std_weights[node_key] = mod_weights[node_key]
            if node_key not in mod_weights.keys():
                mod_weights[node_key] = []
            nodes.append(
                SwitchNeuron(node_key, std_weights[node_key],
                             mod_weights[node_key]))
            continue

        if node_key not in std_weights:
            std_weights[node_key] = []

        #Create the standard part dictionary for the neuron
        params = {
            'activation_function':
            genome_config.activation_defs.get(node.activation),
            'integration_function':
            genome_config.aggregation_function_defs.get(node.aggregation),
            'bias':
            node.bias,
            'activity':
            0,
            'output':
            0,
            'weights':
            std_weights[node_key]
        }
        nodes.append(Neuron(node_key, params))

    return SwitchNeuronNetwork(input_keys, output_keys, nodes)
    def create(genome, config):
        genome_config = config.genome_config
        required = required_for_output(genome_config.input_keys, genome_config.output_keys, genome.connections)
        input_keys = genome_config.input_keys
        output_keys = genome_config.output_keys


        #A dictionary where we keep the standard weights for every node
        std_weights = {}
        #Create a set with the keys of the nodes in the network
        keys = set()
        #Iterate over the connections
        for cg in itervalues(genome.connections):
            #if not cg.enabled:
            #    continue

            i, o = cg.key
            #If neither of the nodes in the connection are required for output then skip this connection
            if o not in required and i not in required:
                continue

            if i not in input_keys:
                keys.add(i)
            keys.add(o)

            #Add the weight to the standard weight of the o node.
            if o not in std_weights.keys():
                std_weights[o] = [(i,cg.weight)]
            else:
                std_weights[o].append((i,cg.weight))
        #Create the array with the network's nodes
        nodes = []
        #Sometimes the output neurons end up not having any connections during the evolutionary process. While we do not
        #desire such networks, we should still allow them to make predictions to avoid fatal errors.
        for okey in output_keys:
            if okey not in keys:
                keys.add(okey)
                std_weights[okey] = []

        #Sometimes a neuron emerges which is only connected to the output neurons with an outgoing connection
        for k in keys:
            if k not in std_weights.keys():
                std_weights[k] = []
        #Deduce the order of activation of the neurons
        conns = {}
        for node in std_weights.keys():
            conns[node] = [inp for inp, weight in std_weights[node]]
        sorted_keys = order_of_activation(conns, input_keys, output_keys)

        #Create the nodes of the network based on the weights dictionaries created above and the genome.
        for node_key in sorted_keys:
            if node_key not in keys:
                continue
            node = genome.nodes[node_key]

            #Create the standard part dictionary for the neuron
            params = {
                'activation_function' : genome_config.activation_defs.get(node.activation),
                'integration_function' : genome_config.aggregation_function_defs.get(node.aggregation),
                'bias' : node.bias,
                'activity' : 0,
                'output' : 0,
                'weights' : std_weights[node_key]
            }
            nodes.append(Neuron(node_key,params))

        return RecurrentNetwork(input_keys,output_keys,nodes)
예제 #13
0
    def create(genome, config, map_size):
        """ Receives a genome and returns its phenotype (a MapNetwork). """
        genome_config = config.genome_config
        required = required_for_output(genome_config.input_keys,
                                       genome_config.output_keys,
                                       genome.connections)

        # Gather inputs and expressed connections.
        node_inputs = {}
        children = {}
        node_keys = list(
            genome.nodes.keys())[:]  #+ list(genome_config.input_keys[:])
        # for key in genome_config.input_keys + genome_config.output_keys:
        #     children[key] = []
        #     for i in range(1,map_size):
        #         if key < 0:
        #             new_idx = min(node_keys) - 1
        #         else:
        #             new_idx = max(node_keys) + 1
        #         children[key].append(new_idx)
        #         node_keys.append(new_idx)

        for cg in itervalues(genome.connections):
            if not cg.enabled:
                continue

            i, o = cg.key
            if o not in required and i not in required:
                continue

            for n in [i, o]:
                if n in children.keys():
                    continue
                children[n] = []
                if n in genome_config.input_keys or n in genome_config.output_keys:
                    continue
                if not genome.nodes[n].is_isolated:
                    for _ in range(1, map_size):
                        new_idx = max(node_keys) + 1
                        children[n].append(new_idx)
                        node_keys.append(new_idx)

            in_map = [i] + children[i]
            out_map = [o] + children[o]
            for n in out_map:
                if n not in node_inputs.keys():
                    node_inputs[n] = []

            if len(in_map) == map_size and len(out_map) == map_size:
                #Map to map connectivity
                if cg.one_to_one:
                    #1-to-1 mapping
                    weight = 5 * cg.weight
                    for i_n in range(map_size):
                        node_inputs[out_map[i_n]].append((in_map[i_n], weight))

                else:
                    #1-to-all
                    if cg.is_gaussian:
                        #Gaussian
                        for o_n in out_map:
                            for i_n in in_map:
                                node_inputs[o_n].append(
                                    (i_n,
                                     np.random.normal(cg.weight, cg.sigma)))
                    else:
                        #Uniform
                        for o_n in out_map:
                            for i_n in in_map:
                                node_inputs[o_n].append((i_n, 5 * cg.weight))

            else:
                #Map-to-isolated or isolated-to-isolated
                if cg.is_gaussian:
                    # Gaussian
                    for o_n in out_map:
                        for i_n in in_map:
                            node_inputs[o_n].append(
                                (i_n, np.random.normal(cg.weight, cg.sigma)))
                else:
                    # Uniform
                    for o_n in out_map:
                        for i_n in in_map:                            \
                                                        node_inputs[o_n].append((i_n, 5 * cg.weight))

        input_keys = genome_config.input_keys
        output_keys = genome_config.output_keys
        conns = {}
        for k in genome.nodes.keys():
            if k not in node_inputs:
                node_inputs[k] = []
                if k in children:
                    for c in children[k]:
                        node_inputs[c] = []
            conns[k] = [i for i, _ in node_inputs[k]]
        sorted_keys = order_of_activation(conns, input_keys, output_keys)
        nodes = []
        for node_key in sorted_keys:
            if node_key not in genome.nodes.keys():
                continue
            node = genome.nodes[node_key]

            activation_function = genome_config.activation_defs.get(
                node.activation)
            aggregation_function = genome_config.aggregation_function_defs.get(
                node.aggregation)
            nodes.append(
                Neuron(
                    node_key, {
                        'activation_function': activation_function,
                        'integration_function': aggregation_function,
                        'bias': node.bias,
                        'activity': 0,
                        'output': 0,
                        'weights': node_inputs[node_key]
                    }))

            if node_key not in children:
                continue

            for n in children[node_key]:
                nodes.append(
                    Neuron(
                        n, {
                            'activation_function': activation_function,
                            'integration_function': aggregation_function,
                            'bias': node.bias,
                            'activity': 0,
                            'output': 0,
                            'weights': node_inputs[n]
                        }))

        # for key in genome_config.input_keys:
        #     input_keys.append(key)
        #     if key in children.keys():
        #         for child in children[key]:
        #             input_keys.append(child)
        #
        # for key in genome_config.output_keys:
        #     output_keys.append(key)
        #     if key in children.keys():
        #         for child in children[key]:
        #             output_keys.append(child)

        return MapNetwork(input_keys, output_keys, nodes)
예제 #14
0
def create_cppn(genome,
                config,
                leaf_names,
                node_names,
                output_activation=None):
    """
    Create cppn as described in HyperNEAT (linked above)

    :param genome:
    :param config:
    :param leaf_names: names of  input nodes aka  input keys
    :param node_names: names of output nodes aka output keys
    :param output_activation:
    """

    genome_config = config.genome_config

    required = required_for_output(genome_config.input_keys,
                                   genome_config.output_keys,
                                   genome.connections)

    # for HyperNEAT, there should be exactly one output node here
    # so it should look like:
    # node_inputs = {0:[]}

    # Gather inputs and expressed connections. # incoming connections of each node i
    node_inputs = {i: [] for i in genome_config.output_keys}

    for cg in genome.connections.values():
        if not cg.enabled:
            continue

        i, o = cg.key
        if o not in required and i not in required:
            continue

        if i in genome_config.output_keys:
            continue

        if o not in node_inputs:
            node_inputs[o] = [(i, cg.weight)]
        else:
            node_inputs[o].append((i, cg.weight))

        if i not in node_inputs:
            node_inputs[i] = []
    # node inputs now contains for all nodes a list of tuples of incoming node, incoming weight

    # initialize set of all nodes with input nodes ("leaves")
    nodes = {i: Leaf() for i in genome_config.input_keys}

    assert len(leaf_names) == len(
        genome_config.input_keys), (leaf_names, genome_config.input_keys)
    leaves = {
        name: nodes[i]
        for name, i in zip(leaf_names, genome_config.input_keys)
    }

    def build_node(idx):
        # Depth first search
        if idx in nodes:  # already built node because its a leaf or its been built on different build_node DFS
            return nodes[idx]

        node = genome.nodes[idx]
        conns = node_inputs[idx]
        children = [build_node(i) for i, w in conns]
        weights = [w for i, w in conns]

        if idx in genome_config.output_keys and output_activation is not None:
            activation = output_activation
        else:
            activation = str_to_activation[node.activation]
        aggregation = str_to_aggregation[node.aggregation]
        nodes[idx] = Node(
            children,
            weights,
            node.response,
            node.bias,
            activation,
            aggregation,
            leaves=leaves,
        )
        return nodes[idx]

    for idx in genome_config.output_keys:
        # start DFS tree creation, starting at each output connection
        build_node(idx)

    outputs = [nodes[i] for i in genome_config.output_keys]

    # assign names to input nodes/input keys/leaves FIXME correct?
    for name in leaf_names:
        leaves[name].name = name

    # assign names to output nodes/output keys FIXME correct?
    for i, name in zip(genome_config.output_keys, node_names):
        nodes[i].name = name

    return outputs