def test_genotype_lifetime(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') universe = darwin.create_universe(path) population = darwin.Population('cne.feedforward') domain = darwin.Domain('tic_tac_toe') population.size = 10 experiment = universe.new_experiment(domain, population) experiment.initialize_population() genotype = population[0] json_checkpoint_1 = genotype.to_json() experiment.evaluate_population() # this is fine, although our genotype may be ranked to a different index now json_checkpoint_2 = genotype.to_json() experiment.create_next_generation() # the old genotype is no longer owned by the population json_checkpoint_3 = genotype.to_json() experiment.reset() # the old population is no longer owned by the experiment json_checkpoint_4 = genotype.to_json() self.assertEqual(json_checkpoint_1, json_checkpoint_2) self.assertEqual(json_checkpoint_1, json_checkpoint_3) self.assertEqual(json_checkpoint_1, json_checkpoint_4)
def test_basic_evolution(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') universe = darwin.create_universe(path) population = darwin.Population('neat') population.size = 10 domain = darwin.Domain('unicycle') experiment = universe.new_experiment(domain, population) # basic evolution cycle experiment.initialize_population() for generation in range(5): summary = experiment.evaluate_population() experiment.create_next_generation() # evolution trace trace = experiment.trace self.assertEqual(trace.size, 5) self.assertEqual(trace.size, len(trace)) self.assertEqual(trace[4].champion.fitness, summary.champion.fitness) self.assertEqual(trace[4].champion.fitness, trace[-1].champion.fitness) self.assertEqual(trace[0].champion.fitness, trace[-5].champion.fitness) with self.assertRaises(IndexError): tmp = trace[5] with self.assertRaises(IndexError): tmp = trace[-6] universe.close()
def test_evaluate_population(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') universe = darwin.create_universe(path) population = darwin.Population('neat') domain = darwin.Domain('tic_tac_toe') population.size = 10 experiment = universe.new_experiment(domain, population) experiment.initialize_population() summary = experiment.evaluate_population() self.assertEqual(population.size, 10) self.assertEqual(population.size, len(population)) # generation summary self.assertEqual(summary.generation, 0) self.assertEqual(summary.best_fitness, summary.champion.fitness) # population fitness values self.assertGreaterEqual(population[0].fitness, population[-1].fitness) self.assertEqual(population[0].fitness, summary.champion.fitness) prev_fitness = summary.champion.fitness for genotype in population: self.assertLessEqual(genotype.fitness, prev_fitness) prev_fitness = genotype.fitness universe.close()
def test_indexing(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') universe = darwin.create_universe(path) population = darwin.Population('cne.feedforward') domain = darwin.Domain('tic_tac_toe') population.size = 10 experiment = universe.new_experiment(domain, population) # can't index into an uninitialized population with self.assertRaises(RuntimeError): genotype = population[0] experiment.initialize_population() # correct indexing genotype = population[0] genotype = population[9] genotype = population[-1] genotype = population[-10] # out of bounds with self.assertRaises(IndexError): genotype = population[10] with self.assertRaises(IndexError): genotype = population[-11]
def test_reuse_checks(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') universe = darwin.create_universe(path) population = darwin.Population('neat') domain = darwin.Domain('unicycle') experiment_a = universe.new_experiment(domain, population, name='A') # currently, once a population or a domain _instance_ is used by an experiment, # it cannot be reused in other experiments new_population = darwin.Population('neat') with self.assertRaises(RuntimeError): experiment_b = universe.new_experiment(domain, new_population, name='B') new_domain = darwin.Domain('unicycle') with self.assertRaises(RuntimeError): experiment_c = universe.new_experiment(new_domain, population, name='C') # after the experiment is disposed, we can reuse the population and domain experiment_a = None experiment_d = universe.new_experiment(domain, population, name='D')
def test_create(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') universe = darwin.create_universe(path) self.assertFalse(universe.closed) self.assertEqual(universe.path, path) universe.close() self.assertTrue(universe.closed)
def test_new_experiment(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') with darwin.create_universe(path) as universe: p = darwin.Population('neat') d = darwin.Domain('unicycle') exp = universe.new_experiment(population=p, domain=d) self.assertRegex(repr(exp), p.name) self.assertRegex(repr(exp), d.name) self.assertIs(exp.population, p) self.assertIs(exp.domain, d) self.assertIs(exp.universe, universe)
def test_sealed_state(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') universe = darwin.create_universe(path) population = darwin.Population('neat') domain = darwin.Domain('unicycle') experiment = universe.new_experiment(domain, population) # changes are ok population.size = 10 population.config.normalize_input = False domain.config.gravity = 10.5 experiment.config.save_genealogy = True experiment.core_config.mutation_std_dev = 0.5 d_config = domain.config d_config.max_torque = 100 # initializing the population will seal all configuration values experiment.initialize_population() # shouldn't be able to change sealed state with self.assertRaises(RuntimeError): population.size = 10 with self.assertRaises(RuntimeError): population.config.normalize_input = True with self.assertRaises(RuntimeError): domain.config.gravity = 0 with self.assertRaises(RuntimeError): experiment.config.save_genealogy = False with self.assertRaises(RuntimeError): experiment.core_config.mutation_std_dev = 0 with self.assertRaises(RuntimeError): d_config.max_torque = 0 # make sure the values were not changed self.assertEqual(population.size, 10) self.assertEqual(population.config.normalize_input.auto, False) self.assertEqual(domain.config.gravity.auto, 10.5) self.assertEqual(experiment.config.save_genealogy.auto, True) self.assertEqual(experiment.core_config.mutation_std_dev.auto, 0.5) self.assertEqual(d_config.max_torque.auto, 100) # resetting the experiment allows configuration changes again experiment.reset() population.size = 1 population.config.normalize_input = 'true' domain.config.gravity = 0.1 experiment.config.save_genealogy = False experiment.core_config.mutation_std_dev = '0.1' d_config.max_torque = 1.5 universe.close()
def test_context_manager(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') # create the universe with darwin.create_universe(path): # nothing to do, we just created a new universe pass # open the universe, using the context manager interface with darwin.open_universe(path) as universe: self.assertFalse(universe.closed) self.assertEqual(universe.path, path) self.assertTrue(str(universe).startswith('<darwin.Universe path=')) self.assertTrue(universe.closed)
def test_experiment_reset(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') universe = darwin.create_universe(path) population = darwin.Population('neat') domain = darwin.Domain('unicycle') population.size = 5 experiment_a = universe.new_experiment(domain, population) for i in range(3): experiment_a.name = f'A{i}' # name must be unique experiment_a.initialize_population() experiment_a.evaluate_population() experiment_a.create_next_generation() experiment_a.reset()
def test_experiment_name(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') universe = darwin.create_universe(path) population = darwin.Population('neat') domain = darwin.Domain('unicycle') experiment = universe.new_experiment(domain, population, name='foo') self.assertEqual(experiment.name, 'foo') self.assertRegex(repr(experiment), "'foo'") experiment.name = ' a new name with lots of spaces! ' self.assertRegex(repr(experiment), "' a new name with lots of spaces! '") experiment.name = None self.assertRegex(repr(experiment), 'Unnamed') # invalid name (empty) with self.assertRaises(RuntimeError): experiment.name = '' experiment.name = 'final' experiment.initialize_population() # can't set the name after the experiment is initialized with self.assertRaises(RuntimeError): experiment.name = 'baz' second_population = darwin.Population('cne.lstm') second_domain = darwin.Domain('tic_tac_toe') # duplicate name with self.assertRaises(RuntimeError): second_experiment = universe.new_experiment( domain=second_domain, population=second_population, name='final') second_experiment = universe.new_experiment( domain=second_domain, population=second_population, name='baz') # ok... second_experiment.name = 'new name' # duplicate name with self.assertRaises(RuntimeError): second_experiment.name = 'final'
def test_reinitialize_population(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') universe = darwin.create_universe(path) population = darwin.Population('neat') population.size = 10 domain = darwin.Domain('unicycle') experiment = universe.new_experiment(domain, population) # multiple runs of the same experiment variation for evolution_run in range(3): # reinitialize the population (which would result in a new evolution trace) experiment.initialize_population() for generation in range(2): experiment.evaluate_population() experiment.create_next_generation() universe.close()
def test_genotype_and_brain(self): path = darwin_test_utils.reserve_universe('python_bindings.darwin') universe = darwin.create_universe(path) population = darwin.Population('cne.feedforward') population.size = 10 domain = darwin.Domain('tic_tac_toe') domain.config.ann_type = 'value' experiment = universe.new_experiment(domain, population) experiment.initialize_population() genotype = population[0].clone() self.assertEqual(genotype.to_json(), population[0].to_json()) brain = genotype.grow() for index in range(9): brain.set_input(index, 0) brain.think() board_value = brain.output(index=0)