예제 #1
0
    def test_crossover(self):
        genome1 = Genome(self.genome_params)
        genome2 = Genome(self.genome_params)
        genome1.connect()
        genome2.connect()

        genome1.fitness = 5
        genome2.fitness = 20

        genome2.mutate()

        assert len(genome2.nodes) == 4
        assert len(genome2.connection_genes) == 4
        assert genome2.connection_genes[3].innovation_number == 4

        disabled_gene = None
        for idx, cg in enumerate(genome2.connection_genes):
            if not cg.enabled:
                disabled_gene = idx
                break

        child = genome2.crossover(genome1, genome2)

        # child inherited fittest parent nodes
        assert len(child.nodes) == len(genome2.nodes)
        # should be of same length despite some being disjoint genes
        assert len(child.connection_genes) == len(genome2.connection_genes)
        # check child got disabled gene transferred
        assert not child.connection_genes[disabled_gene].enabled
예제 #2
0
	def test_mate(self):
		Genome.reset()

		genome1 = Genome()
		genome2 = Genome()
		new_genome = Genome()
		genes1 = []
		genes2 = []

		genome1.allocate_hidden_nodes(1)
		genome2.allocate_hidden_nodes(1)
		new_genome.allocate_hidden_nodes(1)

		#genome 1
		input_node_id_11 = genome1.add_input_node()
		input_node_id_21 = genome1.add_input_node()

		hidden_node_id_11 = genome1.add_hidden_node()

		output_node_id_11 = genome1.add_output_node()
		output_node_id_21 = genome1.add_output_node()

		genes1.append(Gene(input_node_id_11, hidden_node_id_11, weight = 10.0))
		genes1.append(Gene(input_node_id_21, hidden_node_id_11))

		genes1.append(Gene(hidden_node_id_11, output_node_id_11))
		genes1.append(Gene(hidden_node_id_11, output_node_id_21))

		genome1.set_genes((genes1))

		#genome 2
		input_node_id_12 = genome2.add_input_node()
		input_node_id_22 = genome2.add_input_node()

		hidden_node_id_12 = genome2.add_hidden_node()

		output_node_id_12 = genome2.add_output_node()
		output_node_id_22 = genome2.add_output_node()

		genes2.append(Gene(input_node_id_12, hidden_node_id_12, weight = 20.0))
		genes2.append(Gene(input_node_id_22, hidden_node_id_12))

		genes2.append(Gene(hidden_node_id_12, output_node_id_12))
		genes2.append(Gene(hidden_node_id_12, output_node_id_22, enabled = False))

		genome2.set_genes((genes2))
		genome2.allocate_genes(1)

		genome2.add_new_connection(input_node_id_12, output_node_id_12)

		#new genome
		Genome.mate(genome1, genome2, new_genome)

		self.assertEqual(new_genome.genes[0].weight, 15.0)
		self.assertEqual(len(new_genome.genes), 5)
		self.assertFalse(new_genome.genes[3].enabled)
예제 #3
0
def generate_genome_with_hidden_units(n_input, n_output, n_hidden=3):
    # nodes
    node_genes = {}
    for i in range(n_output + n_hidden):
        node_genes = add_node(node_genes, key=i)

    # connections
    # input to hidden
    connection_genes = {}
    input_hidden_tuples = list(
        product(list(range(-1, -n_input - 1, -1)),
                list(range(n_output, n_output + n_hidden))))
    for tuple_ in input_hidden_tuples:
        connection_genes = add_connection(connection_genes, key=tuple_)

    # hidden to output
    hidden_output_tuples = list(
        product(list(range(n_output, n_output + n_hidden)),
                list(range(0, n_output))))
    for tuple_ in hidden_output_tuples:
        connection_genes = add_connection(connection_genes, key=tuple_)

    # initialize genome
    genome = Genome(key=1)
    genome.node_genes = node_genes
    genome.connection_genes = connection_genes
    return genome
