Exemple #1
0
def generate_name(sex, race):
    name = random_choice(name_given_sex[sex.name].items())
    race = race_map[race.name]
    if isinstance(race, list):
        race = random.choice(race)
    surname = random_choice(surname_given_race[race].items())
    return '{} {}'.format(name, surname).title()
Exemple #2
0
def generate_name(sex, race):
    name = random_choice(name_given_sex[sex.name].items())
    race = race_map[race.name]
    if isinstance(race, list):
        race = random.choice(race)
    surname = random_choice(surname_given_race[race].items())
    return '{} {}'.format(name, surname).title()
Exemple #3
0
    def start_business(self, world, buildings):
        # can only have one business
        if self._state['firm_owner']:
            return False, None, None

        # must be able to find a place with affordable rent
        buildings = [b for b in buildings if b.available_space]
        if not buildings:
            return False, None, None

        denom = sum(1/b.rent for b in buildings)
        building = random_choice([(b, 1/(b.rent*denom)) for b in buildings])

        # must be able to hire at least one employee
        min_cost = self.min_business_capital + building.rent + world['mean_wage']

        if self._state['cash'] < min_cost:
            return False, None, None

        industries = ['equip', 'material', 'consumer_good', 'healthcare']
        total_mean_profit = sum(world['mean_{}_profit'.format(name)] for name in industries)
        industry_dist = [(name, world['mean_{}_profit'.format(name)]/total_mean_profit) for name in industries]
        industry = random_choice(industry_dist)

        # choose an industry (based on highest EWMA profit)
        self.twoot('i\'m starting a BUSINESS in {}!'.format(industry), world)

        logger.info('person:{}'.format(json.dumps({
            'event': 'started_firm',
            'id': self.id
        })))
        return True, industry, building
Exemple #4
0
    def hire(self, applicants, wage, world):
        hired = []
        while self.worker_change > 0 and applicants:
            # based on employment prob
            apps = []
            for a in applicants:
                ref = 'friend' if set(a.friends).intersection(self.workers) else 'ad_or_cold_call'
                p = offer_prob(world['year'], world['month'], a.sex, a.race, ref, precomputed_emp_dist=emp_dist)
                apps.append((a, p))
            apps_mass = sum(p for a, p in apps)
            apps = [(a, pr/apps_mass) for a, pr in apps]

            worker = random_choice(apps)
            if worker.employer is not None:
                worker.employer.fire(worker)
            worker.wage = wage
            worker.employer = self
            applicants.remove(worker)
            self.workers.append(worker)
            hired.append(worker)
            logger.info('person:{}'.format(json.dumps({
                'event': 'hired',
                'id': worker.id
            })))
            self.worker_change -= 1

        # increase wage to attract more employees
        if self.worker_change > 0:
            wage += self.config['wage_increment'] * (1.1+self.owner.altruism)
        return hired, self.worker_change, wage
Exemple #5
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
Exemple #6
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
Exemple #7
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
Exemple #8
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
Exemple #9
0
    def set_production_target(self, world):
        """firm decides on how much supply they want to produce this step,
        and what they need to do to accomplish that"""

        # assess previous day's results
        self.prev_profit = self.profit
        self.leftover = self.supply

        # adjust production
        action = self.learner.choose_action(self.current_state)
        action = self.actions[action]
        self.desired_supply = max(1, self.desired_supply + action.get('supply', 0))
        self.profit_margin += action.get('profit_margin', 0)

        # supply expires every day
        self.supply = 0

        # unused materials expire every day
        self.materials = 0

        # resets every day
        self.n_sold = 0
        self.revenue = 0
        self.costs = 0

        # fire workers that are being paid too much
        for worker in self.workers:
            if worker.wage >= world['mean_wage'] + (self.config['extravagant_wage_range'] * (1.1+self.owner.altruism)):
                self.fire(worker)

        # figure out labor goal
        required_labor = self.desired_supply * self.config['labor_cost_per_good']
        n_workers, wage, n_equip = self.assess_assets(required_labor, world['mean_wage'], world['mean_equip_price'])

        # sometimes optimization function returns a huge negative value for
        # workers, need to look into that further
        if n_workers < 0:
            n_workers = 0

        self.worker_change = n_workers - len(self.workers)
        self.desired_equipment = self.equipment + max(0, n_equip - self.equipment)

        # fire workers if necessary
        while self.worker_change < 0:
            # weighted random choice by unemployment prob
            ws = []
            for w in self.workers:
                pu = emp_dist[world['year']][world['month'] - 1][w.race.name][w.sex.name]
                ws.append((w, pu['unemployed']))
            ws_mass = sum(p for w, p in ws)
            ws = [(w, p/ws_mass) for w, p in ws]
            worker = random_choice(ws)
            self.fire(worker)
            self.worker_change += 1

        # job vacancies
        return self.worker_change, wage
