def many_runs(crowd, period): counter = 0 best_run = 0 best_date = ZERO_DATE best_population = 0 best_genome = Genes.protogenome_profile while True: counter += 1 print(f'Номер симуляции: {counter}') print(f'Лучший прогон:{best_run:3d}. Дата: {best_date.display()}') town = main.Simulation(crowd, Date(period)) result, final_date = town.simulate() print(f'Последний год: {final_date.display()}') current_genome = Genes.protogenome_profile print( f'{"Теущ. геном":13s} :{main.display_start_genotype(current_genome)}' ) if best_date < final_date: best_date = final_date best_run = counter best_genome = current_genome print( f'{"Лучший геном":13s} :{main.display_start_genotype(best_genome)}' ) if result: break else: town.close()
def count_avg_death_age(self): summa = 0 for person in self.dead_pool_avg: summa += (person.age.death_date - person.age.birth_date).len() ld = len(self.dead_pool_avg) if ld > 0: avg_date = summa / ld else: avg_date = 0 return Date(0, 0, avg_date).years_float()
def __init__(self, person, age=ZERO_DATE): self.person = person # сколько еды удалось достать за ход self.have_food = 0 # странная переменная. Нужна для статистики, чтобы показывватьь, сколько еды было у человека до перераспределения # то есть предполагается, что будет выводиться сравнение, сколько еды было изначально, и сколько стало по слеперераспределения. Но перераспределений может быть несколько self.have_food_prev = 0 # Определяем запас здоровья человека через его предполагаемый возраст. # Задаем его предполагаемый возраст смерти, отнимаем текущий возраст, переводим в дни и умнодаем на дневную норму очков жизни # определяем возраст смерти персоны (минимум: 55 - 48; максимум: 55 + 48) presume_life: Date = STAGE_DICT[Stage_of_age.AGED] + Date(prop.gauss_sigma_16()) months: int = random.randrange(2 * Date.MONTHS_IN_YEAR) - Date.MONTHS_IN_YEAR #+- меяцев к жизни days: int = random.randrange(2 * Date.DAYS_IN_MONTH) - Date.DAYS_IN_MONTH #+- дней к жизни presume_life += Date(0, months, days) self.health: Date = presume_life - age # здоровье - это количество дней до смерти умноженных на коэффициент self.health: float = HEALTH_PER_DAY * float(self.health.len()) # здоровье это число, а не дата self.satiety = 5 # сытость. При рождении сытость нормальная. self.food_sum = 0
def count_death_distribution(self): death_age = [0 for i in range(11)] number_of_dead_people = 0 nomb_men = 0 nomb_women = 0 men_death_sum = 0 women_death_sum = 0 def death_dist(person): nonlocal death_age nonlocal number_of_dead_people number_of_dead_people += 1 dec_index = int( (person.age.death_date - person.age.birth_date).years_float() // 10) if dec_index > 10: dec_index = 10 death_age[dec_index] += 1 def death_gender(person): nonlocal nomb_men nonlocal nomb_women nonlocal men_death_sum nonlocal women_death_sum if person.gender is Gender.MALE: nomb_men += 1 men_death_sum += (person.age.death_date - person.age.birth_date).years_float() else: nomb_women += 1 women_death_sum += (person.age.death_date - person.age.birth_date).years_float() for person in self.socium.soc_list: if not person.is_alive and self.socium.anno < ( person.age.death_date + Date(MEASURMENT_PERIOD)): death_dist(person) death_gender(person) s = "%s\t" % str(self.socium.anno.year) for i in range(len(death_age)): if number_of_dead_people == 0: s += "0\t" else: s += "%5f\t" % (death_age[i] / number_of_dead_people * 100) am = 0 if nomb_men == 0 else men_death_sum / nomb_men aw = 0 if nomb_women == 0 else women_death_sum / nomb_women s += "%5f\t%5f" % (am, aw) s = s[:-1].replace(".", ",") + "\n" self.death_dist.write(s)
def many_sucsessful_runs(period, estimated_people): global EXPERIMENTS while True: t = datetime.datetime.now() st = t.strftime("%H:%M:%S %d.%m.%Y") print(f'симуляция № {EXPERIMENTS} {st}') town = main.Simulation(Date(period), estimated_people) town.populate(main.FIRST_POPULATION) town.soc.roll_genome() result, final_date, _ = town.simulate() EXPERIMENTS += 1 if result: print(main.display_start_genotype(Genes.protogenome_profile)) town.close()
def get_stage_by_age(self, age_int: int) -> Tuple[Stage_of_age, Date]: s = Stage_of_age.BABY t = ZERO_DATE age_date = Date(age_int) for stage in STAGE_DICT: # возраст наступления следующей стадии age_of_next_stage = STAGE_DICT[stage.value] if age_date < age_of_next_stage: s = stage t = age_of_next_stage break if t == ZERO_DATE: raise Exception( f'Ошибка определения фазы возраста у человека {self.age.person.id} {self.age.person}' ) return s, t
def write_human_state(town): town.every_man_state_log.write( "================================================\n") town.every_man_state_log.write(f'{town.soc.anno.display()}\n') town.every_man_state_log.write( f'население: {town.soc.stat.people_alive_number}\n') for i in town.soc.people_alive: anno_date = f'{town.soc.anno.year}:{ town.soc.anno.month}' famil = f' {i.family.id}' a = i.id satge_name = i.age.stage.name sex = "М" if i.gender is common.Gender.MALE else "Ж" b = i.genes.get_trait(genetics.GN.STRONGNESS) c = i.genes.get_trait(genetics.GN.ABSTINENCE) d = i.health.satiety e = Date(0, 0, round(i.health.health / genetics.HEALTH_PER_DAY)).display(False) fb = -i.health.food_sum hf = i.health.have_food z = anno_date + famil z += f' {a}| {sex}|{i.age.display():14s}| {satge_name:7s}| str= {b:2d}| abs= {c:2d}| sat= {d:2d}| ' \ f'food= {hf:5.1f}| hbonus= {fb:6.1f}| healt={i.health.health:6.1f}| lifetim={e}\n' town.every_man_state_log.write(z)
def update_deadpool(self): temp = [] for person in self.dead_pool_avg: if self.socium.anno < (person.age.death_date + Date(5)): temp.append(person) self.dead_pool_avg = temp
def count_children(self): children_male = [0 for i in range(CHILDREN_COUNT_TRESHOLD)] children_female = [0 for i in range(CHILDREN_COUNT_TRESHOLD)] no_male = 0 no_female = 0 for person in self.socium.soc_list: if person.age.stage is Stage_of_age.ADULT and \ (person.age.death_date is None or self.socium.anno < (person.age.death_date + Date(MEASURMENT_PERIOD))): # считаем количество детей у мужчин и у женщин по отдельности ch = len(person.children) if ch >= CHILDREN_COUNT_TRESHOLD: ch = CHILDREN_COUNT_TRESHOLD - 1 if person.gender is Gender.MALE: no_male += 1 children_male[ch] += 1 else: no_female += 1 children_female[ch] += 1 rec_m = rec_f = "%s\t" % str(self.socium.anno.year) ch_aver_male = 0 ch_aver_fem = 0 for i in range(len(children_female)): ch_aver_male += i * children_male[i] ch_aver_fem += i * children_female[i] if no_male == 0: rec_m += " 0\t" else: rec_m += "%5f\t" % (children_male[i] / no_male * 100) if no_female == 0: rec_f += " 0\t" else: rec_f += "%5f\t" % (children_female[i] / no_female * 100) if no_male == 0: ch_aver_male = 0 else: ch_aver_male /= no_male if no_female == 0: ch_aver_fem = 0 else: ch_aver_fem /= no_female rec_ave = "%d\t%5f\t%5f\n" % (self.socium.anno.year, ch_aver_male, ch_aver_fem) rec_ave = rec_ave.replace(".", ",") self.childern_average.write(rec_ave) rec_m = rec_m[:-1].replace(".", ",") + "\n" rec_f = rec_f[:-1].replace(".", ",") + "\n" self.children_m.write(rec_m) self.children_f.write(rec_f)
from soc_time import Date from human import Human from socium import Socium import family import causes import soc_time import common import genetics # хочется повторяемости картины, фиксируем сид random.seed(664) # количество людей в начальной популяции FIRST_POPULATION = 20 TIMELINE = Date(200) # количество лет симуляции HOME_DIR = os.getcwd() class Simulation: def __init__(self, timeline, estimate_people): self.estimate_people = estimate_people self.init_logs() self.soc = Socium(1000, self.estimate_people) # создется социум self.timeline = timeline def init_logs(self): common.init_sim_dir() self.lohfile = open("./population.txt", "w", encoding="UTF16") self.every_man_state_log = open("./human_state.txt", "w",
import csv import random from pprint import pprint import common from soc_time import Date, Anno #import family from family import Family from causes import BiolParents from human import Human from fdistrib import FoodDistribution import statistics import genetics TIME_TO_EXCLUDE_DEAD_ANCESTORS = Date(40) class Socium: ESTIMAED_NUMBER_OF_PEOPLE = None FOOD_RESOURCE = None def __init__(self, anno=1000, estimate_people=100): # список всех людей в социуме, на данный момент включая мертвых (проверить) self.roll_genome() Socium.class_var_init(estimate_people) Human.init_files() Family.init_files() FoodDistribution.init_files() self.soc_list: List[Human] = list() self.families: List[Family] = list()
class Stage_of_age(int, Enum): BABY = 0 CHILD = 1 TEEN = 2 YOUNG = 3 ADULT = 4 AGED = 5 SENILE = 6 STAGE_LIST = list(Stage_of_age) STAGE_DICT = { Stage_of_age.BABY: Date(6), Stage_of_age.CHILD: Date(12), Stage_of_age.TEEN: Date(17), Stage_of_age.YOUNG: Date(28), Stage_of_age.ADULT: Date(55), Stage_of_age.AGED: Date(70), Stage_of_age.SENILE: Date(100_000) } # множитель еды для насыщения в зависимости от возраста ''' На самом деле это не вполне насыщение. Планируется, что это будет коэффициент усвоения пищи человек может съесть много пищи, но она плохо усвоится, и у человека не будет сил на какие-то действия а насыщение зависит от размера желудка. У старого человека он не увеличивается. Он будет насыщаться тем же количеством пищи, что и молодой. вобще-то это у меня уже реализовано, что старик не будет себе брать 1.7 от нормы пищи. Иначе старики никогда бы не
self.cause = self.cause.NONE class HumanRecCause: def __init__(self, hum: int, start: Date, cause: Generic[T], finish: Date = FAR_FUTURE): self.human = hum self.start = start self.finish = finish self.cause: T = cause.NONE start_date = Date(1000, 1, 1) finish_date = Date(1010, 1, 1) a = HumanRecCause(1, start_date, SpouseCause.NONE) b = HumanRecCause(1, start_date, ParentCause.NONE) print(a.cause) print('---------------') a.cause = SpouseCause.DEATH b.cause = ParentCause.PDEATH print(a.cause) print(b.cause) print(a.cause == b.cause) print('---------------') print('---------------') print('---------------')
from genetics import GN from common import Stage_of_age, Age, STAGE_DICT, Gender, apply_gender import prop import family from causes import (Spouses, BiolParents, SocParents, SpouseCause) import score from soc_time import Date, ZERO_DATE, TIK, YEAR, FAR_FUTURE import fetus # подгоночный коэффициент для беременности, чтобы человек с фертильностью 5 # забеременнил где-то два раза за фертильный возраст PREGNANCY_CONST = 0.218 # беременность должна длиться три четверти года PREGNANCY_DURATION = Date(0, 0, round(Date.DAYS_IN_YEAR * 3 / 4)) DIVROCE_CHANSE = 1 / ( 2 * 20 * Date.DAYS_IN_YEAR ) / 40 # вероятность развестись раз в 20 лет, плюс проверяют оба супруга а еще подгоночный коэффициент FERTIL_RERIOD = (STAGE_DICT[Stage_of_age.AGED] - STAGE_DICT[Stage_of_age.ADULT]).year \ * Date.DAYS_IN_MONTH * Date.MONTHS_IN_YEAR PREGNANCY_CHANCE = PREGNANCY_CONST / FERTIL_RERIOD class Human: GLOBAL_HUMAN_NUMBER: int = 0 chronicle: IO chronicle_stranger_come = '{0}| В социум влился {1}, возраст - {2} лет.' chronicle_marriage = '{0}| {1}| свадьба между {2}({3}) и {4}({5})'
def set_health(self, years): self.health: float = HEALTH_PER_DAY * float(Date(years).len())