def test_deme_number_of_leaders_is_number_of_individuals_with_that_role(
            self, pseudorandom, getFitnessParameters):
        pseudorandom(0)
        self.pop = Pop(fit_fun='socialclass', inst='test/test')
        self.pop.fitnessParameters = getFitnessParameters('socialclass')
        self.pop.numberOfDemes = 3
        self.pop.initialDemeSize = 10
        self.pop.initialPhenotypes = [0.1, 0.2, 0.3, 0.6]
        self.pop.migrationRate = 0
        self.pop.mutationRate = 0

        self.pop.createAndPopulateDemes()
        self.pop.clearDemeInfo()
        self.pop.populationMutationMigration()
        self.pop.updateDemeInfoPreProduction()

        leaderCountPerDeme = [0] * self.pop.numberOfDemes
        for ind in self.pop.individuals:
            leaderCountPerDeme[ind.currentDeme] += ind.leader

        for deme in range(self.pop.numberOfDemes):
            nl = self.pop.demes[deme].numberOfLeaders
            assert nl != 10, "all individuals in deme have been elected leaders when proportion should be about: " + self.pop.initialPhenotypes[
                3]
            assert leaderCountPerDeme[
                deme] == nl, "deme counts {0} leaders when there are {1}".format(
                    nl, leaderCountPerDeme[deme])
    def test_demography_file_has_correct_output(self, pseudorandom, runSim,
                                                clearOutputFiles):
        pseudorandom(69)
        self.pop = Pop(inst='test/test')
        self.pop.mutationRate = 0.1
        self.pop.numberOfDemes = 5
        self.pop.initialDemeSize = 8
        self.pop.fitnessParameters.clear()
        self.pop.fitnessParameters.update({
            "fb": 10,
            "b": 0.5,
            "c": 0.05,
            "gamma": 0.01
        })
        self.pop.createAndPopulateDemes()
        expDemog = []
        for gen in range(5):
            self.pop.lifecycle()
            assert self.pop.numberOfDemes == 5
            expDemog.append(self.pop.demography / self.pop.numberOfDemes)

        pseudorandom(69)
        runSim()
        obsDemog = fman.extractColumnFromFile('test/test/out_demography.txt',
                                              0, float)

        assert obsDemog == expDemog, "unexpected value of group size has been printed"

        clearOutputFiles('test/test/')
 def launchSimulation(self, path, mutbound=True):
     folderName = path.split('/')[-1]
     fitfun = folderName.split('_')[0]
     populationInstance = Pop(fit_fun=fitfun,
                              inst=path,
                              mutationBoundaries=mutbound)
     populationInstance.runSimulation()
    def test_consensus_takes_time_to_reach(self):
        self.pop = Pop(inst='test/test')
        self.pop.fit_fun = 'debate'
        self.pop.initialPhenotypes = [0.1, 0.2, 0.3, 0.4]
        self.pop.numberOfDemes = 3
        self.pop.initialDemeSize = 2
        self.pop.mutationRate = 0
        self.pop.migrationRate = 0

        self.pop.createAndPopulateDemes()
        self.pop.clearDemeInfo()
        self.pop.populationMutationMigration()
        self.pop.updateDemeInfoPreProduction()

        for deme in self.pop.demes:
            assert deme.politicsValues[
                "consensusTime"] is not None, "consensus reaching time has not been calculated"
            assert deme.politicsValues[
                "consensusTime"] > 0, "consensus reaching should take a bare minimum of time"
            disagreement = self.pop.fitnessParameters[
                "aconsensus"] * deme.demography * deme.varPhenotypes[2]
            assert deme.politicsValues[
                "consensusTime"] == self.pop.fitnessParameters[
                    "epsilon"] + disagreement / (
                        self.pop.fitnessParameters["bconsensus"] +
                        disagreement)
    def test_fertility_depends_on_public_good(self, getFitnessParameters):
        fitfun = 'policing'
        self.fakepop = Pop(fit_fun=fitfun, inst='test/test')
        self.fakepop.fitnessParameters = getFitnessParameters(fitfun)
        self.fakepop.numberOfDemes = 2
        self.fakepop.initialDemeSize = 1
        self.fakepop.individualResources = 4
        self.fakepop.initialPhenotypes = [0.2, 0.3]
        self.fakepop.numberOfPhenotypes = len(self.fakepop.initialPhenotypes)
        self.fakepop.migrationRate = 0
        self.fakepop.mutationRate = 0

        self.fakepop.createAndPopulateDemes()
        self.fakepop.clearDemeInfo()
        self.fakepop.populationMutationMigration()

        for ind in range(self.fakepop.demography):
            indiv = self.fakepop.individuals[ind]
            if indiv.currentDeme == 0:
                self.fakepop.fitnessParameters.update({"pg": 1})
                indiv.fertility(self.fakepop.fit_fun,
                                **self.fakepop.fitnessParameters)
                fertility0 = indiv.fertilityValue
            elif indiv.currentDeme == 1:
                self.fakepop.fitnessParameters.update({"pg": 3})
                indiv.fertility(self.fakepop.fit_fun,
                                **self.fakepop.fitnessParameters)
                fertility1 = indiv.fertilityValue

        assert fertility0 < fertility1

        gc.collect()
    def test_consensus_value_defines_policing_amount(self):
        self.pop = Pop(inst='test/test')
        self.pop.fit_fun = 'debate'
        self.pop.initialPhenotypes = [0.1, 0.2, 0.3, 0.4]
        self.pop.numberOfDemes = 3
        self.pop.initialDemeSize = 2
        self.pop.mutationRate = 0
        self.pop.migrationRate = 0

        self.pop.createAndPopulateDemes()
        self.pop.clearDemeInfo()
        self.pop.populationMutationMigration()
        self.pop.updateDemeInfoPreProduction()
        self.pop.populationProduction()
        self.pop.updateDemeInfoPostProduction()

        allres = [0] * self.pop.numberOfDemes
        for ind in self.pop.individuals:
            allres[ind.currentDeme] += ind.resourcesAmount

        for deme in self.pop.demes:
            assert deme.progressValues["institutionQuality"] is not None
            assert deme.progressValues["institutionQuality"] == (
                deme.politicsValues['consensus'] * deme.publicGood *
                self.pop.fitnessParameters['aquality'] /
                allres[deme.id])**self.pop.fitnessParameters['alphaquality']
            assert deme.progressValues["fineBudget"] is not None
            assert deme.progressValues["fineBudget"] == deme.politicsValues[
                'consensus'] * deme.publicGood * (
                    1 - self.pop.fitnessParameters['aquality'])
    def test_group_labour_force_is_calculated_and_given_to_individual_instance(
            self):
        self.pop = Pop(fit_fun='technology', inst='test/test')
        self.pop.numberOfDemes = 3
        self.pop.initialDemeSize = 20
        self.pop.createAndPopulateDemes()
        self.deme = self.pop.demes[0]
        assert hasattr(self.deme, "progressValues"), "make dict"
        assert type(self.deme.progressValues) is dict
        progressKeys = ["fine", "investmentReward"]
        for key in progressKeys:
            assert key in self.deme.progressValues

        self.pop.clearDemeInfo()
        for pheno in self.pop.demes[0].meanPhenotypes:
            assert pheno is not None, "none phenotypes before migration"
        self.pop.populationMutationMigration()
        for pheno in self.pop.demes[0].meanPhenotypes:
            assert pheno is not None, "none phenotypes before update"
        self.pop.updateDemeInfoPreProduction()
        self.pop.populationProduction()
        self.pop.updateDemeInfoPostProduction()

        self.demeAFTER = self.pop.demes[0]
        for key in progressKeys:
            assert self.demeAFTER.progressValues[key] is not None
        # deme labour force = total private time: (demography - nleaders)(1-T1) + nleaders(1-T2)
        # where T1 and T2 is effective time spent in debate by civilian and leader respectively

        gc.collect()
