Пример #1
0
    def __init__(self, params):

        # Create full set of available activation functions.
        self.activation_defs = ActivationFunctionSet()
        # ditto for aggregation functions - name difference for backward compatibility
        self.aggregation_function_defs = AggregationFunctionSet()

        self._params = [
            ConfigParameter('num_inputs', int),
            ConfigParameter('num_outputs', int),
            ConfigParameter('num_initial_states', int),
            ConfigParameter('max_num_states', int, 1000),  # Note the default.
            ConfigParameter('state_add_prob', float),
            ConfigParameter('state_delete_prob', float),
            ConfigParameter('transition_add_prob', float),
            ConfigParameter('transition_delete_prob', float),
            ConfigParameter('compatibility_disjoint_coefficient', float),
            ConfigParameter('compatibility_difference_coefficient', float)
        ]

        # Gather configuration data from the gene classes.
        self.node_gene_type = params['node_gene_type']
        self._params += self.node_gene_type.get_config_params()
        self.connection_gene_type = params['connection_gene_type']
        self._params += self.connection_gene_type.get_config_params()

        # Use the configuration data to interpret the supplied parameters.
        for p in self._params:
            setattr(self, p.name, p.interpret(params))

        self.node_indexer = self.num_initial_states
Пример #2
0
def compare_state_outcomes(genome, sensor_input_file):
    # This function evaluates the difference of the states by running it on a randomly generated set
    # input values and reporting the distance between the output vectors of the states.

    # Load the randomly generated sensor inputs
    with open(sensor_input_file, 'r') as csv_file:
        csv_reader = csv.reader(csv_file, quoting=csv.QUOTE_NONNUMERIC)

        sensor_vectors = [row for row in csv_reader]

    # Evaluate the sensor inputs on each genome.
    state_differences = dict()

    activations = ActivationFunctionSet()
    aggregations = AggregationFunctionSet()
    for enc_state1 in itervalues(genome.states):

        state1 = State(1, enc_state1.weights, enc_state1.biases,
                       aggregations.get(enc_state1.aggregation),
                       activations.get(enc_state1.activation))

        for enc_state2 in itervalues(genome.states):

            key_pair = (enc_state1.key, enc_state2.key)
            if key_pair[0] != key_pair[1] and key_pair not in state_differences \
                    and key_pair[::-1] not in state_differences:

                state2 = State(2, enc_state2.weights, enc_state2.biases,
                               aggregations.get(enc_state2.aggregation),
                               activations.get(enc_state2.activation))

                output_pairs = [(state1.activate(inputs),
                                 state2.activate(inputs))
                                for inputs in sensor_vectors]
                distances = [
                    np.average(
                        np.abs(
                            np.array(output_pair[0]) -
                            np.array(output_pair[1])))
                    for output_pair in output_pairs
                ]

                state_differences[key_pair] = np.average(distances), np.std(
                    distances)

    return state_differences
Пример #3
0
    def __init__(self, params):
        # Create full set of available activation functions.
        self.activation_defs = ActivationFunctionSet()
        # ditto for aggregation functions - name difference for backward compatibility
        self.aggregation_function_defs = AggregationFunctionSet()
        self.aggregation_defs = self.aggregation_function_defs

        self._params = [
            ConfigParameter('num_inputs', int),
            ConfigParameter('num_outputs', int),
            ConfigParameter('num_hidden', int),
            ConfigParameter('feed_forward', bool),
            ConfigParameter('no_output_loopbacks', bool),
            ConfigParameter('compatibility_disjoint_coefficient', float),
            ConfigParameter('compatibility_weight_coefficient', float),
            ConfigParameter('conn_add_prob', float),
            ConfigParameter('conn_delete_prob', float),
            ConfigParameter('node_add_prob', float),
            ConfigParameter('node_delete_prob', float),
            ConfigParameter('single_structural_mutation', bool, 'false'),
            ConfigParameter('structural_mutation_surer', str, 'default'),
            ConfigParameter('initial_connection', str, 'unconnected')
        ]

        # Gather configuration data from the gene classes.
        self.node_gene_type = params['node_gene_type']
        self._params += self.node_gene_type.get_config_params()
        self.connection_gene_type = params['connection_gene_type']
        self._params += self.connection_gene_type.get_config_params()

        # Use the configuration data to interpret the supplied parameters.
        for p in self._params:
            setattr(self, p.name, p.interpret(params))

        # By convention, input pins have negative keys, and the output
        # pins have keys 0,1,...
        self.input_keys = [-i - 1 for i in range(self.num_inputs)]
        self.output_keys = [i for i in range(self.num_outputs)]

        self.connection_fraction = None

        # Verify that initial connection type is valid.
        # pylint: disable=access-member-before-definition
        if 'partial' in self.initial_connection:
            c, p = self.initial_connection.split()
            self.initial_connection = c
            self.connection_fraction = float(p)
            if not (0 <= self.connection_fraction <= 1):
                raise RuntimeError(
                    "'partial' connection value must be between 0.0 and 1.0, inclusive."
                )

        assert self.initial_connection in self.allowed_connectivity

        # Verify structural_mutation_surer is valid.
        # pylint: disable=access-member-before-definition
        if self.structural_mutation_surer.lower() in [
                '1', 'yes', 'true', 'on'
        ]:
            self.structural_mutation_surer = 'true'
        elif self.structural_mutation_surer.lower() in [
                '0', 'no', 'false', 'off'
        ]:
            self.structural_mutation_surer = 'false'
        elif self.structural_mutation_surer.lower() == 'default':
            self.structural_mutation_surer = 'default'
        else:
            error_string = "Invalid structural_mutation_surer {!r}".format(
                self.structural_mutation_surer)
            raise RuntimeError(error_string)

        self.node_indexer = None
