def test_propensity_carnivore(): """ Tests that the propensity function for carnivores works. """ herbs = [{ "species": "Herbivore", "age": 5, "weight": 50 } for _ in range(4)] jungle = bl.Jungle() jungle.cell_population(herbs) assert jungle.propensity()[1] == pytest.approx(np.exp(4)) savannah = bl.Savannah() savannah.cell_population(herbs) savannah.animal_population[0].append(ba.Herbivore(weight=25)) assert savannah.propensity()[1] == pytest.approx(np.exp(4.5), rel=1e-1) desert = bl.Desert() desert.cell_population(herbs) desert.animal_population[0].append(ba.Herbivore(weight=68)) assert desert.propensity()[1] == pytest.approx(np.exp(5.36), rel=1e-1) mountain = bl.Mountain() ocean = bl.Ocean() uninhabitable_landscapes = [mountain, ocean] for landscape in uninhabitable_landscapes: landscape.cell_population(herbs) assert landscape.propensity()[0] == 0
def test_carnivore_eating_probability(mocker): """ Tests that the carnivore eating probability is 0 if the carnivore's fitness is less than the herbivore's fitness, and that it will eat corresponding to the given formula if its fitness is higher than the herbivore that it is trying to eat. Use mocking to set the value of the property fitness. """ herb = ba.Herbivore() mocker.patch("biosim.animals.Herbivore.fitness", new_callable=mocker.PropertyMock, return_value=0.7) carn = ba.Carnivore() mocker.patch("biosim.animals.Carnivore.fitness", new_callable=mocker.PropertyMock, return_value=0.3) assert not carn.eating_probability(herb) mocker.patch("biosim.animals.Herbivore.fitness", new_callable=mocker.PropertyMock, return_value=0.2) mocker.patch("biosim.animals.Carnivore.fitness", new_callable=mocker.PropertyMock, return_value=0.7) assert carn.eating_probability(herb) == pytest.approx( 0.05 ) carn.set_animal_parameters({"DeltaPhiMax": 0.000001}) assert carn.eating_probability(herb) == 1
def test_update_cell_population(mocker): """ Tests whether the cells animal population is updated after a migration cycle. """ current_cell = bl.Desert() current_cell.animal_population[0].append(ba.Herbivore()) desert = bl.Desert() jungle = bl.Jungle() savannah = bl.Savannah() neighbour_cells = [desert, bl.Mountain(), jungle, savannah] probability_list = [0.25, 0.0, 0.5, 0.25] mocker.patch("random.random", return_value=0.7) current_cell_old_population = current_cell.animal_population jungle_cell_old_population = jungle.animal_population current_cell.choose_migration_cell(current_cell.animal_population[0][0], neighbour_cells, probability_list) neighbour_cells.append(current_cell) for cell in neighbour_cells: cell.update_cell_population() current_cell_new_population = current_cell.animal_population jungle_cell_new_population = jungle.animal_population assert current_cell_new_population != current_cell_old_population assert jungle_cell_new_population != jungle_cell_old_population
def test_number_of_herbivores(): """ Test that the method counts the number of herbivores in the specific cell. """ land = bl.Landscape() land.animal_population[0].append(ba.Herbivore()) assert land.number_of_herbivores == 1
def test_set_animal_parameters(): """ Test that manual setting of animal parameters follows the given restrictions. """ herb = ba.Herbivore() new_parameters = {"w_birth": 10, "sigma_birth": 1.5, "beta": 0.78, "eta": 0.14, "a_half": 65.0, "phi_age": 0.5, "w_half": 4.5, "phi_weight": 0.3, "mu": 0.5, "lambda": 1.0, "gamma": 0.7, "zeta": 3.5, "xi": 1.1, "omega": 0.9, "F": 30.0} herb.set_animal_parameters(new_parameters=new_parameters) assert new_parameters["eta"] <= 1 for key in new_parameters.keys(): assert new_parameters[key] >= 0 carn = ba.Carnivore() new_parameters = {"w_birth": 10, "sigma_birth": 1.5, "beta": 0.78, "eta": 0.14, "a_half": 65.0, "phi_age": 0.5, "w_half": 4.5, "phi_weight": 0.3, "mu": 0.5, "lambda": 1.0, "gamma": 0.7, "zeta": 3.5, "xi": 1.1, "omega": 0.9, "F": 30.0, "DeltaPhiMax": 10.0} carn.set_animal_parameters(new_parameters=new_parameters) assert new_parameters["DeltaPhiMax"] > 0 assert new_parameters["eta"] <= 1 for key in new_parameters.keys(): if key is not "DeltaPhiMax": assert new_parameters[key] >= 0
def test_directional_probability(): """ Tests that the probabilities of moving to the adjacent cells are computed correctly. """ current_cell_pop = [{ "species": "Herbivore", "age": 10, "weight": 15 }, { "species": "Carnivore", "age": 5, "weight": 40 }, { "species": "Carnivore", "age": 15, "weight": 25 }] current_cell = bl.Jungle() current_cell.cell_population(current_cell_pop) jungle_right = bl.Jungle() jungle_left = bl.Jungle() desert = bl.Desert() jungle_right.animal_population[0].append(ba.Herbivore(weight=15)) jungle_pop = [{ "species": "Herbivore", "age": 10, "weight": 15 }, { "species": "Herbivore", "age": 5, "weight": 15 }] jungle_left.cell_population(jungle_pop) desert_pop = [{ "species": "Herbivore", "age": 10, "weight": 20 }, { "species": "Herbivore", "age": 5, "weight": 15 }, { "species": "Herbivore", "age": 10, "weight": 35 }] desert.cell_population(desert_pop) neighbour_cells = [desert, bl.Mountain(), jungle_right, jungle_left] herbivore_probabilities = current_cell.directional_probability( current_cell.animal_population[0][0], neighbour_cells) carnivore_probabilities = current_cell.directional_probability( current_cell.animal_population[1][0], neighbour_cells) assert herbivore_probabilities != carnivore_probabilities # The numbers below are calculated manually. assert carnivore_probabilities == pytest.approx([0.56, 0.0, 0.18, 0.25], rel=1e-1)
def test_animals_reproduction_probability(): """ Tests that the Herbivore reproduce after given specifications. """ herb = ba.Herbivore(weight=30) assert not herb.reproduction_probability(n_animals=1) herb2 = ba.Herbivore(weight=50) assert not herb2.reproduction_probability(n_animals=1) assert herb2.reproduction_probability(n_animals=1000) herb3 = ba.Herbivore(weight=2) assert not herb3.reproduction_probability(n_animals=1000) carn = ba.Carnivore(weight=30) assert not carn.reproduction_probability(n_animals=1) carn2 = ba.Carnivore(weight=50) assert not carn2.reproduction_probability(n_animals=1) assert carn2.reproduction_probability(n_animals=1000) carn3 = ba.Carnivore(weight=2) assert not carn3.reproduction_probability(n_animals=1000)
def test_migration_probability(mocker): """ Tests that the migration probability formula works in the corresponding method in the Animal class. """ ba.Herbivore.set_animal_parameters({"mu": 1}) herb = ba.Herbivore() mocker.patch("biosim.animals.Herbivore.fitness", new_callable=mocker.PropertyMock, return_value=1) assert herb.migration_probability()
def test_herbivore_eating(): """ Tests that the herbivore weight is increased corresponding to the given formula. """ herb = ba.Herbivore() initial_weight = herb.weight herb.eating(fodder=10) new_weight = herb.weight assert new_weight > initial_weight
def test_non_negative_animal_weight(): """ Tests that animals have a non-negative weight. """ herb = ba.Herbivore() carn = ba.Carnivore() assert isinstance(herb, ba.Herbivore) assert herb.weight >= 0 assert isinstance(carn, ba.Carnivore) assert carn.weight >= 0
def test_herbivore_parameters(): """ Tests that the given parameters for the herbivore class are in the list of valid parameters. """ keys_list = ["w_birth", "sigma_birth", "beta","eta", "a_half", "phi_age", "w_half", "phi_weight", "mu", "lambda", "gamma", "zeta", "xi", "omega", "F"] herb = ba.Herbivore() for key in keys_list: assert key in herb.default_parameters.keys()
def cell_population(self, population=None): """ Puts the animal population in the specific cell. :param population: list. """ for animal in population: if animal["species"] == "Herbivore": self.animal_population[0].append( ba.Herbivore(age=animal["age"], weight=animal["weight"])) else: self.animal_population[1].append( ba.Carnivore(age=animal["age"], weight=animal["weight"]))
def test_update_fitness(): """ Tests if the fitness of animals is updated as expected after weight change. """ land = bl.Landscape() land.animal_population[0].append(ba.Herbivore()) land.animal_population[1].append(ba.Carnivore()) fit0_herb = land.animal_population[0][0].fitness fit0_carn = land.animal_population[1][0].fitness land.weight_loss() fit1_herb = land.animal_population[0][0].fitness fit1_carn = land.animal_population[1][0].fitness assert fit0_herb > fit1_herb assert fit0_carn > fit1_carn
def test_carnivore_eating(): """ Tests that carnivore weight increases as expected corresponding to the given formula after eating a herbivore, and that the herbivore is removed from the herbivore population. """ herbivores = [ba.Herbivore(weight=15, age=5) for _ in range(6)] ba.Carnivore.set_animal_parameters({"DeltaPhiMax": 0.000001}) carn = ba.Carnivore(weight=500, age=5) start_weight = carn.weight surviving_herbivores = carn.eating(herbivores) new_weight = carn.weight assert len(herbivores) > len(surviving_herbivores) assert new_weight > start_weight assert carn.weight == 537.5
def reproduction(self): """ Finds out which animals for each species that reproduce, based on reproduction probability, and adds a newborn of that species to the cell. """ for species in self.animal_population: newborn_animals = [] for animal in species: if animal.reproduction_probability(len(species)): if isinstance(animal, ba.Herbivore): newborn_animals.append(ba.Herbivore()) elif isinstance(animal, ba.Carnivore): newborn_animals.append(ba.Carnivore()) animal.update_weight_after_birth() species.extend(newborn_animals)
def test_animals_lifecycle(): """ Test the lifecycle of a herbivore; they start with age 0, which is incremented by one for every year passed. They eat and gain weight, and loose weight for every year. """ herb = ba.Herbivore() assert herb.age == 0 herb.aging() start_weight = herb.weight herb.eating(100) assert herb.weight > start_weight assert herb.age == 1 new_weight = herb.weight herb.animal_weight_loss() assert herb.weight < new_weight
def test_choose_migration_cell(mocker): """ Tests whether animals are migrating to the correct cell, given the animals probability to move to a specific cell. """ current_cell = bl.Desert() current_cell.animal_population[0].append(ba.Herbivore()) desert = bl.Desert() jungle = bl.Jungle() savannah = bl.Savannah() neighbour_cells = [desert, bl.Mountain(), jungle, savannah] probability_list = [0.25, 0.0, 0.5, 0.25] mocker.patch("random.random", return_value=0.7) current_cell.choose_migration_cell(current_cell.animal_population[0][0], neighbour_cells, probability_list) assert len(current_cell.new_population[0]) == 0 assert len(jungle.new_population[0]) == 1
def test_animal_update_weight_after_birth(): """ Tests that a herbivore weight is reduced following birth. """ newborn_weight = 8 initial_weight = 50 herb = ba.Herbivore(weight=initial_weight) herb.newborn_weight = 8 herb.update_weight_after_birth() assert herb.weight < initial_weight assert herb.weight == pytest.approx(initial_weight - ( herb.default_parameters["xi"] * newborn_weight ), rel=1e-1) newborn_weight = 8 initial_weight = 50 carn = ba.Carnivore(weight=initial_weight) carn.newborn_weight = 8 carn.update_weight_after_birth() assert carn.weight < initial_weight assert carn.weight == pytest.approx(initial_weight - ( carn.default_parameters["xi"] * newborn_weight ), rel=1e-1)
def test_animal_death(mocker): """ Tests that animals die with certainty 1 if its fitness is 0 and dies with certainty 0 if its fitness is 1, according to the given formula for the probability of animal death. """ herb = ba.Herbivore() herb.default_parameters["omega"] = 1 mocker.patch("biosim.animals.Animal.fitness", new_callable=mocker.PropertyMock, return_value=0) assert herb.death() mocker.patch("biosim.animals.Animal.fitness", new_callable=mocker.PropertyMock, return_value=1) assert not herb.death() carn = ba.Carnivore() carn.default_parameters["omega"] = 1 mocker.patch("biosim.animals.Animal.fitness", new_callable=mocker.PropertyMock, return_value=0) assert carn.death() mocker.patch("biosim.animals.Animal.fitness", new_callable=mocker.PropertyMock, return_value=1) assert not carn.death()
def test_animals_fitness(): """ Tests that the fitness of a herbivore and carnivore is between 0 and 1, and decreases with age and weight-loss. """ herb = ba.Herbivore() value1 = herb.fitness assert 0 <= value1 <= 1 herb.aging() value2 = herb.fitness assert value2 < value1 herb.animal_weight_loss() value3 = herb.fitness assert value3 < value2 carn = ba.Carnivore() value1 = carn.fitness assert 0 <= value1 <= 1 carn.aging() value2 = carn.fitness assert value2 < value1 carn.animal_weight_loss() value3 = carn.fitness assert value3 < value2
def test_migrate(): """ Tests that migration of animals work as expected. """ current_cell_pop = [{ "species": "Herbivore", "age": 10, "weight": 15 }, { "species": "Herbivore", "age": 20, "weight": 35 }, { "species": "Carnivore", "age": 5, "weight": 40 }, { "species": "Carnivore", "age": 15, "weight": 25 }] current_cell = bl.Savannah() current_cell.cell_population(current_cell_pop) jungle_right = bl.Jungle() jungle_left = bl.Jungle() desert = bl.Desert() jungle_right.animal_population[0].append(ba.Herbivore(weight=15)) jungle_pop = [{ "species": "Herbivore", "age": 10, "weight": 15 }, { "species": "Herbivore", "age": 5, "weight": 15 }] jungle_left.cell_population(jungle_pop) desert_pop = [{ "species": "Herbivore", "age": 10, "weight": 20 }, { "species": "Herbivore", "age": 5, "weight": 15 }, { "species": "Herbivore", "age": 10, "weight": 35 }] desert.cell_population(desert_pop) neighbour_cells = [desert, bl.Mountain(), jungle_right, jungle_left] random.seed(124) current_cell.migrate(neighbour_cells) neighbour_cells.append(current_cell) for cell in neighbour_cells: if not isinstance(cell, bl.Mountain): assert cell.new_population != cell.animal_population