예제 #8
0
    def test_migrants_destinations_equally_likely_as_in_uniform_distribution(
            self, pseudorandom, instantiateSingleIndividualsDemes):
        pseudorandom(69)
        self.fakepop = Pop(inst='test/test')
        self.ds = 100
        self.nd = 10
        self.fakepop.createAndPopulateDemes(nDemes=self.nd, dSize=self.ds)

        destinations = []

        for ind in range(self.fakepop.demography):
            indiv = self.fakepop.individuals[ind]
            indiv.migrate(nDemes=self.fakepop.numberOfDemes, migRate=1)
            destinations.append(indiv.destinationDeme)

        observedCountUnsorted = Counter(destinations)
        observedCount = []
        for key, val in sorted(observedCountUnsorted.items()):
            observedCount.append(val)

        expectedCount = [self.ds for i in range(self.nd)]

        chisq, pval = scistats.chisquare(observedCount, expectedCount)
        assert len(expectedCount) == len(
            observedCount), "len obs = {0}, len exp = {1}".format(
                len(observedCount), len(expectedCount))
        assert pval > 0.05, "Test for goodness of fit failed: obs = {0}, exp = {1}".format(
            observedCount, expectedCount)

        gc.collect()
    def test_technology_updates_with_correct_number(self):
        self.pop = Pop(fit_fun='technology', inst='test/test')
        self.pop.numberOfDemes = 2
        self.pop.initialDemeSize = 10
        self.pop.fit_fun = 'technology'
        self.pop.initialPhenotypes = [0.5] * 4
        self.pop.createAndPopulateDemes()

        assert self.pop.demes[
            0].technologyLevel == self.pop.initialTechnologyLevel, "wrong technology level assigned to deme when created"
        self.pop.clearDemeInfo()
        assert self.pop.demes[
            0].technologyLevel == self.pop.initialTechnologyLevel, "wrong technology level after first clearing"
        self.pop.populationMutationMigration()
        self.pop.updateDemeInfoPreProduction()
        self.pop.populationProduction()
        self.pop.updateDemeInfoPostProduction()
        # calculate new technology level as it should be
        publicGood = self.pop.demes[0].publicGood
        tech = self.pop.demes[0].technologyLevel
        tech_new = tech * (self.pop.fitnessParameters['atech'] +
                           ((1 - self.pop.fitnessParameters['p']) * publicGood)
                           **(1 - self.pop.fitnessParameters['betaTech'])) / (
                               1 + self.pop.fitnessParameters['btech'] * tech)
        self.pop.populationReproduction()
        self.pop.clearDemeInfo()
        assert self.pop.demes[
            0].technologyLevel == tech_new, "wrong value for new technology level."

        gc.collect()
    def test_deme_gets_number_of_leaders(self, pseudorandom,
                                         getFitnessParameters):
        pseudorandom(10)
        self.pop = Pop(fit_fun='socialclass', inst='test/test')
        self.pop.fitnessParameters = getFitnessParameters('socialclass')
        self.pop.numberOfDemes = 3
        self.pop.initialDemeSize = 1000
        self.pop.initialPhenotypes = [0.1, 0.2, 0.3, 0.6]
        self.pop.migrationRate = 0
        self.pop.mutationRate = 0

        self.pop.createAndPopulateDemes()
        self.pop.clearDemeInfo()
        self.pop.populationMutationMigration()
        self.pop.updateDemeInfoPreProduction()

        plead = self.pop.initialPhenotypes[3]

        for deme in self.pop.demes:
            nlead = deme.numberOfLeaders
            assert nlead is not None
            assert type(nlead) is int
            assert nlead >= 0
            assert pytest.approx(nlead / deme.demography, 0.1) == plead
            stat1, pval1 = scistats.ttest_1samp(
                [1] * nlead + [0] * (deme.demography - nlead), plead)
            #assert pval1 > 0.05, "T-test mean failed. Observed: {0}, Expected: {1}".format(nlead/deme.demography, plead)
            self.test = scistats.binom_test(nlead,
                                            deme.demography,
                                            plead,
                                            alternative="two-sided")
            assert self.test > 0.05, "Success rate = {0} when proportion of leaders = {1}".format(
                nlead / deme.demography, plead)

        gc.collect()
    def test_all_phenotype_means_in_output(self):
        self.ntraits = 4
        with open('test/test/' + INITIAL_PHENOTYPES_FILE, "w") as f:
            for i in range(self.ntraits):
                f.write('{0}\n'.format(i / self.ntraits))

        self.fakepop = Pop(inst='test/test')

        self.fakepop.numberOfDemes = 3
        self.fakepop.initialDemeSize = 2
        self.fakepop.numberOfGenerations = 5

        self.fakepop.createAndPopulateDemes()
        assert self.fakepop.numberOfPhenotypes == self.ntraits, "uh-oh, the test did not change the number of phenotypes"
        self.fakepop.runSimulation()

        with open('test/test/out_phenotypes.txt') as fp:
            firstline = fp.readline()
            phenotypeMeans = firstline.split(',')
        ### only take half of the line, since the second half is the variance in phenotypes, not the mean
        assert len(
            phenotypeMeans
        ) / 2 == self.ntraits, "Simulation returns mean of {0} phenotypes instead of {1}".format(
            len(phenotypeMeans), self.ntraits)

        os.remove('test/test/out_phenotypes.txt')
        os.remove('test/test/out_demography.txt')
    def test_demes_are_populated(self):
        self.pop = Pop(inst='test/test')
        self.pop.createAndPopulateDemes()
        for deme in self.pop.demes:
            assert deme.demography is not None, "Deme {0} is not populated".format(
                deme)

        gc.collect()
    def test_population_contains_demes(self):
        self.pop = Pop(inst='test/test')
        self.pop.createAndPopulateDemes()
        assert hasattr(self.pop, "demes"), "This population has no deme yet!"

        for deme in self.pop.demes:
            assert type(deme) is Dem

        gc.collect()
    def test_initial_deme_technology_is_not_null(self):
        self.pop = Pop(inst='test/test')
        self.pop.createAndPopulateDemes()

        assert type(self.pop.demes[0].technologyLevel
                    ) is float, "initial technology level info missing"
        assert self.pop.demes[
            0].technologyLevel > 0, "technology level cannot be null or negative"

        gc.collect()