Пример #4
0
class DefaultGenomeConfig(object):
    """Sets up and holds configuration information for the DefaultGenome class."""
    allowed_connectivity = [
        'unconnected', 'fs_neat_nohidden', 'fs_neat', 'fs_neat_hidden',
        'full_nodirect', 'full', 'full_direct', 'partial_nodirect', 'partial',
        'partial_direct'
    ]

    def __init__(self, params):
        # Create full set of available activation functions.
        self.activation_defs = ActivationFunctionSet()
        # ditto for aggregation functions - name difference for backward compatibility
        self.aggregation_function_defs = AggregationFunctionSet()
        self.aggregation_defs = self.aggregation_function_defs

        self._params = [
            ConfigParameter('num_inputs', int),
            ConfigParameter('num_outputs', int),
            ConfigParameter('num_hidden', int),
            ConfigParameter('feed_forward', bool),
            ConfigParameter('no_output_loopbacks', bool),
            ConfigParameter('compatibility_disjoint_coefficient', float),
            ConfigParameter('compatibility_weight_coefficient', float),
            ConfigParameter('conn_add_prob', float),
            ConfigParameter('conn_delete_prob', float),
            ConfigParameter('node_add_prob', float),
            ConfigParameter('node_delete_prob', float),
            ConfigParameter('single_structural_mutation', bool, 'false'),
            ConfigParameter('structural_mutation_surer', str, 'default'),
            ConfigParameter('initial_connection', str, 'unconnected')
        ]

        # Gather configuration data from the gene classes.
        self.node_gene_type = params['node_gene_type']
        self._params += self.node_gene_type.get_config_params()
        self.connection_gene_type = params['connection_gene_type']
        self._params += self.connection_gene_type.get_config_params()

        # Use the configuration data to interpret the supplied parameters.
        for p in self._params:
            setattr(self, p.name, p.interpret(params))

        # By convention, input pins have negative keys, and the output
        # pins have keys 0,1,...
        self.input_keys = [-i - 1 for i in range(self.num_inputs)]
        self.output_keys = [i for i in range(self.num_outputs)]

        self.connection_fraction = None

        # Verify that initial connection type is valid.
        # pylint: disable=access-member-before-definition
        if 'partial' in self.initial_connection:
            c, p = self.initial_connection.split()
            self.initial_connection = c
            self.connection_fraction = float(p)
            if not (0 <= self.connection_fraction <= 1):
                raise RuntimeError(
                    "'partial' connection value must be between 0.0 and 1.0, inclusive."
                )

        assert self.initial_connection in self.allowed_connectivity

        # Verify structural_mutation_surer is valid.
        # pylint: disable=access-member-before-definition
        if self.structural_mutation_surer.lower() in [
                '1', 'yes', 'true', 'on'
        ]:
            self.structural_mutation_surer = 'true'
        elif self.structural_mutation_surer.lower() in [
                '0', 'no', 'false', 'off'
        ]:
            self.structural_mutation_surer = 'false'
        elif self.structural_mutation_surer.lower() == 'default':
            self.structural_mutation_surer = 'default'
        else:
            error_string = "Invalid structural_mutation_surer {!r}".format(
                self.structural_mutation_surer)
            raise RuntimeError(error_string)

        self.node_indexer = None

    def add_activation(self, name, func):
        self.activation_defs.add(name, func)

    def add_aggregation(self, name, func):
        self.aggregation_function_defs.add(name, func)

    def save(self, f):
        if 'partial' in self.initial_connection:
            if not (0 <= self.connection_fraction <= 1):
                raise RuntimeError(
                    "'partial' connection value must be between 0.0 and 1.0, inclusive."
                )
            f.write('initial_connection      = {0} {1}\n'.format(
                self.initial_connection, self.connection_fraction))
        else:
            f.write('initial_connection      = {0}\n'.format(
                self.initial_connection))

        assert self.initial_connection in self.allowed_connectivity

        write_pretty_params(
            f, self,
            [p for p in self._params if 'initial_connection' not in p.name])

    def get_new_node_key(self, node_dict):
        if self.node_indexer is None:
            self.node_indexer = count(max(list(node_dict)) + 1)

        new_id = next(self.node_indexer)

        assert new_id not in node_dict

        return new_id

    def check_structural_mutation_surer(self):
        if self.structural_mutation_surer == 'true':
            return True
        elif self.structural_mutation_surer == 'false':
            return False
        elif self.structural_mutation_surer == 'default':
            return self.single_structural_mutation
        else:
            error_string = "Invalid structural_mutation_surer {!r}".format(
                self.structural_mutation_surer)
            raise RuntimeError(error_string)
