示例#1
0
    def labor_market(self, jobs):
        tasks = [p.get('employer') for p in self.people]
        applicants = {f: [] for (_, __), f in jobs}
        employers = yield from asyncio.gather(*tasks)
        job_seekers = [p for p, e in zip(self.people, employers) if e is None]
        while job_seekers and jobs:
            job_dist = self.job_distribution(jobs)
            for p in shuffle(job_seekers):
                (n_vacancies, wage), firm  = random_choice(job_dist)
                applicants[firm].append(p)

            # firms select from their applicants
            _jobs = []
            for job in shuffle(jobs):
                # filter down to valid applicants
                (n_vacancies, wage), firm = job
                apps = [a for a in applicants[firm] if a in job_seekers]
                hired, n_vacancies, wage = yield from firm.call('hire', apps, wage)

                # remove hired people from the job seeker pool
                for p in hired:
                    job_seekers.remove(p)

                if not job_seekers:
                    break

                # if vacancies remain, post the new jobs with the new wage
                if n_vacancies:
                    _jobs.append(((n_vacancies, wage), firm))
            jobs = _jobs
示例#2
0
    def healthcare_market(self):
        sold = []
        hospitals = [h for h in self.hospitals]
        for person in shuffle(self.people):
            if person._state['health'] < 1.:
                affordable = [
                    h for h in hospitals if h.price <= person._state['cash']
                ]
                if not affordable:
                    continue
                utilities = [
                    person.health_change_utility(1 - person._state['health']) +
                    person.cash_change_utility(-h.price) for h in affordable
                ]
                u_t = sum(utilities)
                choices = [(h, u / u_t) for h, u in zip(hospitals, utilities)]
                hospital = random_choice(choices)
                hospital.sell(1)
                person._state['cash'] -= hospital.price
                person._state['health'] = 1
                person._state['sick'] = False if random.random(
                ) < self.state['recovery_prob'] else True
                sold.append(hospital.price)
                if hospital.supply == 0:
                    hospitals.remove(hospital)
                if not hospitals:
                    break

        profits = [f.revenue - f.costs for f in self.hospitals]
        return sold, profits
示例#3
0
    def step(self):
        tasks = [firm.call('set_production_target', self.state) for firm in shuffle(self.firms)]
        jobs = yield from asyncio.gather(*tasks)
        jobs = list(zip(jobs, self.firms))
        yield from self.labor_market(jobs)

        yield from asyncio.gather(*[firm.call('produce', self.state) for firm in self.raw_material_firms])

        # raw material market
        sold = yield from self.market(
            self.raw_material_firms,
            self.consumer_good_firms + self.capital_equipment_firms,
            'purchase_materials')
        print('materials: ${:.2f}'.format(self.mean_sales_price(sold)))

        yield from asyncio.gather(*[firm.call('produce', self.state) for firm in self.capital_equipment_firms])

        # capital equipment market
        sold = yield from self.market(
            self.capital_equipment_firms,
            self.consumer_good_firms + self.raw_material_firms,
            'purchase_equipment')
        print('equipment: ${:.2f}'.format(self.mean_sales_price(sold)))

        yield from asyncio.gather(*[firm.call('produce', self.state) for firm in self.consumer_good_firms])

        # consumer good market
        sold = yield from self.market(
            self.consumer_good_firms,
            self.people,
            'purchase_goods')
        print('consumer goods: ${:.2f}'.format(self.mean_sales_price(sold)))

        # people consume (reset) their goods
        yield from asyncio.gather(*[p.call('consume') for p in self.people])
示例#4
0
文件: city.py 项目: MaxwellRebo/hosny
    def consumer_good_market(self):
        firm_dist = self.firm_distribution(self.consumer_good_firms)

        sold = []
        households = [h for h in self.households]
        rounds = 0
        while households and firm_dist and rounds < MAX_ROUNDS:
            for household in shuffle(households):
                supplier = random_choice(firm_dist)
                desired, purchased = household.purchase_goods(supplier)
                sold.append((purchased, supplier.price))

                if desired == 0:
                    households.remove(household)

                # if supplier sold out, update firm distribution
                if supplier.supply == 0:
                    firm_dist = self.firm_distribution(self.consumer_good_firms)

                if not firm_dist:
                    break
            rounds += 1

        profits = [f.revenue - f.costs for f in self.consumer_good_firms]
        return sold, profits