예제 #15
0
    def test_migration_is_ran_at_the_population_level(self):
        self.fakepop = Pop(inst='test/test')
        self.nd = self.fakepop.numberOfDemes
        self.fakepop.createAndPopulateDemes(self.nd, 10)

        assert hasattr(self.fakepop, "populationMutationMigration"
                       ), "Migration cannot be ran at the population level"
        assert callable(self.fakepop.populationMutationMigration)

        gc.collect()
    def test_population_has_fitness_method_or_pgg_parameters(self):
        self.fakepop = Pop(inst='test/test')

        assert hasattr(self.fakepop,
                       "fitnessParameters"), "Provide fitness parameters"

        if not hasattr(self.fakepop, "fitnessMethod"):
            for key in ["fb", "b", "c", "gamma"]:
                assert key in self.fakepop.fitnessParameters, "PGG parameter {0} not provided".format(
                    key)
    def test_simulation_stops_if_population_extinct(self):
        self.fakepop = Pop(inst='test/test')
        self.fakepop.numberOfDemes = 10
        self.fakepop.numberOfGenerations = 10

        self.fakepop.fitnessParameters[
            "fb"] = 0.0001  # to make the population die out

        self.fakepop.createAndPopulateDemes()
        assert self.fakepop.demography == self.fakepop.numberOfDemes * self.fakepop.initialDemeSize
    def test_population_mutation_updates_individual_phenotypes(self):
        self.fakepop = Pop(inst='test/test')
        self.fakepop.numberOfDemes = 2
        self.fakepop.initialDemeSize = 50
        self.fakepop.migrationRate = 0
        self.fakepop.mutationRate = 1
        # the two following lines are very important so that the test does not fail at the boundaries,
        # e.g. if phen = 0 and dev < 0, mutated phenotype will still be 0
        self.fakepop.initialPhenotypes = [0.5]
        self.fakepop.numberOfPhenotypes = 1

        self.fakepop.createAndPopulateDemes(nDemes=self.fakepop.numberOfDemes,
                                            dSize=self.fakepop.initialDemeSize)

        origPhenDeme0 = []
        origPhenDeme1 = []

        for ind in self.fakepop.individuals:
            if ind.currentDeme == 0:
                origPhenDeme0.append(ind.phenotypicValues[0])
            elif ind.currentDeme == 1:
                origPhenDeme1.append(ind.phenotypicValues[0])

        self.fakepop.clearDemeInfo()
        self.fakepop.populationMutationMigration()

        phenDeme0 = []
        devDeme0 = []
        phenDeme1 = []
        devDeme1 = []

        for ind in self.fakepop.individuals:
            if ind.currentDeme == 0:
                phenDeme0.append(ind.phenotypicValues[0])
                devDeme0.append(ind.mutationDeviation[0])
            elif ind.currentDeme == 1:
                phenDeme1.append(ind.phenotypicValues[0])
                devDeme1.append(ind.mutationDeviation[0])

        assert len(origPhenDeme0) == len(
            phenDeme0
        ), "Number of individuals in deme 0 have changed from {0} to {1} after mutation".format(
            len(origPhenDeme0), len(phenDeme0))
        assert len(origPhenDeme1) == len(
            phenDeme1
        ), "Number of individuals in deme 1 have changed from {0} to {1} after mutation".format(
            len(origPhenDeme1), len(phenDeme1))

        for i in range(self.fakepop.initialDemeSize):
            assert origPhenDeme0[i] != phenDeme0[
                i], "Individual {0} in deme 0 mutated from {1} to {2} when deviation was supposed to be {3}".format(
                    i, origPhenDeme0[i], phenDeme0[i], devDeme0[i])
            assert origPhenDeme1[i] != phenDeme1[
                i], "Individual {0} in deme 1 mutated from {1} to {2} when deviation was supposed to be {3}".format(
                    i, origPhenDeme1[i], phenDeme1[i], devDeme1[i])
    def test_fitness_function_runs_at_population_level(self):
        self.pop = Pop(fit_fun='socialclass', inst='test/test')
        self.pop.numberOfDemes = 3
        self.pop.initialDemeSize = 5
        self.pop.initialPhenotypes = [0.9, 0.7, 0.5, 0.3]
        self.pop.createAndPopulateDemes()

        try:
            self.pop.lifecycle()
        except ValueError as e:
            assert False, str(e)
    def test_individual_attributes_are_non_empty(self,
                                                 objectAttributesAreNotNone):
        self.pop = Pop(inst='test/test')
        self.pop.createAndPopulateDemes()
        for ind in self.pop.individuals:
            testObj, attrObj = objectAttributesAreNotNone(
                ind, ["phenotypicValues", "currentDeme"])
            assert testObj, "Individual {0} has attribute(s) {1} set to None".format(
                ind, attrObj)

        gc.collect()
    def test_population_has_the_right_size(self):
        self.howManyDemes = 10
        self.howManyIndividualsPerDeme = 10
        self.pop = Pop(inst='test/test')
        self.pop.createAndPopulateDemes(nDemes=self.howManyDemes,
                                        dSize=self.howManyIndividualsPerDeme)

        assert len(
            self.pop.individuals
        ) == self.howManyIndividualsPerDeme * self.howManyDemes, "You created a population of {0} individuals instead of {1}!".format(
            len(self.pop.individuals),
            self.howManyIndividualsPerDeme * self.howManyDemes)
