def test_multi_objective_pareto_fitness(self): """ Test if the Fitness dataset is correctly defined for the multi objective "pareto" criteria. """ def process(x, y): return {'out1': x*y, 'out2': x-y} blueprint_dict = { 'x': { 'type': 'integer', 'specs': { 'domain': [10, 60]}}, 'y': { 'type': 'integer', 'specs': { 'domain': [1, 20]}}, } blueprint = Blueprint(blueprint_dict) pop = blueprint.populate.deterministic(n=3) opt = Optimizer(pop, process) opt.run() opt.apply_fitness.multi_criteria_pareto(['out1', 'out2'], ['max', 'min']) results_data = { 'out1': [10, 100, 200, 35, 350, 700, 60, 600, 1200], 'out2': [9, 0, -10, 34, 25, 15, 59, 50, 40] } fronts_data = [3, 2, 1, 3, 2, 1, 3, 2, 1] crowds_data = [np.inf, np.inf, np.inf, 100., 550., 1050., np.inf, np.inf, np.inf] index = opt.datasets.population.index results = pd.DataFrame(results_data, index=index) fronts = pd.Series(fronts_data, index=index, name='Front') crowds = pd.Series(crowds_data, index=index, name='Crowd') r1 = fronts.rank(method='dense', ascending=True) r2 = crowds.rank(method='dense', ascending=False) order1 = int(np.log10(r2.max())) + 1 factor1 = 10**order1 ranks = (r1 * factor1 + r2).rank(method='min').astype(int).rename('Rank') # Test Results Data expected = results actual = opt.datasets.results assert_frame_equal(expected, actual) # Test Fitness Data expected = pd.concat((fronts, crowds, ranks), axis=1) actual = opt.datasets.fitness assert_frame_equal(expected, actual)
def test_readme_basic_example(self): # Defining the Process def my_process(x, y): val = np.sin(x) * x + np.sin(y) * y return {'val': val} # Building the Blueprint builder = BlueprintBuilder() # Adding gene specs builder.add_float_gene(name='x', domain=(0, 12 * np.pi)) builder.add_float_gene(name='y', domain=(0, 12 * np.pi)) blueprint = builder.get_blueprint() # Building the Population popdet = blueprint.populate.deterministic(n=20) poprnd = blueprint.populate.random(n=600) pop = popdet + poprnd # Setting up the Optimizer opt = Optimizer(pop, my_process) # Simulate (this will return an optimized population) opt.config.multithread = False opt.simulate.single_criteria(output='val', objective='max') # Check the best solution print(opt.datasets.get_best_criature(outputs='val', objectives='max')) # Assertions self.assertIsInstance(opt, Optimizer) self.assertIsInstance(opt.population, Population)
def test_simulation_outputs(self): """ Run the population and check if the output data is sane. """ pop = self.blueprint.populate.deterministic(n=3) opt = Optimizer(population=pop, process=self.process) inputs = { 'min_size': [6] * 5, 'max_size': [8] * 5, 'price': [100.] * 5, 'brand': ['AMTA'] * 5, 'sick_pattern': [('L', 'L', 'L')] * 5, 'groove': [('hh', 'bd', 'sn'), ('hh', 'bd', 'sn'), ('bd', 'hh', 'sn'), ('bd', 'hh', 'sn'), ('sn', 'bd', 'hh')], 'is_loud': [False, True, False, True, False] } expected_data = { 'id': [], 'gear_sickness': [], 'price_unbelievebleness': [], 'grooveness': [], } for i in range(5): params = {} for key, vals in inputs.items(): params.update({key: vals[i]}) encoded_index = str(tuple([v for v in params.values()])).encode() index_str = hashlib.sha256(encoded_index).hexdigest() out_dict = self.process(**params) expected_data['id'].append(index_str) expected_data['gear_sickness'].append(out_dict['gear_sickness']) expected_data['price_unbelievebleness'].append( out_dict['price_unbelievebleness']) expected_data['grooveness'].append(out_dict['grooveness']) out_data = pd.DataFrame(expected_data).set_index('id') expected = out_data.sort_index() opt.run(quiet=True) actual = opt.datasets.results.head().sort_index() assert_frame_equal(expected, actual)
def test_single_objective_fitness(self): """ Test if the Fitness dataset is correctly defined for the single objective criteria. Tests ----- 1. opt.dataset.fitness data 2. opt.dataset.simulation data """ pop = self.blueprint.populate.deterministic(n=3) opt = Optimizer(population=pop, process=self.process) opt.run(quiet=True) opt.apply_fitness.single_criteria(output='gear_sickness', objective='max') # Test 1 rank = opt.datasets.results['gear_sickness']\ .rank(method='min', ascending=False)\ .astype(int)\ .rename('Rank') concat_data = ( opt.datasets.results['gear_sickness'].rename('Criteria'), rank ) expected = pd.concat(concat_data, axis=1) actual = opt.datasets.fitness assert_frame_equal(expected, actual) # Test 2 concat_data = ( opt.datasets.population, opt.datasets.results, opt.datasets.results['gear_sickness'].rename('Criteria'), rank ) expected = pd.concat(concat_data, axis=1) actual = opt.datasets.simulation assert_frame_equal(expected, actual)
def test_readme_salesman_example(self): builder = BlueprintBuilder() # Defining the Process # In order to persist the TravelSalesman object for the Process, we need to # wrap it in a function def process_deco(travel_salesman): def wrapper(route): return {'distance': travel_salesman.get_route_distance(route)} return wrapper # Genome Blueprint # (this will only have one variable that is a "Vector" of the particular order # of cities that the salesman should vist) number_of_cities = 20 cities = tuple(range(number_of_cities)) builder.add_set_gene(name='route', domain=cities, length=number_of_cities) # Creating the Population (5000 randomly generated 'route's) blueprint = builder.get_blueprint() pop = blueprint.populate.random(n=5000) # Setting up the Environment trav_salesman = TravelSalesman(number_of_cities, seed=123) process = process_deco(trav_salesman) # Setting up the Optimizer opt = Optimizer(population=pop, process=process) # Activate MultiThreading (for better performance) opt.config.multithread = True # Simulate (this will return an optimized population) opt.simulate.single_criteria(output='distance', objective='min') # Check the best solution print(opt.datasets.get_best_criature()) # Assertions self.assertIsInstance(opt, Optimizer) self.assertIsInstance(opt.population, Population)
def test_multi_objective_ranked_fitness(self): """ Test if the Fitness dataset is correctly defined for the multi objective "ranked" criteria. Tests ----- 1. opt.dataset.fitness data with 2 objectives 2. opt.dataset.simulation data with 2 objective 3. opt.dataset.fitness data with 3 objectives 4. opt.dataset.simulation data with 3 objective """ popdet = self.blueprint.populate.deterministic(n=3) poprnd = self.blueprint.populate.random(n=1000, seed=42) pop = popdet + poprnd opt = Optimizer(population=pop, process=self.process) ascmap = {'min': True, 'max': False} def multirank(df, priorities, objectives): ranks = [] for priority, objective in zip(priorities, objectives): asc = ascmap[objective] r = df[priority]\ .rank(method='min', ascending=asc) ranks.append(r) rank = ranks[-1] for r in ranks[::-1]: order = int(np.log10(r.max())) + 1 factor = 10**order rscore = r * factor + rank rank = rscore.rank(method='min') return rank.astype(int) opt.run(quiet=True) # Tests 1 & 2 - Setup outputs = ['gear_sickness', 'price_unbelievebleness'] objectives = ['max', 'min'] opt.apply_fitness.multi_criteria_ranked(outputs=outputs, objectives=objectives) rank = multirank(opt.datasets.results, outputs, objectives).rename('Rank') # Test 1 concat_data = ( [opt.datasets.results[col].rename(f'Criteria{i+1}') for i, col in enumerate(outputs)] + [rank] ) expected = pd.concat(concat_data, axis=1) actual = opt.datasets.fitness assert_frame_equal(expected, actual) # Test 2 concat_data = ( [opt.datasets.population, opt.datasets.results] + [opt.datasets.results[col].rename(f'Criteria{i+1}') for i, col in enumerate(outputs)] + [rank] ) expected = pd.concat(concat_data, axis=1) actual = opt.datasets.simulation assert_frame_equal(expected, actual) # Tests 3 & 4 - Setup outputs = ['gear_sickness', 'price_unbelievebleness', 'grooveness'] objectives = ['max', 'min', 'max'] opt.apply_fitness.multi_criteria_ranked(outputs=outputs, objectives=objectives) rank = multirank(opt.datasets.results, outputs, objectives).rename('Rank') # Test 3 concat_data = ( [opt.datasets.results[col].rename(f'Criteria{i+1}') for i, col in enumerate(outputs)] + [rank] ) expected = pd.concat(concat_data, axis=1) actual = opt.datasets.fitness assert_frame_equal(expected, actual) # Test 4 concat_data = ( [opt.datasets.population, opt.datasets.results] + [opt.datasets.results[col].rename(f'Criteria{i+1}') for i, col in enumerate(outputs)] + [rank] ) expected = pd.concat(concat_data, axis=1) actual = opt.datasets.simulation assert_frame_equal(expected, actual)
# Defining the Process def my_process(x, y): val = np.sin(x)*x + np.sin(y)*y return {'val': val} # Building the Blueprint builder = BlueprintBuilder() # (note that 'x' and 'y' are declared, which are the exact same names as the # parameters of the function 'my_process' - *this is required*) builder.add_float_gene(name='x', domain=(0, 12*np.pi)) builder.add_float_gene(name='y', domain=(0, 12*np.pi)) blueprint = builder.get_blueprint() # Building the Population popdet = blueprint.populate.deterministic(n=20) poprnd = blueprint.populate.random(n=600) pop = popdet + poprnd # Setting up the Optimizer opt = Optimizer(pop, my_process) # Simulate (this will return an optimized population) opt.simulate.single_criteria(output='val', objective='max') # Check the best solution print(opt.datasets.get_best_criature())
# (this will only have one variable that is a "Vector" of the particular order # of cities that the salesman should vist) number_of_cities = 20 cities = tuple(range(number_of_cities)) builder.add_set_gene(name='route', domain=cities, length=number_of_cities) # Creating the Population (5000 randomly generated 'route's) blueprint = builder.get_blueprint() pop = blueprint.populate.random(n=5000) # Setting up the Environment trav_salesman = TravelSalesman(number_of_cities, seed=123) trav_salesman.create.random() process = process_deco(trav_salesman) # Setting up the Optimizer opt = Optimizer(population=pop, process=process) # Activate MultiThreading (for better performance) opt.config.multithread = True # peek best solution during runtime opt.config.peek_champion_variables = ['route', 'distance'] # Simulate (this will return an optimized population) opt.simulate.single_criteria(output='distance', objective='min') # Check the best solution best_creature = opt.datasets.get_best_criature() print([print(f'{k}: {x}') for k, x in best_creature.iteritems()])
def setUp(self): blueprint_dict = { 'min_size': { 'type': 'integer', 'specs': { 'domain': [6, 10] } }, 'max_size': { 'type': 'integer', 'specs': { 'domain': [8, 24] } }, 'price': { 'type': 'float', 'specs': { 'domain': [100, 250] } }, 'brand': { 'type': 'categorical', 'specs': { 'domain': ['AMTA', 'REPAL', 'NOSOR'] } }, 'sick_pattern': { 'type': 'array', 'specs': { 'domain': ['L', 'R'], 'length': 3 } }, 'groove': { 'type': 'set', 'specs': { 'domain': ['hh', 'bd', 'sn'], 'length': 3 } }, 'is_loud': { 'type': 'boolean', 'specs': {} } } def process(min_size, max_size, price, brand, sick_pattern, groove, is_loud): brand_factor = {'AMTA': 3.7, 'REPAL': 3.2, 'NOSOR': 4.6} gear_sickness = (max_size / min_size) * brand_factor[brand] * ( 2 + int(is_loud)) price_unbelievebleness = (price / gear_sickness) * min_size pattern_val = hash(sick_pattern) % 1000 groove_val = hash(groove) % 5000 groovy = pattern_val + groove_val return { 'gear_sickness': gear_sickness, 'price_unbelievebleness': price_unbelievebleness, 'grooveness': groovy } self.blueprint = Blueprint(blueprint_dict) pop = self.blueprint.populate.random(n=10, seed=42) self.populator = Populator(self.blueprint) self.opt = Optimizer(pop, process) self.opt.run_multithread(quiet=True)
class TestReproduction(unittest.TestCase): """ Tests for the multiple reproduciton methods available. Reproduction Methods -------------------- - Sexual - Cross-Over methods - Tournament - Asexual (mutation) """ def setUp(self): blueprint_dict = { 'min_size': { 'type': 'integer', 'specs': { 'domain': [6, 10] } }, 'max_size': { 'type': 'integer', 'specs': { 'domain': [8, 24] } }, 'price': { 'type': 'float', 'specs': { 'domain': [100, 250] } }, 'brand': { 'type': 'categorical', 'specs': { 'domain': ['AMTA', 'REPAL', 'NOSOR'] } }, 'sick_pattern': { 'type': 'array', 'specs': { 'domain': ['L', 'R'], 'length': 3 } }, 'groove': { 'type': 'set', 'specs': { 'domain': ['hh', 'bd', 'sn'], 'length': 3 } }, 'is_loud': { 'type': 'boolean', 'specs': {} } } def process(min_size, max_size, price, brand, sick_pattern, groove, is_loud): brand_factor = {'AMTA': 3.7, 'REPAL': 3.2, 'NOSOR': 4.6} gear_sickness = (max_size / min_size) * brand_factor[brand] * ( 2 + int(is_loud)) price_unbelievebleness = (price / gear_sickness) * min_size pattern_val = hash(sick_pattern) % 1000 groove_val = hash(groove) % 5000 groovy = pattern_val + groove_val return { 'gear_sickness': gear_sickness, 'price_unbelievebleness': price_unbelievebleness, 'grooveness': groovy } self.blueprint = Blueprint(blueprint_dict) pop = self.blueprint.populate.random(n=10, seed=42) self.populator = Populator(self.blueprint) self.opt = Optimizer(pop, process) self.opt.run_multithread(quiet=True) def test_tournament(self): """ Assert that tournament behaviours are sane. Tests ----- 1. Assert number of parents is equal to n_parents 2. Assert it raises exception if total number of parents is lower then the number of solicited parents 3. Assert if elitism lock works (that is if the number of n_parents and n_dispute end up creating a situation where the top n_parents are necessarily selected) """ self.opt.apply_fitness.single_criteria(output='gear_sickness', objective='max') ranked_data = self.opt.datasets.fitness n_selection = int(round(len(ranked_data) * 0.5)) ranked_pop = ranked_data.sort_values('Rank')[0:n_selection] # Test 1 parents = select_parents_by_tournament(ranked_pop, n_dispute=2, n_parents=2, seed=42) expected = 2 actual = len(parents) self.assertEqual(expected, actual) parents = select_parents_by_tournament(ranked_pop, n_dispute=2, n_parents=3, seed=42) expected = 3 actual = len(parents) self.assertEqual(expected, actual) parents = select_parents_by_tournament(ranked_pop, n_dispute=3, n_parents=3, seed=42) expected = 3 actual = len(parents) self.assertEqual(expected, actual) # Test 2 with self.assertRaises(ParentOverloadException): select_parents_by_tournament(ranked_pop, n_dispute=4, n_parents=3, seed=42) with self.assertRaises(ParentOverloadException): select_parents_by_tournament(ranked_pop, n_dispute=3, n_parents=4, seed=42) # Test 3 sortcols = ['Rank', 'id'] expected = ranked_pop.reset_index().sort_values( by=sortcols)[0:3].reset_index(drop=True) actual = select_parents_by_tournament(ranked_pop, n_dispute=3, n_parents=3)\ .reset_index()\ .sort_values(by=sortcols)\ .reset_index(drop=True) assert_frame_equal(expected, actual) def test_sexual_offspring_generation(self): """ Assert that the sexual reproduction method is generating the offspring population correctly. Tests ----- 0. Validate schema 0.1. Making 1 children 0.2. Making 10 children 1. Assert that the number of generated offspring correspond to the :n_offspring: param. 1.1. 4 children (children_per_relation=2) - must result 4 children 1.2. 5 children (children_per_relation=2) - must result 6 children 1.3. 4 children (children_per_relation=3) - must result 6 children 1.4. 5 children (children_per_relation=1) - must result 5 children 1.5. 1 children (children_per_relation=3) - must result 3 children 1.6. 1 children (children_per_relation=1) - must result 1 child 2. Distinct children is equal or greater than the number of children_per_relation 2.1. n_parents=2, children_per_relation=2 2.2. n_parents=2, children_per_relation=3 2.3. n_parents=3, children_per_relation=3 2.4. n_parents=3, children_per_relation=4 """ self.opt.apply_fitness.single_criteria(output='gear_sickness', objective='max') ranked_data = self.opt.datasets.simulation n_selection = int(round(len(ranked_data) * 0.5)) ranked_pop_data = ranked_data.sort_values('Rank')[0:n_selection] # Test 0 expected_data = { 'min_size': np.dtype(int), 'max_size': np.dtype(int), 'price': np.dtype(float), 'brand': np.dtype(object), 'sick_pattern': np.dtype(object), 'groove': np.dtype(object), 'is_loud': np.dtype(bool), } expected = pd.Series(expected_data) # Test 0.1 offspring = self.populator.sexual(ranked_pop_data=ranked_pop_data, n_offspring=1, n_dispute=2, n_parents=2, children_per_relation=1, rank_column='Rank', seed=42) actual = offspring.data.dtypes assert_series_equal(expected, actual) # Test 0.2 offspring = self.populator.sexual(ranked_pop_data=ranked_pop_data, n_offspring=10, n_dispute=2, n_parents=2, children_per_relation=2, rank_column='Rank', seed=42) actual = offspring.data.dtypes assert_series_equal(expected, actual) n_trials = 500 for _ in range(n_trials): # Test 1 # Test 1.1 offspring = self.populator.sexual(ranked_pop_data=ranked_pop_data, n_offspring=4, n_dispute=2, n_parents=2, children_per_relation=2, rank_column='Rank', seed=42) expected = 4 actual = offspring.size self.assertEqual(expected, actual) # Test 1.2 offspring = self.populator.sexual(ranked_pop_data=ranked_pop_data, n_offspring=5, n_dispute=2, n_parents=2, children_per_relation=2, rank_column='Rank', seed=42) expected = 6 actual = offspring.size self.assertEqual(expected, actual) # Test 1.3 offspring = self.populator.sexual(ranked_pop_data=ranked_pop_data, n_offspring=4, n_dispute=2, n_parents=2, children_per_relation=3, rank_column='Rank', seed=42) expected = 6 actual = offspring.size self.assertEqual(expected, actual) # Test 1.4 offspring = self.populator.sexual(ranked_pop_data=ranked_pop_data, n_offspring=5, n_dispute=2, n_parents=2, children_per_relation=1, rank_column='Rank', seed=42) expected = 5 actual = offspring.size self.assertEqual(expected, actual) # Test 1.5 offspring = self.populator.sexual(ranked_pop_data=ranked_pop_data, n_offspring=1, n_dispute=2, n_parents=2, children_per_relation=3, rank_column='Rank', seed=42) expected = 3 actual = offspring.size self.assertEqual(expected, actual) # Test 1.6 offspring = self.populator.sexual(ranked_pop_data=ranked_pop_data, n_offspring=1, n_dispute=2, n_parents=2, children_per_relation=1, rank_column='Rank', seed=42) expected = 1 actual = offspring.size self.assertEqual(expected, actual) # Test 2 # Test 2.1 offspring = self.populator.sexual(ranked_pop_data=ranked_pop_data, n_offspring=4, n_dispute=2, n_parents=2, children_per_relation=2, rank_column='Rank', seed=42) expected = 2 actual = offspring.unique().size self.assertGreaterEqual(actual, expected) # Test 2.2 offspring = self.populator.sexual(ranked_pop_data=ranked_pop_data, n_offspring=4, n_dispute=2, n_parents=2, children_per_relation=3, rank_column='Rank', seed=42) expected = 3 actual = offspring.unique().size self.assertGreaterEqual(actual, expected) # Test 2.3 offspring = self.populator.sexual(ranked_pop_data=ranked_pop_data, n_offspring=4, n_dispute=2, n_parents=3, children_per_relation=3, rank_column='Rank', seed=42) expected = 3 actual = offspring.unique().size self.assertGreaterEqual(actual, expected) # Test 2.4 offspring = self.populator.sexual(ranked_pop_data=ranked_pop_data, n_offspring=4, n_dispute=2, n_parents=3, children_per_relation=4, rank_column='Rank', seed=42) expected = 4 actual = offspring.unique().size self.assertGreaterEqual(actual, expected) def test_asexual_offspring_generation(self): """ Assert that the sexual reproduction method is generating the offspring population correctly. Tests ----- 0. Validate schema 0.1. Making 1 children 0.2. Making 10 children 1. Assert that the number of generated offspring correspond to the :n_offspring: param. 1.1. 1 child 1.2. 5 children 1.3. 10 children 1.4. 3 children """ self.opt.apply_fitness.single_criteria(output='gear_sickness', objective='max') ranked_data = self.opt.datasets.simulation n_selection = int(round(len(ranked_data) * 0.5)) ranked_pop_data = ranked_data.sort_values('Rank')[0:n_selection] # Test 0 expected_data = { 'min_size': np.dtype(int), 'max_size': np.dtype(int), 'price': np.dtype(float), 'brand': np.dtype(object), 'sick_pattern': np.dtype(object), 'groove': np.dtype(object), 'is_loud': np.dtype(bool), } expected = pd.Series(expected_data) # Test 0.1 offspring = self.populator.asexual(ranked_pop_data=ranked_pop_data, n_offspring=1, n_mutated_genes=1, children_per_creature=1, rank_column='Rank', seed=42) actual = offspring.data.dtypes assert_series_equal(expected, actual) # Test 0.2 offspring = self.populator.asexual(ranked_pop_data=ranked_pop_data, n_offspring=10, n_mutated_genes=1, children_per_creature=1, rank_column='Rank', seed=42) actual = offspring.data.dtypes assert_series_equal(expected, actual) # Test 1.1 offspring = self.populator.asexual(ranked_pop_data=ranked_pop_data, n_offspring=1, n_mutated_genes=1, rank_column='Rank', seed=42) expected = 1 actual = offspring.size self.assertEqual(expected, actual) # Test 1.2 offspring = self.populator.asexual(ranked_pop_data=ranked_pop_data, n_offspring=5, n_mutated_genes=1, children_per_creature=1, rank_column='Rank', seed=42) expected = 5 actual = offspring.size self.assertEqual(expected, actual) # Test 1.3 offspring = self.populator.asexual(ranked_pop_data=ranked_pop_data, n_offspring=10, n_mutated_genes=1, children_per_creature=1, rank_column='Rank', seed=42) expected = 10 actual = offspring.size self.assertEqual(expected, actual) # Test 1.4 offspring = self.populator.asexual(ranked_pop_data=ranked_pop_data, n_offspring=1, n_mutated_genes=1, children_per_creature=3, rank_column='Rank', seed=42) expected = 3 actual = offspring.size self.assertEqual(expected, actual)
def test_datasets_construction(self): """ Test if the initial datasets are adequatetly set with the hashed id's as the index and the empty result columns in the :results:, :fitness: and :history: datasets. Also tests if the data concatenation that constitutes the :simulation: dataset is working es espected. """ pop = self.blueprint.populate.deterministic(n=2) opt = Optimizer(population=pop, process=self.process) # population pop_data = { 'min_size': [6] * 5, 'max_size': [8] * 5, 'price': [100.] * 5, 'brand': ['AMTA'] * 5, 'sick_pattern': [('L', 'L', 'L')] * 4 + [('R', 'R', 'R')], 'groove': [('hh', 'bd', 'sn'), ('hh', 'bd', 'sn'), ('sn', 'bd', 'hh'), ('sn', 'bd', 'hh'), ('hh', 'bd', 'sn')], 'is_loud': [False, True, False, True, False] } expected_index_encoded_strings = [ str(tuple(arr[i] for arr in pop_data.values())).encode() for i in range(5) ] expected_index_strings = [ hashlib.sha256(encoded).hexdigest() for encoded in expected_index_encoded_strings ] expected_index = pd.Series(expected_index_strings) expected_index.name = 'id' expected = pd.DataFrame(pop_data, index=expected_index) actual = opt.datasets.population.head() assert_frame_equal(expected, actual) # results results_cols = ('gear_sickness', 'price_unbelievebleness', 'grooveness') expected = pd.DataFrame(columns=results_cols, index=expected_index) actual = opt.datasets.results.head() assert_frame_equal(expected, actual) # fitness expected = pd.DataFrame(index=expected_index) actual = opt.datasets.fitness.head() assert_frame_equal(expected, actual) # history expected = pd.DataFrame(columns=['generation'], dtype=int) actual = opt.datasets.history assert_frame_equal(expected, actual) # simulation datasets = (pd.DataFrame(pop_data, index=expected_index), pd.DataFrame(columns=results_cols, index=expected_index), pd.DataFrame(index=expected_index)) expected = pd.concat(datasets, axis=1) actual = opt.datasets.simulation.head() assert_frame_equal(expected, actual)