示例#5
0
文件: city.py 项目: MaxwellRebo/hosny
    def labor_market(self, jobs):
        job_seekers = [p for p in self.people if p.seeking_job(self.state)]
        applicants = {f: [] for _, __, f in jobs}

        # iterate until there are no more job seekers or no more jobs
        while job_seekers and jobs:
            # job seekers apply to jobs which satisfy their wage criteria
            # TODO should they apply to anything if nothing satifies their
            # criteria?
            for p in shuffle(job_seekers):
                for job in jobs:
                    n_vacancies, wage, firm = job
                    if wage >= p.wage_minimum:
                        applicants[firm].append(p)

            # firms select from their applicants
            _jobs = []
            for job in jobs:
                # filter down to valid applicants
                n_vacancies, wage, firm = job
                apps = [a for a in applicants[firm] if a in job_seekers]
                hired, n_vacancies, wage = firm.hire(apps, wage, self.state)

                # remove hired people from the job seeker pool
                for p in hired:
                    job_seekers.remove(p)

                if not job_seekers:
                    break

                # if vacancies remain, post the new jobs with the new wage
                if n_vacancies:
                    _jobs.append((n_vacancies, wage, firm))
            jobs = _jobs
示例#6
0
    def consumer_good_market(self):
        firm_dist = self.firm_distribution(self.consumer_good_firms)

        sold = []
        households = [h for h in self.households]
        rounds = 0
        while households and firm_dist and rounds < MAX_ROUNDS:
            for household in shuffle(households):
                supplier = random_choice(firm_dist)
                desired, purchased = household.purchase_goods(supplier)
                sold.append((purchased, supplier.price))

                if desired == 0:
                    households.remove(household)

                # if supplier sold out, update firm distribution
                if supplier.supply == 0:
                    firm_dist = self.firm_distribution(
                        self.consumer_good_firms)

                if not firm_dist:
                    break
            rounds += 1

        profits = [f.revenue - f.costs for f in self.consumer_good_firms]
        return sold, profits
示例#7
0
    def labor_market(self, jobs):
        job_seekers = [p for p in self.people if p.seeking_job(self.state)]
        applicants = {f: [] for _, __, f in jobs}

        # iterate until there are no more job seekers or no more jobs
        while job_seekers and jobs:
            # job seekers apply to jobs which satisfy their wage criteria
            # TODO should they apply to anything if nothing satifies their
            # criteria?
            for p in shuffle(job_seekers):
                for job in jobs:
                    n_vacancies, wage, firm = job
                    if wage >= p.wage_minimum:
                        applicants[firm].append(p)

            # firms select from their applicants
            _jobs = []
            for job in jobs:
                # filter down to valid applicants
                n_vacancies, wage, firm = job
                apps = [a for a in applicants[firm] if a in job_seekers]
                hired, n_vacancies, wage = firm.hire(apps, wage, self.state)

                # remove hired people from the job seeker pool
                for p in hired:
                    job_seekers.remove(p)

                if not job_seekers:
                    break

                # if vacancies remain, post the new jobs with the new wage
                if n_vacancies:
                    _jobs.append((n_vacancies, wage, firm))
            jobs = _jobs
示例#8
0
    def market(self, sellers, buyers, purchase_func):
        sold = []
        seller_dist = yield from self.firm_distribution(sellers)

        while buyers and seller_dist:
            for buyer in shuffle(buyers):
                supplier = random_choice(seller_dist)
                required, purchased = yield from buyer.call(purchase_func, supplier)
                supply, price = yield from supplier.get('supply', 'price')
                sold.append((purchased, price))
                if required == 0:
                    buyers.remove(buyer)

                # if supplier sold out, update firm distribution
                if supply == 0:
                    seller_dist = yield from self.firm_distribution(sellers)

                if not seller_dist:
                    break
        return sold