예제 #22
0
    def test_simulation_cycle(self):
        fakepop = Pop(fit_fun='policingdemog', inst='test/test')
        fakepop.numberOfDemes = 3
        fakepop.initialDemeSize = 10
        fakepop.numberOfGenerations = 10

        try:
            fakepop.runSimulation()
            for f in glob.glob('test/test/out_*.txt'):
                os.remove(f)
        except ValueError as e:
            assert False, str(e)
 def test_program_requires_valid_fitness_function(self, clearOutputFiles):
     self.population = Pop(fit_fun="gibberish", inst='test/test')
     setattr(self.population, "numberOfGenerations", 4)
     try:
         self.population.runSimulation()
     except KeyError as e:
         assert str(e).replace(
             "'", ""
         ) == 'Fitness function "gibberish" unknown. Add it to the functions in fitness.py', "Explain why the program fails!, not '{0}'".format(
             e)
     else:
         assert False, "The program should return an error message when trying to run simulations with unknown fitness function".format(
             self.population.numberOfDemes)
         clearOutputFiles('test/test/')
	def test_single_sim_reads_and_writes_from_same_folder(self):
		dirpath = Path('simulations')
		if dirpath.exists() and dirpath.is_dir():
			shutil.rmtree(dirpath)

		shutil.copytree('test/test', 'simulations')
		self.pop = Pop(inst='simulations')
		self.pop.numberOfGenerations = 3
		self.pop.runSimulation()

		self.outputfiles = ["out_consensus.txt", "out_demography.txt", "out_phenotypes.txt", "out_resources.txt", "out_technology.txt"] 

		for file in self.outputfiles:
			assert file in os.listdir('simulations')

		shutil.rmtree('simulations')
    def test_elections_take_place_in_demes(self, pseudorandom):
        pseudorandom(23)
        self.pop = Pop(fit_fun='socialclass', inst='test/test')
        self.pop.numberOfDemes = 2
        self.pop.initialDemeSize = 500
        self.pop.migrationRate = 0

        self.pop.createAndPopulateDemes()
        self.pop.clearDemeInfo()
        self.pop.populationMutationMigration()
        self.pop.updateDemeInfoPreProduction()

        for deme in self.pop.demes:
            assert deme.numberOfLeaders is not None
            assert deme.numberOfLeaders / deme.demography == pytest.approx(
                deme.meanPhenotypes[3], 1.4)