예제 #4
0
	def test_add_node(self):
		Genome.reset()

		genome = Genome()

		genome.allocate_hidden_nodes(3)

		input_node_id_1 = genome.add_input_node()
		input_node_id_2 = genome.add_input_node()

		hidden_node_id_1 = genome.add_hidden_node()
		hidden_node_id_2 = genome.add_hidden_node()
		hidden_node_id_3 = genome.add_hidden_node()

		output_node_id_1 = genome.add_output_node()
		output_node_id_2 = genome.add_output_node()

		#Inserted check
		self.assertTrue(input_node_id_1 in range(len(genome.nodes)))
		self.assertTrue(input_node_id_2 in range(len(genome.nodes)))

		self.assertTrue(hidden_node_id_1 in range(len(genome.nodes)))
		self.assertTrue(hidden_node_id_2 in range(len(genome.nodes)))
		self.assertTrue(hidden_node_id_3 in range(len(genome.nodes)))

		self.assertTrue(output_node_id_1 in range(len(genome.nodes)))
		self.assertTrue(output_node_id_2 in range(len(genome.nodes)))

		#Added to output ndoes check
		self.assertFalse(input_node_id_1 in genome.output_nodes_ids)
		self.assertFalse(input_node_id_2 in genome.output_nodes_ids)

		self.assertFalse(hidden_node_id_1 in genome.output_nodes_ids)
		self.assertFalse(hidden_node_id_2 in genome.output_nodes_ids)
		self.assertFalse(hidden_node_id_3 in genome.output_nodes_ids)

		self.assertTrue(output_node_id_1 in genome.output_nodes_ids)
		self.assertTrue(output_node_id_2 in genome.output_nodes_ids)

		#Type set check
		self.assertEqual(genome.nodes[input_node_id_1].type, Type.INPUT)
		self.assertEqual(genome.nodes[input_node_id_2].type, Type.INPUT)

		self.assertEqual(genome.nodes[hidden_node_id_1].type, Type.HIDDEN)
		self.assertEqual(genome.nodes[hidden_node_id_2].type, Type.HIDDEN)
		self.assertEqual(genome.nodes[hidden_node_id_3].type, Type.HIDDEN)

		self.assertEqual(genome.nodes[output_node_id_1].type, Type.OUTPUT)
		self.assertEqual(genome.nodes[output_node_id_2].type, Type.OUTPUT)

		#ID set check
		self.assertEqual(genome.nodes[input_node_id_1].id, input_node_id_1)
		self.assertEqual(genome.nodes[input_node_id_2].id, input_node_id_2)

		self.assertEqual(genome.nodes[hidden_node_id_1].id, hidden_node_id_1)
		self.assertEqual(genome.nodes[hidden_node_id_2].id, hidden_node_id_2)
		self.assertEqual(genome.nodes[hidden_node_id_3].id, hidden_node_id_3)

		self.assertEqual(genome.nodes[output_node_id_1].id, output_node_id_1)
		self.assertEqual(genome.nodes[output_node_id_2].id, output_node_id_2)
예제 #5
0
    def initialze_network(self, **kwargs):
        number_hidden_nodes = kwargs['number_hidden_nodes']
        number_genes = kwargs['number_genes']
        new_weight_range = kwargs['new_weight_range']
        genome = Genome()
        genes = []

        genome.allocate_hidden_nodes(number_hidden_nodes)

        self.input_node1 = genome.add_input_node()
        self.input_node2 = genome.add_input_node()

        self.output_node = genome.add_output_node()

        genes.append(
            Gene(0, self.output_node,
                 new_weight_range - 2 * new_weight_range * random.random()))
        genes.append(
            Gene(self.input_node1, self.output_node,
                 new_weight_range - 2 * new_weight_range * random.random()))
        genes.append(
            Gene(self.input_node2, self.output_node,
                 new_weight_range - 2 * new_weight_range * random.random()))

        genome.set_genes(genes)

        genome.allocate_genes(number_genes)

        return Network(genome)