示例#9
0
文件: city.py 项目: MaxwellRebo/hosny
    def capital_equipment_market(self):
        sold = []
        firm_dist = self.firm_distribution(self.capital_equipment_firms)

        firms = self.consumer_good_firms + self.raw_material_firms
        rounds = 0
        while firms and firm_dist and rounds < MAX_ROUNDS:
            for firm in shuffle(firms):
                supplier = random_choice(firm_dist)
                required, purchased = firm.purchase_equipment(supplier)
                sold.append((purchased, supplier.price))
                if required == 0:
                    firms.remove(firm)

                # if supplier sold out, update firm distribution
                if supplier.supply == 0:
                    firm_dist = self.firm_distribution(self.capital_equipment_firms)

                if not firm_dist:
                    break
            rounds += 1
        profits = [f.revenue - f.costs for f in self.capital_equipment_firms]
        return sold, profits
示例#10
0
    def raw_material_market(self):
        sold = []
        firm_dist = self.firm_distribution(self.raw_material_firms)

        firms = self.consumer_good_firms + self.capital_equipment_firms
        rounds = 0
        while firms and firm_dist and rounds < MAX_ROUNDS:
            for firm in shuffle(firms):
                supplier = random_choice(firm_dist)
                required, purchased = firm.purchase_materials(supplier)
                sold.append((purchased, supplier.price))
                if required == 0:
                    firms.remove(firm)

                # if supplier sold out, update firm distribution
                if supplier.supply == 0:
                    firm_dist = self.firm_distribution(self.raw_material_firms)

                if not firm_dist:
                    break
            rounds += 1
        profits = [f.revenue - f.costs for f in self.raw_material_firms]
        return sold, profits
示例#11
0
文件: city.py 项目: MaxwellRebo/hosny
    def healthcare_market(self):
        sold = []
        hospitals = [h for h in self.hospitals]
        for person in shuffle(self.people):
            if person._state['health'] < 1.:
                affordable = [h for h in hospitals if h.price <= person._state['cash']]
                if not affordable:
                    continue
                utilities = [person.health_change_utility(1 - person._state['health']) + person.cash_change_utility(-h.price) for h in affordable]
                u_t = sum(utilities)
                choices = [(h, u/u_t) for h, u in zip(hospitals, utilities)]
                hospital = random_choice(choices)
                hospital.sell(1)
                person._state['cash'] -= hospital.price
                person._state['health'] = 1
                person._state['sick'] = False if random.random() < self.state['recovery_prob'] else True
                sold.append(hospital.price)
                if hospital.supply == 0:
                    hospitals.remove(hospital)
                if not hospitals:
                    break

        profits = [f.revenue - f.costs for f in self.hospitals]
        return sold, profits