예제 #26
0
    def test_function_runs_at_population_level(self):
        fakepop = Pop(fit_fun='policingdemog', inst='test/test')
        fakepop.numberOfDemes = 3
        fakepop.initialDemeSize = 4

        fakepop.createAndPopulateDemes()
        fakepop.clearDemeInfo()
        fakepop.populationMutationMigration()
        fakepop.updateDemeInfoPreProduction()
        fakepop.populationProduction()
        fakepop.updateDemeInfoPostProduction()

        try:
            fakepop.populationReproduction()
        except:
            assert False, "not running"
 def test_simulations_only_run_on_structured_populations(
         self, clearOutputFiles):
     self.population = Pop(inst='test/test')
     setattr(self.population, "numberOfDemes", 1)
     setattr(self.population, "numberOfGenerations", 4)
     try:
         self.population.runSimulation()
     except ValueError as e:
         assert str(
             e
         ) == 'This program runs simulations on well-mixed populations only. "numberOfDemes" in initialisation.txt must be > 1', "Explain why the program fails!, not '{0}'".format(
             e)
     else:
         assert False, "You cannot let people run simulations on well-mixed populations (only {0} deme)!".format(
             self.population.numberOfDemes)
         clearOutputFiles('test/test/')
    def test_policing_function_in_population_reproduction(self):
        self.fakepop = Pop(inst='test/test', fit_fun='policing')
        self.fakepop.numberOfDemes = 3
        self.fakepop.initialDemeSize = 3
        self.fakepop.createAndPopulateDemes()
        self.fakepop.clearDemeInfo()
        self.fakepop.populationMutationMigration()
        self.fakepop.updateDemeInfoPreProduction()
        self.fakepop.populationProduction()
        self.fakepop.updateDemeInfoPostProduction()

        try:
            self.fakepop.populationReproduction()
        except Exception as e:
            assert False, "something went wrong, raised {0}: {1}".format(
                e.__class__.__name__, str(e))
    def test_consensus_is_aggregate_of_opinions(self):
        self.pop = Pop(inst='test/test')
        self.pop.fit_fun = 'debate'
        self.pop.initialPhenotypes = [0.1, 0.2, 0.3, 0.4]
        self.pop.numberOfDemes = 3
        self.pop.initialDemeSize = 2
        self.pop.mutationRate = 0
        self.pop.migrationRate = 0

        self.pop.createAndPopulateDemes()
        self.pop.clearDemeInfo()
        self.pop.populationMutationMigration()
        self.pop.updateDemeInfoPreProduction()

        for deme in self.pop.demes:
            assert deme.politicsValues[
                "consensus"] == 0.3, "wrong consensus value"
    def test_identify_deme_neighbours(self):
        self.fakepop = Pop(inst='test/test')
        self.nd = self.fakepop.numberOfDemes

        for deme in range(self.nd):
            newDemeInstance = Dem()
            newDemeInstance.id = deme
            assert deme in range(self.nd)
            newDemeInstance.neighbours = self.fakepop.identifyNeighbours(
                self.nd, deme)
            assert deme not in newDemeInstance.neighbours, "Deme {0} counts itself as a neighbour".format(
                deme)
            assert all(
                x in range(self.nd) for x in newDemeInstance.neighbours
            ), "Neighbour(s) of deme {0} are missing: takes into account {1} out of its {2} neighbours".format(
                deme, newDemeInstance.neighbours, self.nd - 1)

        gc.collect()