예제 #6
0
    def fully_connected_nn(n_inputs, n_outputs):
        """Generate a genotype representing a fully connected neural network.

        Arguments:
            n_inputs: How many inputs the network should have.
            n_outputs: How many outputs the network should have.

        Returns: The generated genotype.
        """
        genome = Genome()

        sensors = [NodeGene(Sensor()) for _ in range(n_inputs)]
        outputs = [NodeGene(Output()) for _ in range(n_outputs)]

        connections = []

        for input_id in range(n_inputs):
            for output_id in range(n_inputs, n_inputs + n_outputs):
                connections.append(ConnectionGene(output_id, input_id))

        genome.add_genes(sensors)
        genome.add_genes(outputs)
        genome.add_genes(connections)

        return genome
예제 #7
0
    def test_regression_case(self):
        config = create_configuration(filename='/regression-siso.json')
        config.parallel_evaluation = False

        genome = Genome(key=1)
        genome.create_random_genome()

        dataset = get_dataset(config.dataset,
                              train_percentage=config.train_percentage,
                              testing=True)

        n_samples = 3
        network = ComplexStochasticNetwork(genome=genome)

        x, y_true, output_distribution = calculate_prediction_distribution(
            network,
            dataset=dataset,
            problem_type=config.problem_type,
            is_testing=True,
            n_samples=n_samples,
            use_sigmoid=False)
        expected_output_distribution_shape = [
            len(y_true), n_samples, config.n_output
        ]
        self.assertEqual(list(output_distribution.shape),
                         expected_output_distribution_shape)
예제 #8
0
def _breed(parents):
    # create a new child with topology size at least as big as either parents
    child = Genome(parents[0].x_dim, parents[0].y_dim, random_weights=False)
    child.h_dim = max(parents[0].h_dim, parents[1].h_dim)

    # if both parents have h_dim = 1, then randomly mix weights
    # otherwise, breed them by crossover
    if parents[0].h_dim == 1 and parents[1].h_dim == 1:
        w1 = mix_weights(parents[0].w1, parents[1].w1)
        w2 = mix_weights(parents[0].w2, parents[1].w2)
    else:
        if parents[0].h_dim < parents[1].h_dim:
            small_genome = parents[0]
            large_genome = parents[1]
        else:
            small_genome = parents[1]
            large_genome = parents[0]
        slice_idx = np.random.randint(1, small_genome.h_dim + 1)
        w1 = np.vstack(
            [small_genome.w1[:slice_idx], large_genome.w1[slice_idx:]])
        w2 = np.hstack(
            [small_genome.w2[:, :slice_idx], large_genome.w2[:, slice_idx:]])

    child.w1 = w1
    child.w2 = w2

    child.genome_type = "bred"
    return child
예제 #9
0
 def test_genome_only_links_to_valid_nodes(self):
     link_tester = [LinkGene(0, 3), LinkGene(1, 3), LinkGene(2, 4), LinkGene(0, 5)]
     try:
         genome = Genome(self.config, node_genes=self.test_node_genes, link_genes=link_tester)
         self.fail("Genome should raise exception if link connects to non-existing node")
     except ValueError:
         pass
예제 #10
0
 def test_genome_doesnt_create_inputs_as_sinks(self):
     link_tester = [LinkGene(0, 1), LinkGene(3, 2), LinkGene(2, 4)]
     try:
         genome = Genome(self.config, node_genes=self.test_node_genes, link_genes=link_tester)
         self.fail("Genome should raise exception if input is sink")
     except ValueError:
         pass
예제 #11
0
 def test_genome_doesnt_create_duplicate_links(self):
     link_tester = [LinkGene(0, 3), LinkGene(1, 3), LinkGene(2, 4)]
     try:
         genome = Genome(self.config, node_genes=self.test_node_genes, link_genes=link_tester)
         self.fail("Genome should raise exception if duplicate links exist")
     except AssertionError:
         pass