Пример #5
0
    def __init__(
        self,
        params: Dict[str, Union[str, Type[DefaultNodeGene],
                                Type[DefaultConnectionGene]]],
    ) -> None:
        # parameters
        self.conn_delete_prob: float = 0
        self.node_delete_prob: float = 0
        self.compatibility_disjoint_coefficient: float = 0
        self.compatibility_weight_coefficient: float = 0
        self.conn_add_prob: float = 0
        self.feed_forward: bool = True
        self.node_add_prob: float = 0
        self.num_inputs: int = 0
        self.num_hidden: int = 0
        self.num_outputs: int = 0
        self.single_structural_mutation: bool = False
        self.node_gene_type: DefaultNodeGene
        self.connection_gene_type: DefaultConnectionGene

        # Create full set of available activation functions.
        self.activation_defs: ActivationFunctionSet = ActivationFunctionSet()
        # ditto for aggregation functions - name difference for backward compatibility
        self.aggregation_function_defs: AggregationFunctionSet = (
            AggregationFunctionSet())
        self.aggregation_defs: AggregationFunctionSet = self.aggregation_function_defs

        self._params: List[ConfigParameter] = [
            ConfigParameter("num_inputs", int),
            ConfigParameter("num_outputs", int),
            ConfigParameter("num_hidden", int),
            ConfigParameter("feed_forward", bool),
            ConfigParameter("compatibility_disjoint_coefficient", float),
            ConfigParameter("compatibility_weight_coefficient", float),
            ConfigParameter("conn_add_prob", float),
            ConfigParameter("conn_delete_prob", float),
            ConfigParameter("node_add_prob", float),
            ConfigParameter("node_delete_prob", float),
            ConfigParameter("single_structural_mutation", bool, "false"),
            ConfigParameter("structural_mutation_surer", str, "default"),
            ConfigParameter("initial_connection", str, "unconnected"),
        ]

        # Gather configuration data from the gene classes.
        self.node_gene_type: Type[DefaultNodeGene] = params["node_gene_type"]
        self._params += self.node_gene_type.get_config_params()
        self.connection_gene_type: Type[DefaultConnectionGene] = params[
            "connection_gene_type"]
        self._params += self.connection_gene_type.get_config_params()

        # Use the configuration data to interpret the supplied parameters.
        # `num_inputs`, `num_outputs`などGenomeに関するプロパティを型を解釈してクラスメンバに実数値を設定する
        for p in self._params:
            setattr(self, p.name, p.interpret(params))

        # By convention, input pins have negative keys, and the output
        # pins have keys 0,1,...
        self.input_keys: List[int] = [-i - 1 for i in range(self.num_inputs)]
        self.output_keys: List[int] = [i for i in range(self.num_outputs)]

        self.connection_fraction = None

        # Verify that initial connection type is valid.
        # pylint: disable=access-member-before-definition
        if "partial" in self.initial_connection:
            c, p = self.initial_connection.split()
            self.initial_connection = c
            self.connection_fraction = float(p)
            if not (0 <= self.connection_fraction <= 1):
                raise RuntimeError(
                    "'partial' connection value must be between 0.0 and 1.0, inclusive."
                )

        assert self.initial_connection in self.allowed_connectivity

        # Verify structural_mutation_surer is valid.
        # pylint: disable=access-member-before-definition
        if self.structural_mutation_surer.lower() in [
                "1", "yes", "true", "on"
        ]:
            self.structural_mutation_surer = "true"
        elif self.structural_mutation_surer.lower() in [
                "0", "no", "false", "off"
        ]:
            self.structural_mutation_surer = "false"
        elif self.structural_mutation_surer.lower() == "default":
            self.structural_mutation_surer = "default"
        else:
            error_string = "Invalid structural_mutation_surer {!r}".format(
                self.structural_mutation_surer)
            raise RuntimeError(error_string)

        self.node_indexer: Optional[count] = None