def __init__(self, n_households): self.n_households = n_households super().__init__() # Chose a schedule self.schedule = RandomActivation(self) self.production = 10 self.kapital_households = 0 # To change in a list of the sum self.kapital_households_speculators = 0 # # To change in a list of the sum self.sum_loans_households = self.n_households * loan_households self.travail = 0 self.alpha = 0 self.beta = 0 # Create a bank, a firm and n household # self.bank = Bank(1, self) # self.schedule.add(bank) # firm = Firm(2, self) # self.schedule.add(firm) x = risk_lovers_rate * self.n_households for i in range(self.n_households): if i <= x: h = Household(i + 2, 1, self) self.schedule.add(h) else: hp = Household(i + 2, -1, self) self.schedule.add(hp)
def init_house(self, l_0, theta, gamma, phi, omega_p=None, f=None, r=None): """ Initialize a household object as instance of economy class. Refer to household class. :param l_0: baseline work offer, :param theta: preferency factors, :param gamma: aversion to work parameter, :param phi: Frisch index, :param omega_p: confidence parameter :param f: fraction of budget to save, :param r: savings growth rate. :return: Initializes household class with given parameters. """ self.house = Household(l_0, theta, gamma, phi, omega_p, f, r)
def _form_single_hh(self, t, ind): """ Move specified individual, with no partner, into their own household. :param t: the current time step. :type t: int :param i_id: the first partner in the couple. :type i_id: int :returns: the ID of the new household. """ assert not ind.partner # assert len(self.housemates(i_id)) > 0 # remove any guardians self._remove_from_guardians(t, ind, \ 'c-', "Lost dependent %d (leaving)" % ind.ID, ind.ID) # remove from old household self._remove_individual_from_hh(t, ind, 'l', "Individual left") # add to newly created household new_hh = self.add_group('household', [ind]) ind.with_parents = False self.households[new_hh] = Household(t) if self.logging: ind.add_log(t, 'l1', "Leaving household (single)") self.households[new_hh].add_log(t, 'f1', "Household formed", 1) return new_hh
def duplicate_household(self, t, hh_id): """ Create a duplicate of household hh_id, consisting of new individuals with same household age composition. Return id of newly created household. :param t: The current time step. :type t: int :param hh_id: The household to duplicate :type hh_id: int :returns the id of the newly created household. """ new_hh = [] for ind in self.groups['household'][hh_id]: new_ind = self.add_individual(ind.age, ind.sex, logging=self.logging) if self.logging: new_ind.add_log(t, 'i', "Individual (immigrated)") new_hh.append(new_ind) new_hh_id = self.add_group('household', new_hh) self.households[new_hh_id] = Household(t) self._init_household(new_hh_id) if self.logging: self.households[new_hh_id].add_log( t, 'i', "Household (immigrated)", len(self.groups['household'][new_hh_id])) return new_hh_id
def __init__(self, n_agents): """ Basic constructor with mostly default values Parameters n_agents : dict containing the number of each type of agents that we want our model to include """ # "Private parameters" # These parameters will be used to communicate to the agents that # a new day or a new month started #self.daypassed = False self.monthpassed = False # Attributes related to time self.start_datetime = datetime(2005, 1, 1, 0, 0, 0, tzinfo=None) self.current_datetime = self.start_datetime self.step_interval = "month" self.n_banks = n_agents['banks'] self.n_firms = n_agents['firms'] self.n_households = n_agents['households'] # Chose a scheduler self.scheduler = RandomActivation(self) # Create the required number of each agent for i in range(self.n_banks): a = Bank(i, self) a.liquidity = 1000 self.scheduler.add(a) for i in range(self.n_firms): a = Firm(i + self.n_banks, self) self.scheduler.add(a) for i in range(self.n_households): a = Household(i + self.n_banks + self.n_firms, self) self.scheduler.add(a) # If any deposits is to be given to banks it should be given now # Init all firms with their employees self.init_all_firms() # Create the data collector self.datacollector = DataCollector( model_reporters = {"Household liquidity": agent2_liquidity, "Household deposit": agent2_deposit, "Bank liquidity": agent0_liquidity, "Networth of household": agent2_netWorth, "Networth of bank": agent0_netWorth, "Firm net worth": agent1_netWorth}) self.running = True
def init_households(self): employer_idx = 0 for hh in range(self.hh_param.get("num_hh")): # first, hhs are distributed such that each firm has one employee # afterwards, hhs are randomly assigned to an employer # employers need to be informed who their employees are employer = self.firm_list[employer_idx] if employer_idx < len(self.firm_list) else random.choice(self.firm_list) new_household = Household(self, employer) employer.list_employees.append(new_household) self.hh_list.append(new_household) employer_idx += 1
def gen_hh_age_structured_pop(self, pop_size, hh_probs, age_probs_i, cutoffs, rng): """ Generate a population of individuals with age structure and household composition. Household composition here is approximated by the number of individuals who are: - pre-school age (0--4) - school age (5--17) - adult (18+) This is a bit ad hoc, but serves current purposes. :param pop_size: The size of the population to be generated. :type pop_size: int :param hh_probs: A table of household size probabilities. :type hh_probs: list :param age_probs_i: A table of age probabilities. :type age_probs_i: list :param rng: The random number generator to use. :type rng: :class:`random.Random` """ age_probs = [[x, int(y[0])] for x, y in age_probs_i] split_probs = split_age_probs(age_probs, cutoffs) split_probs.reverse() i = 0 while i < pop_size: # get list of [adults, school age, preschool age] hh_type = [int(x) for x in sample_table(hh_probs, rng)] # hh_type = [int(x) for x in sample_uniform(hh_probs, rng)] cur_hh = [] for cur_hh_type, cur_prob in zip(hh_type, split_probs): for _ in itertools.repeat(None, cur_hh_type): sex = rng.randint(0, 1) cur_age = sample_table(cur_prob, rng) cur_ind = self.add_individual(cur_age, sex, adam=True, logging=self.logging) if self.logging: cur_ind.add_log(0, 'f', "Individual (bootstrap)") cur_hh.append(cur_ind) i += 1 hh_id = self.add_group('household', cur_hh) self.households[hh_id] = Household(0, adam=True) if self.logging: self.households[hh_id].add_log( 0, 'f', "Household (bootstrap)", len(self.groups['household'][hh_id]))
def _form_couple_hh(self, t, inds): """ Make specified single individuals into a couple and move them into a new household. Any dependents of either individual accompany them to the new household. :param t: the current time step. :type t: int :param i_ids: the individuals to move into a couple household. :type i_ids: list :returns: the ID of the new household. """ ind_a = inds[0] ind_b = inds[1] inds[0].with_parents = False inds[1].with_parents = False # move dependents along with guardians new_inds = list(inds) combined_deps = ind_a.deps + ind_b.deps ind_a.deps = combined_deps[:] ind_b.deps = combined_deps[:] new_inds.extend(combined_deps) # remove any guardians of new couple self._remove_from_guardians(t, inds[0], \ 'c-', "Lost dependent %d (leaving)" % inds[0].ID, inds[0].ID) self._remove_from_guardians(t, inds[1], \ 'c-', "Lost dependent %d (leaving)" % inds[1].ID, inds[1].ID) # remove individuals from prior households and create new household for ind in new_inds: self._remove_individual_from_hh(t, ind, 'l', "Individual left") hh_id = self.add_group('household', new_inds) self.households[hh_id] = Household(t) if self.logging: ind_a.add_log(t, 'l2', "Leaving household - couple with %d" % ind_b.ID) ind_b.add_log(t, 'l2', "Leaving household - couple with %d" % ind_a.ID) self.households[hh_id].add_log(t, 'f2', \ "Household formed (%d individuals)" % \ len(new_inds), len(new_inds)) return hh_id
def gen_single_hh_pop(self, hh_size, rng): """ Generate a dummy population consisting of a single household. """ cur_hh = [] for i in xrange(hh_size): sex = rng.randint(0, 1) cur_ind = self.add_individual(20, sex, adam=True, logging=self.logging) if self.logging: cur_ind.add_log(0, 'f', "Individual (bootstrap)") cur_hh.append(cur_ind) hh_id = self.add_group('household', cur_hh) self.households[hh_id] = Household(0, adam=True) if self.logging: self.households[hh_id].add_log( 0, 'f', "Household (bootstrap)", len(self.groups['household'][hh_id]))
def agents_update(self): ''' Update household(and person)'s demographic status; do everything except for marriage and child birth. ''' temp_hh_list = list() # Annual household status update for HID in self.hh_dict: temp_hh_list.append(Household.household_demographic_update(self.hh_dict[HID], self.current_year, self.model_parameters_dict)) # Reset the households dict self.hh_dict = dict() # Refresh hh_dict for h in temp_hh_list: self.hh_dict[h.HID] = h if h.is_exist == 0: # If the household does not exist... if h.is_dissolved_this_year == True: # ...and it becomes non-exist this year # Dissolve non-existing households self.dissolve_household(h.HID)
def setup_households(self): if self.adaptive: for i in range(self.init_households): new_household = Household(model=self, coords=self.random_coords(), energy=self.init_energy, move_threshold=random(), move_dist=randint(1, 5), farm_dist=randint(1, 20), fission_rate=uniform(1, 2), min_fertility=random()) new_household.claim_land() else: for i in range(self.init_households): new_household = Household(model=self, coords=self.random_coords(), energy=self.init_energy, move_threshold=(self.init_energy * self.move_rate), move_dist=randint(1, 5), farm_dist=self.swidden_radius, fission_rate=self.fission_energy, min_fertility=0.8) new_household.claim_land()
class Simulation(): def __init__(self, runParameters, firmParameters, householdParameters): self.runParameters = runParameters self.firmParameters = firmParameters self.householdParameters = householdParameters self.duration = runParameters['duration'] self.money = runParameters['money'] self.stock = runParameters['stock'] self.verbose = runParameters['verbose'] self.expectation = runParameters['expectation'] self.demandKnown = runParameters['demandKnown'] def equilibrium(self, money, householdParameters, firmParameters): Lmax = householdParameters['Lmax'] alpha = householdParameters['alpha'] beta = householdParameters['beta'] gamma = firmParameters['gamma'] zeta_0 = firmParameters['zeta_0'] L_star = beta / (alpha + beta) * Lmax p_star = L_star**(1 - gamma) S_star = L_star**gamma z_star = p_star * S_star**zeta_0 print( 'Equilibrium values are: p = {:.4f}, S = {:.4f}, L = {:.4f}, z = {:.4f}' .format(p_star, S_star, L_star, z_star)) return (p_star, L_star, S_star, z_star) def saveSimResults(self): self.firmSimResults = self.firmSimResults.append(self.firm.__dict__, ignore_index=True) self.householdSimResults = self.householdSimResults.append( self.household.__dict__, ignore_index=True) self.marketSimResults = self.marketSimResults.append( self.market.__dict__, ignore_index=True) def advanceAttributes(self): self.market.SM_t, self.market.LM_t = self.market.SM_tp1, self.market.LM_tp1 self.firm.LD_t, self.firm.SSP_t, self.firm.SS_t = self.firm.LD_tp1, self.firm.SSP_tp1, self.firm.SS_tp1 self.firm.p_t = self.firm.p_tp1 self.firm.z_t, self.firm.zeta_t = self.firm.z_tp1, self.firm.zeta_tp1 if self.stock: self.firm.stock_t = self.firm.stock_tp1 if self.money: self.firm.mF_t = self.firm.mF_tp1 self.household.LS_t, self.household.SD_t = self.household.LS_tp1, self.household.SD_tp1 if self.money: self.household.mH_t = self.household.mH_tp1 def Run(self): self.p_star, self.L_star, self.S_star, self.z_star = self.equilibrium( self.money, self.householdParameters, self.firmParameters) self.firm = Firm(self.money, self.firmParameters, self.p_star, self.S_star, self.L_star, self.z_star, self.expectation) self.household = Household(self.householdParameters, self.p_star, self.S_star, self.z_star, self.firm.zeta_0) self.market = Market(self.S_star, self.L_star) self.firmSimResults = pd.DataFrame() self.householdSimResults = pd.DataFrame() self.marketSimResults = pd.DataFrame() for t in range(self.duration): if self.verbose: print('\nstep ', str(t + 1)) #add time step as instance attribute self.market.step = t + 1 self.firm.step = t + 1 self.household.step = t + 1 #firms plan sugar production self.firm.decideProduction(self.verbose, self.money, self.market.SM_t, self.household.Lmax) #households decide labor supply self.household.decideLabor(self.verbose) #market decides labor supply self.market.laborTransaction(self.verbose, self.firm.LD_tp1, self.household.LS_tp1) #firms produce sugar self.firm.produce(self.verbose, self.market.LM_tp1) #households decide sugar consumption self.household.decideConsumption(self.verbose, self.money, self.market.LM_tp1, self.firm.p_tp1) #market decides demand for sugar self.market.stuffTransaction(self.verbose, self.firm.SS_tp1, self.household.SD_tp1) #update firm stock if self.stock: self.firm.updateStock(self.verbose, self.market.SM_tp1) #update firm ledgers if self.money: self.firm.updateLedger(self.verbose, self.market.SM_tp1, self.market.LM_tp1) #no labor curve updating first round if t == 0: self.market.LM_t = self.market.LM_tp1 #update sugar demand an labor supply function parameters if self.demandKnown: self.firm.updateExpectations(self.verbose, self.money, self.household.SD_t, self.household.SD_tp1, self.market.LM_tp1, self.market.LM_t, self.market.LM_tp1) else: self.firm.updateExpectations(self.verbose, self.money, self.market.SM_t, self.market.SM_tp1, self.market.LM_tp1, self.market.LM_t, self.market.LM_tp1) #update household ledgers if self.money: self.household.updateLedger(self.verbose, self.firm.p_tp1, self.market.SM_tp1, self.market.LM_tp1) #save step results self.saveSimResults() # update timed variables self.advanceAttributes() #print('step', t + 1, 'complete') print( 'Final simulation values are: p = {:.4f}, S = {:.4f}, L = {:.4f}'. format(self.firm.p_tp1, self.market.SM_t, self.market.LM_t)) return self.firmSimResults, self.householdSimResults, self.marketSimResults
class Economy: def __init__(self, n, d, netstring, directed, j0, a0, q, b): # Network initialization self.n = n self.j = create_net(netstring, directed, n, d) self.j0 = j0 self.j_a = None self.a0 = a0 a = np.multiply(np.random.uniform(0, 1, (n, n)), self.j) self.a = np.array([(1 - a0[i]) * a[i] / np.sum(a[i]) for i in range(n)]) self.a_a = None self.q = q self.zeta = 1 / (q + 1) self.b = b # Auxiliary network variables self.lamb = None self.a_a = None self.j_a = None self.lamb_a = None self.m_cal = None self.v = None self.kappa = None self.zeros_j_a = None # Firms and household sub-classes self.firms = None self.house = None # Equilibrium quantities self.p_eq = None self.g_eq = None self.mu_eq = None self.labour_eq = None self.cons_eq = None self.b_eq = None self.utility_eq = None def init_house(self, l_0, theta, gamma, phi, omega_p=None, f=None, r=None): """ Initialize a household object as instance of economy class. Refer to household class. :param l_0: baseline work offer, :param theta: preferency factors, :param gamma: aversion to work parameter, :param phi: Frisch index, :param omega_p: confidence parameter :param f: fraction of budget to save, :param r: savings growth rate. :return: Initializes household class with given parameters. """ self.house = Household(l_0, theta, gamma, phi, omega_p, f, r) def init_firms(self, z, sigma, alpha, alpha_p, beta, beta_p, omega): """ Initialize a firms object as instance of economy class. Refer to firms class. :param z: Productivity factors, :param sigma: Depreciation of stocks parameters, :param alpha: Log-elasticity of prices' growth rates against surplus, :param alpha_p: Log-elasticity of prices' growth rates against profits, :param beta: Log-elasticity of productions' growth rates against profits, :param beta_p: Log-elasticity of productions' growth rates against surplus, :param omega: Log-elasticity of wages' growth rates against labor-market tensions. :return: Initializes firms class with given parameters. """ self.firms = Firms(z, sigma, alpha, alpha_p, beta, beta_p, omega) # Setters for class instances def set_house(self, house): """ Sets a household object as instance of economy class. :param house: :return: """ self.house = house def set_firms(self, firms): """ Sets a firms object as instance of economy class. :param firms: :return: """ self.firms = firms # Update methods for firms and household def update_firms_z(self, z): self.firms.update_z(z) self.set_quantities() self.compute_eq() def update_firms_sigma(self, sigma): self.firms.update_sigma(sigma) def update_firms_alpha(self, alpha): self.firms.update_alpha(alpha) def update_firms_alpha_p(self, alpha_p): self.firms.update_alpha_p(alpha_p) def update_firms_beta(self, beta): self.firms.update_beta(beta) def update_firms_beta_p(self, beta_p): self.firms.update_beta_p(beta_p) def update_firms_w(self, omega): self.firms.update_w(omega) def update_house_labour(self, labour): self.house.update_labour(labour) self.compute_eq() def update_house_theta(self, theta): self.house.update_theta(theta) self.compute_eq() def update_house_gamma(self, gamma): self.house.update_gamma(gamma) self.compute_eq() def update_house_phi(self, phi): self.house.update_phi(phi) self.compute_eq() def update_house_w_p(self, omega_p): self.house.update_w_p(omega_p) def update_house_f(self, f): self.house.update_f(f) def update_house_r(self, r): self.house.update_r(r) # Setters for the networks and subsequent instances def set_j(self, j): """ Sets a particular input-output network. :param j: a n by n matrix. :return: side effect """ if j.shape != (self.n, self.n): raise ValueError('Input-output network must be of size (%d, %d)' % (self.n, self.n)) self.j = j self.set_quantities() self.compute_eq() def set_a(self, a): """ Sets a particular input-output network. :param a: a n by n matrix. :return: side effect """ if a.shape != (self.n, self.n): raise ValueError('Substitution network must be of size (%d, %d)' % (self.n, self.n)) self.a = a self.set_quantities() self.compute_eq() def set_quantities(self): """ Sets redundant economy quantities as class instances. :return: side effect """ if self.q == 0: self.lamb = self.j self.a_a = np.hstack((np.array([self.a0]).T, self.a)) self.j_a = np.hstack((np.array([self.j0]).T, self.j)) self.lamb_a = self.j_a self.m_cal = np.diag(self.firms.z) - self.lamb self.v = np.array(self.lamb_a[:, 0]) elif self.q == np.inf: self.lamb = self.a self.a_a = np.hstack((np.array([self.a0]).T, self.a)) self.j_a = np.hstack((np.array([self.j0]).T, self.j)) self.lamb_a = self.a_a self.m_cal = np.eye(self.n) - self.lamb self.v = np.array(self.lamb_a[:, 0]) else: self.lamb = np.multiply(np.power(self.a, self.q * self.zeta), np.power(self.j, self.zeta)) self.a_a = np.hstack((np.array([self.a0]).T, self.a)) self.j_a = np.hstack((np.array([self.j0]).T, self.j)) self.lamb_a = np.multiply(np.power(self.a_a, self.q * self.zeta), np.power(self.j_a, self.zeta)) self.m_cal = np.diag(np.power(self.firms.z, self.zeta)) - self.lamb self.v = np.array(self.lamb_a[:, 0]) self.mu_eq = np.power( np.power(self.house.gamma, 1. / self.house.phi) * np.sum(self.house.theta) * (1 - (1 - self.house.f) * (1 + self.house.r)) / (self.house.f * np.power(self.house.l_0, 1 + 1. / self.house.phi)), self.house.phi / (1 + self.house.phi)) self.kappa = self.house.theta / self.mu_eq self.zeros_j_a = self.j_a != 0 def get_eps_cal(self): """ Computes the smallest eigenvalue of the economy matrix :return: smallest eigenvalue """ return np.min(np.real(np.linalg.eigvals(self.m_cal))) def set_eps_cal(self, eps): """ Modifies firms instance to set smallest eigenvalue of economy matrix to given epsilon. :param eps: a real number, :return: side effect. """ min_eig = self.get_eps_cal() z_n = self.firms.z * np.power( 1 + (eps - min_eig) / np.power(self.firms.z, self.zeta), self.q + 1) sigma = self.firms.sigma alpha = self.firms.alpha alpha_p = self.firms.alpha_p beta = self.firms.beta beta_p = self.firms.beta_p omega = self.firms.omega self.init_firms(z_n, sigma, alpha, alpha_p, beta, beta_p, omega) self.set_quantities() self.compute_eq() def update_b(self, b): """ Sets return to scale parameter :param b: return to scale :return: side effect """ self.b = b self.compute_eq() def update_q(self, q): self.q = q self.zeta = 1 / (q + 1) self.set_quantities() self.compute_eq() def update_network(self, netstring, directed, d, n): self.j = create_net(netstring, directed, n, d) a = np.multiply(np.random.uniform(0, 1, (n, n)), self.j) self.a = np.array([(1 - self.a0[i]) * a[i] / np.sum(a[i]) for i in range(n)]) self.set_quantities() self.compute_eq() def update_a0(self, a0): self.a0 = a0 a = np.multiply(np.random.uniform(0, 1, (self.n, self.n)), self.j) self.a = np.array([(1 - self.a0[i]) * a[i] / np.sum(a[i]) for i in range(self.n)]) self.set_quantities() self.compute_eq() def update_j0(self, j0): self.j0 = j0 self.set_quantities() self.compute_eq() def production_function(self, q_available): """ CES production function. :param q_available: matrix of available labour and goods for production, :return: production levels of the firms. """ if self.q == 0: return np.power( np.nanmin(np.divide(q_available, self.j_a), axis=1), self.b) elif self.q == np.inf: return np.power( np.nanprod(np.power(np.divide(q_available, self.j_a), self.a_a), axis=1), self.b) else: return np.power( np.nansum(self.a_a * np.power(self.j_a, 1. / self.q) / np.power(q_available, 1. / self.q), axis=1), -self.b * self.q) def compute_eq(self): """ Computes the competitive equilibrium of the economy. We use least-squares to compute solutions of linear systems Ax=b for memory and computational efficiency. The non-linear equations for non-constant return to scale parameters are solved using generalized least-squares with initial guesses taken to be the solution of the b=1 linear equation. For a high number of firms, high heterogeneity of close to 0 epsilon, this function might can output erroneous results or errors. :return: side effect. """ if self.q == np.inf: h = np.sum( self.a_a * np.log(np.ma.masked_invalid(np.divide(self.j_a, self.a_a))), axis=1) v = lstsq(np.eye(self.n) - self.a.T, self.kappa, rcond=10e-7)[0] log_p = lstsq(np.eye(self.n) / self.b - self.a, -np.log(self.firms.z) / self.b + (1 - self.b) * np.log(v) / self.b + h, rcond=10e-7)[0] log_g = -np.log(self.firms.z) - log_p + np.log(v) self.p_eq, self.g_eq = np.exp(log_p), np.exp(log_g) else: if self.b != 1: if self.q == 0: init_guess_peq = lstsq(self.m_cal, self.v, rcond=10e-7)[0] init_guess_geq = lstsq(self.m_cal.T, np.divide(self.kappa, init_guess_peq), rcond=10e-7)[0] par = (self.firms.z, self.v, self.m_cal, self.b - 1, self.kappa) pert_peq = lstsq(self.m_cal, self.firms.z * init_guess_peq * np.log(init_guess_geq), rcond=10e-7)[0] pert_geq = lstsq( np.transpose(self.m_cal), -np.divide(self.kappa, np.power(init_guess_peq, 2)) * pert_peq + self.firms.z * init_guess_geq * np.log(init_guess_geq), rcond=10e-7)[0] pg = leastsq( lambda x: self.non_linear_eq_qzero(x, *par), np.array( np.concatenate( (init_guess_peq + (1 - self.b) * pert_peq, np.power( init_guess_geq + (1 - self.b) * (pert_geq - init_guess_geq * np.log(init_guess_geq)), 1 / self.b))).reshape(2 * self.n)))[0] # pylint: disable=unbalanced-tuple-unpacking self.p_eq, g = np.split(pg, 2) self.g_eq = np.power(g, self.b) else: # The numerical solving is done for variables u = p_eq ^ zeta and # w = z ^ (q * zeta) * u ^ q * g_eq ^ (zeta * (bq+1) / b) init_guess_u = lstsq(self.m_cal, self.v, rcond=None)[0] init_guess_w = lstsq(self.m_cal.T, np.divide(self.kappa, init_guess_u), rcond=None)[0] par = (np.power(self.firms.z, self.zeta), self.v, self.m_cal, self.q, (self.b - 1) / (self.b * self.q + 1), self.kappa) uw = leastsq( lambda x: self.non_linear_eq_qnonzero(x, *par), np.concatenate((init_guess_u, init_guess_w)), )[0] # pylint: disable=unbalanced-tuple-unpacking u, w = np.split(uw, 2) self.p_eq = np.power(u, 1. / self.zeta) self.g_eq = np.power( np.divide( w, np.power(self.firms.z, self.q * self.zeta) * np.power(u, self.q)), self.b / (self.zeta * (self.b * self.q + 1))) else: if self.q == 0: self.p_eq = lstsq(self.m_cal, self.v, rcond=10e-7)[0] self.g_eq = lstsq(self.m_cal.T, np.divide(self.kappa, self.p_eq), rcond=10e-7)[0] else: # The numerical solving is done for variables u = p_eq ^ zeta and # w = z ^ (q * zeta) * u ^ q * g_eq u = lstsq(self.m_cal, self.v, rcond=None)[0] self.p_eq = np.power(u, 1. / self.zeta) w = lstsq(self.m_cal.T, np.divide(self.kappa, u), rcond=None)[0] self.g_eq = np.divide( w, np.power(self.firms.z, self.q * self.zeta) * np.power(u, self.q)) self.labour_eq = np.power(self.mu_eq * self.house.f, 1. / self.house.phi) / self.house.v_phi self.cons_eq = self.kappa / self.p_eq self.b_eq = np.sum(self.house.theta) / self.mu_eq self.utility_eq = np.dot(self.house.theta, np.log( self.cons_eq)) - self.house.gamma * np.power( self.labour_eq / self.house.l_0, self.house.phi + 1) / (self.house.phi + 1) def save_eco(self, name): """ Saves the economy as multi-indexed data-frame in hdf format along with networks in npy format. :param name: name of file, """ first_index = np.concatenate( (np.repeat('Firms', 11), np.repeat('Household', 11))) second_index = np.concatenate(([ 'q', 'b', 'z', 'sigma', 'alpha', 'alpha_p', 'beta', 'beta_p', 'w', 'p_eq', 'g_eq' ], ['l', 'theta', 'gamma', 'phi'])) multi_index = [first_index, second_index] values = np.vstack(( self.q * np.ones(self.n), self.b * np.ones(self.n), self.firms.z, self.firms.sigma, self.firms.alpha * np.ones(self.n), self.firms.alpha_p * np.ones(self.n), self.firms.beta * np.ones(self.n), self.firms.beta_p * np.ones(self.n), self.firms.w * np.ones(self.n), self.p_eq, self.g_eq, self.house.l_0 * np.ones(self.n), self.house.theta, self.house.gamma * np.ones(self.n), self.house.phi * np.ones(self.n), )) df_eco = pd.DataFrame(values, index=multi_index, columns=[np.arange(1, self.n + 1)]) df_eco.to_hdf(name + '/eco.h5', key='df', mode='w') np.save(name + '/network.npy', self.j_a) if self.q != 0: np.save(name + '/sub_network.npy', self.a_a) # Fixed point equations for equilibrium computation @staticmethod def non_linear_eq_qnonzero(x, *p): """ Function used for computation of equilibrium with non constant return to scale and general CES production function. :param x: guess for equilibrium :param p: tuple z, z_zeta, v, m_cal, zeta, q, theta, theta_bar, power :return: function's value at x """ if len(x) % 2 != 0: raise ValueError("x must be of even length") # pylint: disable=unbalanced-tuple-unpacking u, w = np.split(x, 2) z_zeta, v, m_cal, q, exponent, kappa = p w_over_uq_p = np.power( np.divide(w, np.power(z_zeta, q) * np.power(u, q)), exponent) v1 = np.multiply(z_zeta, np.multiply(u, 1 - w_over_uq_p)) m1 = np.dot(m_cal, u) m2 = u * np.dot(m_cal.T, w) - w * m1 return np.concatenate((m1 - v1 - v, m2 + w * v - kappa)) @staticmethod def non_linear_eq_qzero(x, *par): """ Function used for computation of equilibrium with non constant return to scale and Leontieff production function. :param x: guess for equilibrium :param par: tuple z_zeta, v, m_cal, q power :return: function's value at x """ if len(x) % 2 != 0: raise ValueError('x must be of even length') # pylint: disable=unbalanced-tuple-unpacking p, g = np.split(x, 2) z, v, m_cal, exponent, kappa = par v1 = np.multiply(z, np.multiply(p, 1 - np.power(g, exponent))) m1 = np.dot(m_cal, p) m2 = g * m1 - p * np.dot(m_cal.T, g) return np.concatenate((m1 - v1 - v, m2 - g * v + kappa))
def __init__(self, db, model_table_name, model_table, hh_table_name, hh_table, pp_table_name, pp_table, land_table_name, land_table, business_sector_table_name, business_sector_table, policy_table_name, policy_table, stat_table_name, stat_table, start_year): ''' Initialize the society class; ''' # Set the start year and current time stamps self.start_year = start_year self.current_year = start_year # Create a dictionary to store model parameters, indexed by Variable_Name, and contents are Variable_Value self.model_parameters_dict = dict() # Fill in the model parameters dictionary from the model table (fetched from DB) for record in model_table: self.model_parameters_dict[record.Variable_Name] = record.Variable_Value # Get the variable lists for household, person, land, business sector, policy, and statistics classes self.hh_var_list = DataAccess.get_var_list(db, hh_table_name) self.pp_var_list = DataAccess.get_var_list(db, pp_table_name) self.land_var_list = DataAccess.get_var_list(db, land_table_name) self.business_sector_var_list = DataAccess.get_var_list(db, business_sector_table_name) self.policy_var_list = DataAccess.get_var_list(db, policy_table_name) self.stat_var_list = DataAccess.get_var_list(db, stat_table_name) # Initialize the land instances, and create a land dictionary to store all the land parcels # Note that the land parcels here do not necessarily belong to any household. i.e. land_parcel.HID could be "None". self.land_dict = dict() for land in land_table: land_parcel = Land(land, self.land_var_list, self.current_year) self.land_dict[land_parcel.ParcelID] = land_parcel # Indexed by ParcelID # Initialize the household instances (household capital property and land class instances are initialized at the initialization of household class); # And create a dictionary to store them, indexed by HID. self.hh_dict = dict() # Add household instances to hh_dict for hh in hh_table: hh_temp = Household(hh, self.hh_var_list, self.current_year, db, pp_table_name, pp_table, self.land_dict, self.model_parameters_dict) self.hh_dict[hh_temp.HID] = hh_temp # Indexed by HID # Initialize the business sector instances; # And create a dictionary to store them, indexed by sector name. self.business_sector_dict = dict() for sector in business_sector_table: sector_temp = BusinessSector(sector, self.business_sector_var_list) self.business_sector_dict[sector_temp.SectorName] = sector_temp # Indexed by SectorName # Initialize the policy program instances; # And create a dictionary to store them, indexed by policy program type. self.policy_dict = dict() for program in policy_table: program_temp = Policy(program, self.policy_var_list) self.policy_dict[program_temp.PolicyType] = program_temp # Indexed by PolicyType # Create a statistics dictionary; indexed by Variable Names.To be filled later in Statistics Class. self.stat_dict = dict() # Create some variables to record the confiscated (due to ownerlessness) money and land self.ownerless_land = list() self.ownerless_money = 0
def editHousehold(self, hhid, newhhid, householdname, dateofcollection): household = Household( self.pid, hhid ) household.setData( householdname, dateofcollection, newhhid ) return household
def Run(self): self.p_star, self.L_star, self.S_star, self.z_star = self.equilibrium( self.money, self.householdParameters, self.firmParameters) self.firm = Firm(self.money, self.firmParameters, self.p_star, self.S_star, self.L_star, self.z_star, self.expectation) self.household = Household(self.householdParameters, self.p_star, self.S_star, self.z_star, self.firm.zeta_0) self.market = Market(self.S_star, self.L_star) self.firmSimResults = pd.DataFrame() self.householdSimResults = pd.DataFrame() self.marketSimResults = pd.DataFrame() for t in range(self.duration): if self.verbose: print('\nstep ', str(t + 1)) #add time step as instance attribute self.market.step = t + 1 self.firm.step = t + 1 self.household.step = t + 1 #firms plan sugar production self.firm.decideProduction(self.verbose, self.money, self.market.SM_t, self.household.Lmax) #households decide labor supply self.household.decideLabor(self.verbose) #market decides labor supply self.market.laborTransaction(self.verbose, self.firm.LD_tp1, self.household.LS_tp1) #firms produce sugar self.firm.produce(self.verbose, self.market.LM_tp1) #households decide sugar consumption self.household.decideConsumption(self.verbose, self.money, self.market.LM_tp1, self.firm.p_tp1) #market decides demand for sugar self.market.stuffTransaction(self.verbose, self.firm.SS_tp1, self.household.SD_tp1) #update firm stock if self.stock: self.firm.updateStock(self.verbose, self.market.SM_tp1) #update firm ledgers if self.money: self.firm.updateLedger(self.verbose, self.market.SM_tp1, self.market.LM_tp1) #no labor curve updating first round if t == 0: self.market.LM_t = self.market.LM_tp1 #update sugar demand an labor supply function parameters if self.demandKnown: self.firm.updateExpectations(self.verbose, self.money, self.household.SD_t, self.household.SD_tp1, self.market.LM_tp1, self.market.LM_t, self.market.LM_tp1) else: self.firm.updateExpectations(self.verbose, self.money, self.market.SM_t, self.market.SM_tp1, self.market.LM_tp1, self.market.LM_t, self.market.LM_tp1) #update household ledgers if self.money: self.household.updateLedger(self.verbose, self.firm.p_tp1, self.market.SM_tp1, self.market.LM_tp1) #save step results self.saveSimResults() # update timed variables self.advanceAttributes() #print('step', t + 1, 'complete') print( 'Final simulation values are: p = {:.4f}, S = {:.4f}, L = {:.4f}'. format(self.firm.p_tp1, self.market.SM_t, self.market.LM_t)) return self.firmSimResults, self.householdSimResults, self.marketSimResults
def create_households(self): """Creates X number of households and adds them to list of households.""" for i, _ in enumerate(range(self.NEIGHBORHOOD_APARTMENTS), 1): household = Household(i) self.households.append(household)
def __init__(self, n_households, df3): self.n_households = n_households self.df3 = pd.read_excel(df3) super().__init__() # Chose a schedule self.schedule = RandomActivation(self) self.production = 0 self.kapital_households = [] self.kapital_households_speculators = [] self.kapital_global_btcModel = [] self.kapital_global = 7.5 * n_households self.kh_high = 0 self.kh_medium = 0 self.kh_low = 0 self.kh = 0 self.sum_speculator_portfolio = 0 self.sum_wages_households = 0 self.sum_consumption_households = 0 self.sum_loans_households = 0 self.travail = 1000 self.alpha = 0.5 self.beta = 0.5 self.techno = 1.3 # technology factor self.gamma = 0.67 # coefficient of production applie to salaries 0.67 self.n = 12 self.start_datetime = datetime(2017, 1, 1, tzinfo=None) self.current_datetime = self.start_datetime self.datacollector = DataCollector(model_reporters={ "Production": production, "KapitalG": evolution_kapital_global, "KapitalH": kapital_new, "Kapital_households_risk_averse": graph_households_risk_averse_kapital, "Kapital_households_speculator": graph_households_speculator_kapital, "WagesH": graph_households_wage, "sum_wage": increase_wages_households, "Conso": graph_households_conso, "KapitalF": graph_kapital_firm, "KapitalB": graph_kapital_bank, "diff": diff }, agent_reporters={"Wage": "wage"}) self.running = True # Create a bank, a firm and n household self.firm = Firm(2, self) self.bank = Bank(1, self) xh = risk_high_rate * self.n_households xm = xh + risk_medium_rate * self.n_households xl = xm + risk_low_rate * self.n_households for i in range(self.n_households): if i < xh: h = Household(i + 2, 2, P2, self) self.schedule.add(h) elif i >= xh and i < xm: h = Household(i + 2, 1, P1, self) self.schedule.add(h) elif i >= xm and i < xl: h = Household(i + 2, 0, P0, self) self.schedule.add(h) else: h = Household(i + 2, -1, 0, self) self.schedule.add(h) #Init production with kapital initialisation of agents and give loans production(self) self.bank.give_loan()