예제 #12
0
    def get_offspring(self, offspring_key, genome1: Genome, genome2: Genome):
        assert isinstance(genome1.fitness, (int, float))
        assert isinstance(genome2.fitness, (int, float))
        if genome1.fitness > genome2.fitness:
            parent1, parent2 = genome1, genome2
        else:
            parent1, parent2 = genome2, genome1

        offspring = Genome(key=offspring_key)

        # Inherit connection genes
        for key, cg1 in parent1.connection_genes.items():
            cg2 = parent2.connection_genes.get(key)
            if cg2 is None:
                # Excess or disjoint gene: copy from the fittest parent.
                logger.debug('Use connection copy')
                offspring.connection_genes[key] = cg1.copy()
            else:
                # Homologous gene: combine genes from both parents.
                offspring.connection_genes[
                    key] = self._get_connection_crossover(cg1, cg2)

        # Inherit node genes
        for key, ng1 in parent1.node_genes.items():
            ng2 = parent2.node_genes.get(key)
            assert key not in offspring.node_genes
            if ng2 is None:
                # Extra gene: copy from the fittest parent
                logger.debug('Use node copy')
                offspring.node_genes[key] = ng1.copy()
            else:
                # Homologous gene: combine genes from both parents.
                offspring.node_genes[key] = self._get_node_crossover(ng1, ng2)
        return offspring
예제 #13
0
	def test_add_gene(self):
		Genome.reset()

		genome = Genome()
		genes = []

		genome.allocate_hidden_nodes(1)

		input_node_id_1 = genome.add_input_node()
		input_node_id_2 = genome.add_input_node()

		hidden_node_id_1 = genome.add_hidden_node()

		output_node_id_1 = genome.add_output_node()
		output_node_id_2 = genome.add_output_node()

		genes.append(Gene(input_node_id_1, hidden_node_id_1))
		genes.append(Gene(input_node_id_2, hidden_node_id_1))

		genes.append(Gene(hidden_node_id_1, output_node_id_1))
		genes.append(Gene(hidden_node_id_1, output_node_id_2))

		genome.set_genes((genes))

		gene = Gene(input_node_id_1, output_node_id_1)

		genome.add_gene(gene)

		self.assertEqual(genome.nodes[output_node_id_1].connected_nodes[1], genome.nodes[input_node_id_1])
예제 #14
0
def generate_genome_given_graph(graph, connection_weights):
    genome = Genome(key='foo')

    unique_node_keys = []
    input_nodes = []
    for connection in graph:
        for node_key in connection:
            if node_key not in unique_node_keys:
                unique_node_keys.append(node_key)

            if node_key < 0:
                input_nodes.append(node_key)
    input_nodes = set(input_nodes)

    unique_node_keys = list(
        set(unique_node_keys + genome.get_output_nodes_keys()) - input_nodes)
    nodes = {}
    for node_key in unique_node_keys:
        node = NodeGene(key=node_key).random_initialization()
        node.set_mean(0)
        node.set_std(STD)
        nodes[node_key] = node

    connections = {}
    for connection_key, weight in zip(graph, connection_weights):
        connection = ConnectionGene(key=connection_key)
        connection.set_mean(weight)
        connection.set_std(STD)
        connections[connection_key] = connection

    genome.connection_genes = connections
    genome.node_genes = nodes
    return genome
예제 #15
0
 def test_genome_does_not_allow_duplicate_node_indices(self):
     print(len(self.test_node_genes))
     self.test_node_genes[0].idx = 1
     self.test_node_genes[1].idx = 1
     try:
         genome = Genome(self.config, node_genes=self.test_node_genes)
     except AssertionError:
         pass
예제 #16
0
 def test_genome_needs_right_number_output_genes(self):
     try:
         self.config.num_outputs = 3
         genome = Genome(self.config, node_genes=self.test_node_genes)
         self.config.num_outputs = 2
         self.fail("Should raise exception if n_outputs does not match number of output genes")
     except AssertionError:
         pass