Exemple #10
0
def sample_rent(year, puma):
    """generates a plausible rent amount (here, rent can mean a monthly mortgage payment)
    given a year and a PUMA"""
    rent = 0
    rent_info = rent_dists[year][puma]
    if random.random() < rent_info['p_owned']:
        ownership = random_choice(rent_info['p_ownership'].items())
        if ownership == 'free':
            rent = 0
        elif ownership == 'mortgage1':
            rent = rent_info['mortgage1_dist'].resample(1)[0][0]
        elif ownership == 'mortgage2':
            try:
                rent += rent_info['mortgage2_dist'].resample(1)[0][0]
            except AttributeError:
                rent += rent_info['mortgage2_dist']
    else:
        rent = rent_info['rent_dist'].resample(1)[0][0]
    return rent
Exemple #11
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
Exemple #12
0
    def sample_node(self, n, sampled):
        """sample an individual node,
        samples from parents as necessary"""
        parents = self.g.predecessors(n)

        if not parents:
            # if no parents, use p(n)
            try:
                prob_dist = self._cache[n.name]['_']
            except KeyError:
                prob_dist = self.p_n(n)
        else:
            # if parents, use prod(p(n|x_i) for x_i in parents)
            for parent in parents:
                if parent not in sampled:
                    sampled = self.sample_node(parent, sampled)
            given = {k: v for k, v in sampled.items() if k in parents}
            prob_dist = self.probs_given(n, given=given)
        sampled[n] = random_choice(prob_dist.items())
        return sampled
Exemple #13
0
    def sample_node(self, n, sampled):
        """sample an individual node,
        samples from parents as necessary"""
        parents = self.g.predecessors(n)

        if not parents:
            # if no parents, use p(n)
            try:
                prob_dist = self._cache[n.name]['_']
            except KeyError:
                prob_dist = self.p_n(n)
        else:
            # if parents, use prod(p(n|x_i) for x_i in parents)
            for parent in parents:
                if parent not in sampled:
                    sampled = self.sample_node(parent, sampled)
            given = {k:v for k,v in sampled.items() if k in parents}
            prob_dist = self.probs_given(n, given=given)
        sampled[n] = random_choice(prob_dist.items())
        return sampled
Exemple #14
0
    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
Exemple #15
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
Exemple #16
0
    def hire(self, applicants, wage, world):
        hired = []
        while self.worker_change > 0 and applicants:
            # based on employment prob
            apps = []
            for a in applicants:
                ref = 'friend' if set(a.friends).intersection(
                    self.workers) else 'ad_or_cold_call'
                p = offer_prob(world['year'],
                               world['month'],
                               a.sex,
                               a.race,
                               ref,
                               precomputed_emp_dist=emp_dist)
                apps.append((a, p))
            apps_mass = sum(p for a, p in apps)
            apps = [(a, pr / apps_mass) for a, pr in apps]

            worker = random_choice(apps)
            if worker.employer is not None:
                worker.employer.fire(worker)
            worker.wage = wage
            worker.employer = self
            applicants.remove(worker)
            self.workers.append(worker)
            hired.append(worker)
            logger.info('person:{}'.format(
                json.dumps({
                    'event': 'hired',
                    'id': worker.id
                })))
            self.worker_change -= 1

        # increase wage to attract more employees
        if self.worker_change > 0:
            wage += self.config['wage_increment'] * (1.1 + self.owner.altruism)
        return hired, self.worker_change, wage
Exemple #17
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
Exemple #18
0
    def set_production_target(self, world):
        """firm decides on how much supply they want to produce this step,
        and what they need to do to accomplish that"""

        # assess previous day's results
        self.prev_profit = self.profit
        self.leftover = self.supply

        # adjust production
        action = self.learner.choose_action(self.current_state)
        action = self.actions[action]
        self.desired_supply = max(
            1, self.desired_supply + action.get('supply', 0))
        self.profit_margin += action.get('profit_margin', 0)

        # supply expires every day
        self.supply = 0

        # unused materials expire every day
        self.materials = 0

        # resets every day
        self.n_sold = 0
        self.revenue = 0
        self.costs = 0

        # fire workers that are being paid too much
        for worker in self.workers:
            if worker.wage >= world['mean_wage'] + (
                    self.config['extravagant_wage_range'] *
                (1.1 + self.owner.altruism)):
                self.fire(worker)

        # figure out labor goal
        required_labor = self.desired_supply * self.config[
            'labor_cost_per_good']
        n_workers, wage, n_equip = self.assess_assets(
            required_labor, world['mean_wage'], world['mean_equip_price'])

        # sometimes optimization function returns a huge negative value for
        # workers, need to look into that further
        if n_workers < 0:
            n_workers = 0

        self.worker_change = n_workers - len(self.workers)
        self.desired_equipment = self.equipment + max(0,
                                                      n_equip - self.equipment)

        # fire workers if necessary
        while self.worker_change < 0:
            # weighted random choice by unemployment prob
            ws = []
            for w in self.workers:
                pu = emp_dist[world['year']][world['month'] -
                                             1][w.race.name][w.sex.name]
                ws.append((w, pu['unemployed']))
            ws_mass = sum(p for w, p in ws)
            ws = [(w, p / ws_mass) for w, p in ws]
            worker = random_choice(ws)
            self.fire(worker)
            self.worker_change += 1

        # job vacancies
        return self.worker_change, wage