示例#12
0
文件: city.py 项目: MaxwellRebo/hosny
    def step(self):
        """one time step in the model (a day)"""
        super().step()

        prev_month = self.date.month

        self.date += relativedelta(days=1)
        self.state['month'] = self.date.month
        self.state['year'] = self.date.year

        self._log('step', {
            'people': [p.as_json() for p in self.people]
        })
        self._log('datetime', {'month': self.date.month, 'day': self.date.day, 'year': self.date.year})

        if not self.initialized:
            # create initial firms
            for person in self.people:
                if person._state['firm_owner']:
                    industry = random.choice(['equip', 'material', 'consumer_good', 'healthcare'])
                    building = random.choice(self.buildings)
                    self.start_firm(person, industry, building)
            self.initialized = True

        # month change
        if prev_month != self.date.month:
            # pay rent
            for building in self.buildings:
                for tenant in building.tenants:
                    tenant.pay(building.rent)

        for household in self.households:
            household.step()

        n_deaths = self.contagion_model()
        self.stat('n_sick', len([p for p in self.people if p._state['sick']]))

        # self.real_estate_market()

        # see if anyone want to start a business
        # only possible if there is space available to rent
        self.state['available_space'] = sum(b.available_space for b in self.buildings)
        n_tenants = sum(len(b.tenants) for b in self.buildings)
        mean_rent = sum(b.rent * len(b.tenants) for b in self.buildings)/n_tenants if n_tenants else 0
        self.ewma_stat('mean_rent', mean_rent, graph=True)
        if self.state['available_space']:
            for person in shuffle(self.people):
                yes, industry, building = person.start_business(self.state, self.buildings)
                if yes:
                    self.start_firm(person, industry, building)

        jobs = []
        for firm in shuffle(self.firms):
            n_vacancies, wage = firm.set_production_target(self.state)
            jobs.append((n_vacancies, wage, firm))

        self.labor_market(jobs)

        labor_force = [p for p in self.people if p.wage != 0]
        mean_wage = sum(p.wage for p in labor_force)/len(labor_force) if labor_force else 0
        self.ewma_stat('mean_wage', mean_wage, graph=True)

        for firm in self.raw_material_firms:
            firm.produce(self.state)

        sold, profits = self.raw_material_market()
        mean = sum(profits)/len(profits) if profits else 0
        self.ewma_stat('mean_material_profit', mean, graph=True)

        sell_prices = []
        for amt, price in sold:
            sell_prices += [price for _ in range(amt)]
        mean = sum(sell_prices)/len(sell_prices) if sell_prices else 0
        self.ewma_stat('mean_material_price', mean, graph=True)

        for firm in self.capital_equipment_firms:
            firm.produce(self.state)

        sold, profits = self.capital_equipment_market()
        mean = sum(profits)/len(profits) if profits else 0
        self.ewma_stat('mean_equip_profit', mean, graph=True)

        sell_prices = []
        for amt, price in sold:
            sell_prices += [price for _ in range(amt)]
        mean = sum(sell_prices)/len(sell_prices) if sell_prices else 0
        self.ewma_stat('mean_equip_price', mean, graph=True)

        for firm in self.consumer_good_firms:
            firm.produce(self.state)

        sold, profits = self.consumer_good_market()
        mean = sum(profits)/len(profits) if profits else 0
        self.ewma_stat('mean_consumer_good_profit', mean, graph=True)

        sell_prices = []
        for amt, price in sold:
            sell_prices += [price for _ in range(amt)]
        mean = sum(sell_prices)/len(sell_prices) if sell_prices else 0
        self.ewma_stat('mean_consumer_good_price', mean, graph=True)

        for household in self.households:
            if not household.check_goods():
                for p in household.people:
                    self.dies(p)
                    n_deaths += 1
        self.stat('n_deaths', n_deaths)
        self.stat('n_population', len(self.people))

        # taxes and wages
        for person in self.people:
            taxes = 0
            if person._state['firm_owner']:
                profit = max(person.firm.profit, 0)
                taxes = profit * self.government.tax_rate
                person.firm.cash -= taxes
            elif person.employer is not None:
                wage = min(person.wage, person.employer.cash)
                taxes = wage * self.government.tax_rate
                person._state['cash'] += (wage - taxes)
                # TODO should people keep track of how much they are _actually_
                # paid vs their stated wage?
            self.government.cash += taxes

        for firm in self.hospitals:
            firm.produce(self.state)

        sold, profits = self.healthcare_market()
        mean = sum(profits)/len(profits) if profits else 0
        self.ewma_stat('mean_healthcare_profit', mean, graph=True)
        mean = sum(sold)/len(sold) if sold else 0
        self.ewma_stat('mean_healthcare_price', mean, graph=True)

        # TODO this should be limited by the amount of cash the gov't actual
        # has, or should deficit spending be ok?
        # gov't subsidies
        subs = self.government.subsidies
        subsidy = subs[CapitalEquipmentFirm]/len(self.capital_equipment_firms) if self.capital_equipment_firms else 0
        for firm in self.capital_equipment_firms:
            firm.cash += subsidy
        subsidy = subs[CapitalEquipmentFirm]/len(self.capital_equipment_firms) if self.capital_equipment_firms else 0
        for firm in self.consumer_good_firms:
            firm.cash += subsidy
        subsidy = subs[RawMaterialFirm]/len(self.raw_material_firms) if self.raw_material_firms else 0
        for firm in self.raw_material_firms:
            firm.cash += subsidy

        n_bankruptcies = 0
        for firm in self.firms:
            # bankrupt
            if firm.cash < 0:
                n_bankruptcies += 1
                self.close_firm(firm)

        self.stat('n_bankruptcies', n_bankruptcies)
        self.stat('n_firms', len(self.firms))

        mean_quality_of_life = sum(h.quality_of_life for h in self.households)/len(self.households) if self.households else 0
        self.ewma_stat('mean_quality_of_life', mean_quality_of_life, graph=True)

        mean_cash = sum(h.cash for h in self.households)/len(self.households) if self.households else 0
        self.ewma_stat('mean_cash', mean_cash, graph=True)

        self.government.adjust(self.households)
        self.stat('welfare', self.government.welfare)
        self.stat('tax_rate', self.government.tax_rate)

        for person in self.people:
            person._state['cash'] += self.government.welfare
            self.government.cash -= self.government.welfare
