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_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_available_populations(self): populations = darwin.available_populations() self.assertTrue(populations) for name in populations: population = darwin.Population(name) self.assertEqual(name, population.name) self.assertIsNotNone(population.config)
def test_set_attributes(self): p = darwin.Population('cne.lstm') p.config.activation_function = 'relu' p.config.hidden_layers = '{ 10, 20, 5, 1, 100 }'; self.assertEqual(repr(p.config.activation_function), 'relu') self.assertEqual(repr(p.config.hidden_layers), '{ 10, 20, 5, 1, 100 }') # we support simple conversions p.config.mutation_chance = 0.15 self.assertEqual(float(p.config.mutation_chance), 0.15) # trying to set an nonexistent property with self.assertRaises(RuntimeError): p.config.mutation_chance_foo = '0.1' # invalid value syntax with self.assertRaises(RuntimeError): p.config.mutation_chance = '#0.15' # setting to a unkown enum value with self.assertRaises(RuntimeError): p.config.activation_function = 'relu_blah' # we have a check to prevent accidental conversions with self.assertRaises(RuntimeError): p.config.hidden_layers = { 10, 20, 5, 1, 100 };
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_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_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_size(self): p = darwin.Population('neat') self.assertGreater(p.size, 0) p.size = 1 # smallest valid value # invalid size value with self.assertRaises(RuntimeError): p.size = 0
def test_get_attributes(self): p = darwin.Population('cne.lstm') self.assertEqual(repr(p.config.activation_function), 'tanh') self.assertEqual(repr(p.config.normalize_input), 'false') # trying to get an nonexistent property with self.assertRaises(RuntimeError): value = p.config.nonexistent_property
def test_config_assignment(self): p1 = darwin.Population('cne.lstm') p2 = darwin.Population('neat') # this is ok, we can bind to config instances c = p1.config c = p2.config # ... but we can't set the config with self.assertRaises(AttributeError): p1.config = p2.config # ... even self assignments with self.assertRaises(AttributeError): p1.config = p1.config # ... or setting to None with self.assertRaises(AttributeError): p1.config = None
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_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_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)
def test_property_assignment(self): p = darwin.Population('cne.lstm') value = p.config.hidden_layers p.config.hidden_layers = value
def test_dir(self): p = darwin.Population('cne.lstm') attr_list = dir(p.config) self.assertTrue(attr_list) self.assertIn('activation_function', attr_list) self.assertIn('normalize_input', attr_list)
def test_bool_attributes(self): p = darwin.Population('neat') p.config.normalize_input = True self.assertEqual(repr(p.config.normalize_input), 'true') p.config.normalize_input = False self.assertEqual(repr(p.config.normalize_input), 'false')
def test_config_lifetime(self): p = darwin.Population('neat') config = p.config p = None self.assertTrue(repr(config))