예제 #17
0
    def test_mutate_delete_connection(self):
        genome = Genome(key='foo').create_random_genome()

        possible_connections_to_delete = \
            set(ArchitectureMutation._calculate_possible_connections_to_delete(genome=genome))
        expected_possible_connections_to_delete = {(-1, 0), (-2, 0)}
        self.assertSetEqual(expected_possible_connections_to_delete,
                            possible_connections_to_delete)
    def create(self):
        genomes = []
        for i in range(self.genome_params.population_size):
            g = Genome(self.genome_params)
            g.connect()
            genomes.append(g)

        return genomes
예제 #19
0
 def test_draw_random_phenome(self):
     self.config.num_inputs = 3
     self.config.num_outputs = 3
     gen = Genome(self.config)
     phenome = FeedForwardPhenome(genome=gen, config=self.config)
     self.config.num_inputs = 2
     self.config.num_outputs = 2
     phenome.draw(testing=True)
예제 #20
0
 def setUp(self):
     self.config = Config('../tests/conf_tester.conf')
     NodeGene.counter = 1
     LinkGene.innovation_counter = 0
     self.test_node_genes = [NodeGene(node_type='INPUT',),
                             NodeGene(node_type='INPUT'),
                             NodeGene(node_type='OUTPUT'),
                             NodeGene(node_type='OUTPUT')]
     self.test_link_genes = [LinkGene(2, 3, weight=1), LinkGene(1, 3, weight=1)]
     self.genome = Genome(self.config, node_genes=self.test_node_genes, link_genes=self.test_link_genes)
예제 #21
0
 def test_randomly_created_genome(self):
     config = self.config
     config.num_outputs = 3
     config.num_inputs = 3
     genome = Genome(config)
     self.config = Config('../tests/conf_tester.conf')
     assert len(genome.output_genes) == 3, \
         "Genome should have 3 outputs, has %i" % len(genome.output_genes)
     assert len(genome.input_genes) == 3, \
         "Genome should have 3 inputs, has %i" % len(genome.input_genes)
예제 #22
0
    def test_write_and_read_geneme(self):
        filename = self.path + '/genome_test.json'
        genome = Genome(key=0)
        genome.create_random_genome()

        genome.save_genome(filename)

        genome_read = Genome.create_from_file(filename)

        self.assertEqual(len(genome.__dict__), len(genome_read.__dict__))
예제 #23
0
    def test_mutate_delete_connection_when_two_input_one_hidden(self):
        self.config.n_initial_hidden_neurons = 1
        genome = Genome(key='foo').create_random_genome()

        possible_connections_to_delete = set(
            ArchitectureMutation._calculate_possible_connections_to_delete(
                genome=genome))
        expected_possible_connections_to_delete = {(-1, 1), (-2, 1), (1, 0)}
        self.assertSetEqual(expected_possible_connections_to_delete,
                            possible_connections_to_delete)
예제 #24
0
def generate_genome_without_hidden_units():
    # output nodes
    node_genes = {}
    node_genes = add_node(node_genes, key=0)

    connection_genes = {}
    connection_genes = add_connection(connection_genes, key=(-1, 0))
    connection_genes = add_connection(connection_genes, key=(-2, 0))

    genome = Genome(key=1)
    genome.node_genes = node_genes
    genome.connection_genes = connection_genes
    return genome
예제 #25
0
    def test_classification_case(self):
        config = create_configuration(filename='/classification-miso.json')
        genome = Genome(key=1)
        genome.create_random_genome()
        n_samples = 5

        estimator = PredictionDistributionEstimatorGenome(genome=genome, config=config, testing=True,
                                                          n_samples=n_samples)\
            .estimate() \
            .enrich_with_dispersion_quantile() \
            .calculate_metrics_by_dispersion_quantile()

        results = estimator.results
        self.assertTrue(isinstance(results, pd.DataFrame))