示例#13
0
    def step(self):
        """one time step in the model (a day)"""
        super().step()

        prev_month = self.date.month

        self.date += relativedelta(days=1)
        self.state['month'] = self.date.month
        self.state['year'] = self.date.year

        self._log('step', {'people': [p.as_json() for p in self.people]})
        self._log('datetime', {
            'month': self.date.month,
            'day': self.date.day,
            'year': self.date.year
        })

        if not self.initialized:
            # create initial firms
            for person in self.people:
                if person._state['firm_owner']:
                    industry = random.choice(
                        ['equip', 'material', 'consumer_good', 'healthcare'])
                    building = random.choice(self.buildings)
                    self.start_firm(person, industry, building)
            self.initialized = True

        # month change
        if prev_month != self.date.month:
            # pay rent
            for building in self.buildings:
                for tenant in building.tenants:
                    tenant.pay(building.rent)

        for household in self.households:
            household.step()

        n_deaths = self.contagion_model()
        self.stat('n_sick', len([p for p in self.people if p._state['sick']]))

        # self.real_estate_market()

        # see if anyone want to start a business
        # only possible if there is space available to rent
        self.state['available_space'] = sum(b.available_space
                                            for b in self.buildings)
        n_tenants = sum(len(b.tenants) for b in self.buildings)
        mean_rent = sum(
            b.rent * len(b.tenants)
            for b in self.buildings) / n_tenants if n_tenants else 0
        self.ewma_stat('mean_rent', mean_rent, graph=True)
        if self.state['available_space']:
            for person in shuffle(self.people):
                yes, industry, building = person.start_business(
                    self.state, self.buildings)
                if yes:
                    self.start_firm(person, industry, building)

        jobs = []
        for firm in shuffle(self.firms):
            n_vacancies, wage = firm.set_production_target(self.state)
            jobs.append((n_vacancies, wage, firm))

        self.labor_market(jobs)

        labor_force = [p for p in self.people if p.wage != 0]
        mean_wage = sum(
            p.wage
            for p in labor_force) / len(labor_force) if labor_force else 0
        self.ewma_stat('mean_wage', mean_wage, graph=True)

        for firm in self.raw_material_firms:
            firm.produce(self.state)

        sold, profits = self.raw_material_market()
        mean = sum(profits) / len(profits) if profits else 0
        self.ewma_stat('mean_material_profit', mean, graph=True)

        sell_prices = []
        for amt, price in sold:
            sell_prices += [price for _ in range(amt)]
        mean = sum(sell_prices) / len(sell_prices) if sell_prices else 0
        self.ewma_stat('mean_material_price', mean, graph=True)

        for firm in self.capital_equipment_firms:
            firm.produce(self.state)

        sold, profits = self.capital_equipment_market()
        mean = sum(profits) / len(profits) if profits else 0
        self.ewma_stat('mean_equip_profit', mean, graph=True)

        sell_prices = []
        for amt, price in sold:
            sell_prices += [price for _ in range(amt)]
        mean = sum(sell_prices) / len(sell_prices) if sell_prices else 0
        self.ewma_stat('mean_equip_price', mean, graph=True)

        for firm in self.consumer_good_firms:
            firm.produce(self.state)

        sold, profits = self.consumer_good_market()
        mean = sum(profits) / len(profits) if profits else 0
        self.ewma_stat('mean_consumer_good_profit', mean, graph=True)

        sell_prices = []
        for amt, price in sold:
            sell_prices += [price for _ in range(amt)]
        mean = sum(sell_prices) / len(sell_prices) if sell_prices else 0
        self.ewma_stat('mean_consumer_good_price', mean, graph=True)

        for household in self.households:
            if not household.check_goods():
                for p in household.people:
                    self.dies(p)
                    n_deaths += 1
        self.stat('n_deaths', n_deaths)
        self.stat('n_population', len(self.people))

        # taxes and wages
        for person in self.people:
            taxes = 0
            if person._state['firm_owner']:
                profit = max(person.firm.profit, 0)
                taxes = profit * self.government.tax_rate
                person.firm.cash -= taxes
            elif person.employer is not None:
                wage = min(person.wage, person.employer.cash)
                taxes = wage * self.government.tax_rate
                person._state['cash'] += (wage - taxes)
                # TODO should people keep track of how much they are _actually_
                # paid vs their stated wage?
            self.government.cash += taxes

        for firm in self.hospitals:
            firm.produce(self.state)

        sold, profits = self.healthcare_market()
        mean = sum(profits) / len(profits) if profits else 0
        self.ewma_stat('mean_healthcare_profit', mean, graph=True)
        mean = sum(sold) / len(sold) if sold else 0
        self.ewma_stat('mean_healthcare_price', mean, graph=True)

        # TODO this should be limited by the amount of cash the gov't actual
        # has, or should deficit spending be ok?
        # gov't subsidies
        subs = self.government.subsidies
        subsidy = subs[CapitalEquipmentFirm] / len(
            self.capital_equipment_firms
        ) if self.capital_equipment_firms else 0
        for firm in self.capital_equipment_firms:
            firm.cash += subsidy
        subsidy = subs[CapitalEquipmentFirm] / len(
            self.capital_equipment_firms
        ) if self.capital_equipment_firms else 0
        for firm in self.consumer_good_firms:
            firm.cash += subsidy
        subsidy = subs[RawMaterialFirm] / len(
            self.raw_material_firms) if self.raw_material_firms else 0
        for firm in self.raw_material_firms:
            firm.cash += subsidy

        n_bankruptcies = 0
        for firm in self.firms:
            # bankrupt
            if firm.cash < 0:
                n_bankruptcies += 1
                self.close_firm(firm)

        self.stat('n_bankruptcies', n_bankruptcies)
        self.stat('n_firms', len(self.firms))

        mean_quality_of_life = sum(
            h.quality_of_life for h in self.households) / len(
                self.households) if self.households else 0
        self.ewma_stat('mean_quality_of_life',
                       mean_quality_of_life,
                       graph=True)

        mean_cash = sum(h.cash for h in self.households) / len(
            self.households) if self.households else 0
        self.ewma_stat('mean_cash', mean_cash, graph=True)

        self.government.adjust(self.households)
        self.stat('welfare', self.government.welfare)
        self.stat('tax_rate', self.government.tax_rate)

        for person in self.people:
            person._state['cash'] += self.government.welfare
            self.government.cash -= self.government.welfare