예제 #26
0
    def initialize_population(self):
        population = {}
        for i in range(self.pop_size):
            key = next(self.genome_indexer)
            if self.config.initial_genome_filename is None:
                genome = Genome(key=key)
                genome.create_random_genome()
            else:
                filename = self.config.initial_genome_filename
                genome = Genome.create_from_file(filename=filename, key=key)

            population[key] = genome
            self.ancestors[key] = tuple()
        return population
예제 #27
0
    def __init__(self, population_size, num_inputs, num_outputs):
        self.population_size = population_size

        # We initially create random-weighted organisms
        self.organisms = []
        for _ in range(population_size):
            self.organisms.append(Organism(Genome(num_inputs, num_outputs)))

        # The global innovation counter is used to assign unique ids to innovations across generations
        self.global_innovation_counter = UniqueId(num_outputs)
        # The global node counter is used to assign unique ids to nodes across organisms
        self.global_node_counter = UniqueId(num_inputs + 1 + num_outputs)
        # The global species counter is used to assign unique ids to species across generations
        self.global_species_counter = UniqueId()

        self.species = []
예제 #28
0
    def __init__(self, num_input, num_output, pop_size=POP_SIZE):
        self.generation = 1
        self.num_input = num_input
        self.num_output = num_output

        self.pop_size = pop_size
        self.num_survive = int(self.pop_size * SURVIVE_RATE)
        self.num_mutate = int(self.pop_size * MUTATE_RATE)
        self.num_breed = self.pop_size - int(self.num_survive +
                                             self.num_mutate)
        self.num_diverge = int(self.pop_size * DIVERGE_RATE)

        # creation of initial gene pool
        self.genomes = [
            Genome(self.num_input, self.num_output)
            for _ in range(self.pop_size)
        ]

        return
예제 #29
0
	def test_add_new_connection(self):
		Genome.reset()

		genome = Genome()
		genes = []

		genome.allocate_hidden_nodes(1)

		input_node_id_1 = genome.add_input_node()
		input_node_id_2 = genome.add_input_node()

		hidden_node_id_1 = genome.add_hidden_node()

		output_node_id_1 = genome.add_output_node()
		output_node_id_2 = genome.add_output_node()

		genes.append(Gene(input_node_id_1, hidden_node_id_1))
		genes.append(Gene(input_node_id_2, hidden_node_id_1))

		genes.append(Gene(hidden_node_id_1, output_node_id_1))
		genes.append(Gene(hidden_node_id_1, output_node_id_2))

		genome.set_genes((genes))
		genome.allocate_genes(1)

		connected = genome.add_new_connection(input_node_id_1, output_node_id_1)

		self.assertEqual(genome.nodes[output_node_id_1].connected_nodes[1], genome.nodes[input_node_id_1])
		self.assertTrue(connected)

		connected1 = genome.add_new_connection(input_node_id_1, input_node_id_2)
		connected2 = genome.add_new_connection(output_node_id_1, output_node_id_2)
		connected3 = genome.add_new_connection(output_node_id_2, hidden_node_id_1)
		connected4 = genome.add_new_connection(output_node_id_2, input_node_id_1)

		self.assertFalse(connected1)
		self.assertFalse(connected2)
		self.assertFalse(connected3)
		self.assertFalse(connected4)
예제 #30
0
    def cross(self, genome1, genome2, gene_tracker):
        child_genome = Genome()
        for node in genome1.nodes:
            child_genome.add_node(node.copy())

        for connection in genome1.connections:
            new_connection = connection.copy()
            if genome2.contains_connection(new_connection.in_node_id,
                                           new_connection.out_node_id):
                other_connection = genome2.get_connection(
                    new_connection.in_node_id, new_connection.out_node_id)
                if not new_connection.enabled or not other_connection.enabled:
                    should_enable = random.random() > self.disable_probability
                    if new_connection.enabled != should_enable:
                        new_connection.disable(
                        ) if new_connection.enabled else new_connection.enable(
                        )
                if random.choice([True, False]):
                    new_connection.weight = other_connection.weight
            child_genome.add_connection(new_connection)

        return child_genome