def retired(sol, z_plus, p, t, par): # Prepare w = np.ones((par.Na)) a = par.grid_a[t, :] p = np.tile(p, par.Na) # Next period states p_plus = p m_plus = par.R * a + par.kappa * p_plus # value w_raw = tools.interp_2d_vec(par.grid_m, par.grid_p, sol.v[t + 1, z_plus], m_plus, p_plus) # Consumption c_plus = tools.interp_2d_vec(par.grid_m, par.grid_p, sol.c[t + 1, z_plus], m_plus, p_plus) #Marginal utility marg_u_plus = marg_util(c_plus, par) #Expected average marginal utility avg_marg_u_plus = marg_u_plus * w return w_raw, avg_marg_u_plus
def value_of_choice(c, t, m, h, z, par, sol): # End-of-period assets a = m - c # Calculate inverse value-of-choice in next period still_working_next_period = t + 1 <= par.TR - 1 if still_working_next_period: fac_vec = par.G[t] * par.psi_vec w = par.w xi = par.xi_vec if t + 1 < par.TH - 1: h_plus_vec = np.repeat(0.0, len(fac_vec)) elif t + 1 == par.TH - 1: #h_plus_vec = np.repeat(0.0, len(fac)) h_plus_vec = np.repeat(par.alpha, len(fac_vec)) elif t + 1 > par.TH - 1 and z == 0: h_plus_vec = np.repeat( ((par.d_vec + par.delta - 1) / fac_vec) * h, len(fac_vec)) elif t + 1 > par.TH - 1 and z == 1: h_plus_vec = np.repeat(0.0, len(fac_vec)) if t + 1 == par.TH and z == 1: h_term_vec = ((par.d_vec + par.delta - 1) / fac_vec) * h else: h_term_vec = np.repeat(0.0, len(fac_vec)) m_plus_vec = (par.R / fac_vec) * a + xi + h_term_vec inv_v_plus_vec = tools.interp_2d_vec(par.grid_m, par.grid_h, sol.inv_v[t + 1, :, z, :], m_plus_vec, h_plus_vec) else: fac = par.G[t] if t + 1 == par.TR and z == 0: h_term = (par.delta / fac) * h else: h_term = 0.0 m_plus = (par.R / fac) * a + 1 + h_term inv_v_plus = tools.interp_2d(par.grid_m, par.grid_h, sol.inv_v[t + 1, :, z, :], m_plus, 0.0) # Value-of-choice if still_working_next_period: v_plus_vec = 1 / inv_v_plus_vec total = utility(c, par.rho) + par.beta * np.sum( w * fac_vec**(1 - par.rho) * v_plus_vec) else: v_plus = 1 / inv_v_plus total = utility(c, par.rho) + par.beta * fac**(1 - par.rho) * v_plus return -total
def working(sol, z_plus, p, t, par): # Prepare xi = np.tile(par.xi, par.Na) p = np.tile(p, par.Na * par.Nxi) a = np.repeat(par.grid_a[t], par.Nxi) w = np.tile(par.xi_w, (par.Na, 1)) # Next period states p_plus = xi * p m_plus = par.R * a + par.W * p_plus # Value, consumption, marg_util shape = (2, m_plus.size) v_plus = np.nan + np.zeros(shape) c_plus = np.nan + np.zeros(shape) marg_u_plus = np.nan + np.zeros(shape) for i in range(2): #Range over working and not working next period # Choice specific value v_plus[i, :] = tools.interp_2d_vec(par.grid_m, par.grid_p, sol.v[t + 1, i], m_plus, p_plus) # Choice specific consumption c_plus[i, :] = tools.interp_2d_vec(par.grid_m, par.grid_p, sol.c[t + 1, i], m_plus, p_plus) # Choice specific Marginal utility marg_u_plus[i, :] = marg_util(c_plus[i, :], par) # Expected value V_plus, prob = logsum(v_plus[0], v_plus[1], par.sigma_eta) w_raw = w * np.reshape(V_plus, (par.Na, par.Nxi)) w_raw = np.sum(w_raw, 1) marg_u_plus = prob[0, :] * marg_u_plus[0] + prob[1, :] * marg_u_plus[1] #Expected average marg. utility avg_marg_u_plus = w * np.reshape(marg_u_plus, (par.Na, par.Nxi)) avg_marg_u_plus = np.sum(avg_marg_u_plus, 1) return w_raw, avg_marg_u_plus
def calculate_euler_errors(sol,sim,par,grid_m): def marg_utility(c, rho): return c**(-rho) euler_residual = np.nan + np.zeros((par.simN,par.T-1)) euler_residual_cons = np.nan + np.zeros((par.simN,par.T-1)) a = np.nan + np.zeros((par.simN,par.T-1)) for t in range(par.T-1): for i in range(par.simN): # Initialize m = sim.m[i,t] c = sim.c[i,t] a[i,t] = m-c h = sim.h[i,t] if t < par.TH-1: z = 0 else: z = sim.z[i] still_working_next_period = t+1 <= par.TR-1 if still_working_next_period: fac_vec = par.G[t]*par.psi_vec w = par.w xi = par.xi_vec if t+1 < par.TH-1: h_plus_vec = np.repeat(0.0, len(fac_vec)) elif t+1 == par.TH-1: h_plus_vec = np.repeat(par.alpha, len(fac_vec)) elif t+1 > par.TH-1 and z == 0: h_plus_vec = np.repeat(((par.d_vec+par.delta-1)/fac_vec)*h, len(fac_vec)) elif t+1 > par.TH-1 and z == 1: h_plus_vec = np.repeat(0.0, len(fac_vec)) if t+1 == par.TH and z == 1: h_term_vec = ((par.d_vec+par.delta-1)/fac_vec)*h else: h_term_vec = np.repeat(0.0,len(fac_vec)) m_plus_vec = (par.R/fac_vec)*a[i,t] + xi + h_term_vec # Future c c_plus_vec = tools.interp_2d_vec(grid_m, par.grid_h, sol.c[t+1,:,z,:], m_plus_vec, h_plus_vec) # Average future marginal utility marg_u_plus_vec = marg_utility(fac_vec*c_plus_vec,par.rho) avg_marg_u_plus_vec = np.sum(w*marg_u_plus_vec) euler_residual[i,t] = marg_utility(c,par.rho)-par.beta*par.R*avg_marg_u_plus_vec euler_residual_cons[i,t] = c - (par.beta*par.R*avg_marg_u_plus_vec)**(-1/par.rho) else: fac = par.G[t] if t+1 == par.TR and z == 0: h_term = (par.delta/fac)*h else: h_term = 0.0 m_plus = (par.R/fac)*a[i,t] + 1 + h_term # Future c c_plus = tools.interp_2d(grid_m, par.grid_h, sol.c[t+1,:,z,:], m_plus, 0.0) # Average future marginal utility marg_u_plus = marg_utility(fac*c_plus,par.rho) avg_marg_u_plus = marg_u_plus euler_residual[i,t] = marg_utility(c,par.rho)-par.beta*par.R*avg_marg_u_plus euler_residual_cons[i,t] = c - (par.beta*par.R*avg_marg_u_plus)**(-1/par.rho) # 4. Calculate the average absolute euler residual I = (a>0) # Define an indicator for a bigger than 0 (m>c) eulers_indexed = euler_residual.flatten()[I.flatten()] euler_error = np.mean(np.abs(eulers_indexed)) c = (sim.c[:,0:par.T-1]) # The euler error is not defined in last period eulers_indexed_cons = euler_residual_cons.flatten()[I.flatten()] nom_euler_error = np.log10(np.abs(eulers_indexed_cons)/(c.flatten()[I.flatten()])) nom_euler_error = np.mean(nom_euler_error) return euler_error, nom_euler_error
def EGM(sol, h, k, t, par): # Prepare epsi = np.tile(par.epsi, par.Na) k = np.tile(k, par.Na * par.Nw) a = np.repeat(par.grid_a[t], par.Nw) w = np.tile(par.epsi_w, (par.Na, 1)) # Next period states k_plus = k + par.phi1 * pow(par.hlist[h], par.phi2) # Income/transfers wage = par.kappa * k * epsi S_plus = par.rho * k_plus if t < par.To: m_plus = (1 + par.r) * a + par.hlist[h] * wage if t >= par.Tp: if h == 0: m_plus = (1 + par.r) * a + par.P + S_plus else: m_plus = (1 + par.r) * a + par.hlist[h] * wage + S_plus else: m_plus = (1 + par.r) * a + par.hlist[h] * wage + S_plus # Value, consumption, marg_util shape = (3, m_plus.size) v_plus = np.nan + np.zeros(shape) c_plus = np.nan + np.zeros(shape) marg_u_plus = np.nan + np.zeros(shape) for i in range( 3 ): #Range over working full-time, part-time and not working next period # Choice specific value v_plus[i, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.v[t + 1, i], m_plus, k_plus) # Choice specific consumption c_plus[i, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.c[t + 1, i], m_plus, k_plus) # Choice specific Marginal utility marg_u_plus[i, :] = marg_u(c_plus[i, :], par) # Expected value V_plus, prob = logsum(v_plus[0], v_plus[1], v_plus[2], par.sigma_epsilon) w_raw = w * np.reshape(V_plus, (par.Na, par.Nw)) w_raw = np.sum(w_raw, 1) marg_u_plus = prob[0, :] * marg_u_plus[0] + prob[ 1, :] * marg_u_plus[1] + prob[2, :] * marg_u_plus[2] #Expected average marg. utility avg_marg_u_plus = w * np.reshape(marg_u_plus, (par.Na, par.Nw)) avg_marg_u_plus = np.sum(avg_marg_u_plus, 1) # raw c, m and v c_raw = inv_marg_util(par.beta * (1 + par.r) * avg_marg_u_plus, par) m_raw = c_raw + par.grid_a[t, :] # Upper Envelope c, v = upper_envelope(t, h, c_raw, m_raw, w_raw, par) return c, v
def simulate(self): par = self.par sol = self.sol sim = self.sim # Initialize shape = (par.simT, par.simN) sim.m = np.nan + np.zeros(shape) sim.k = np.nan + np.zeros(shape) sim.c = np.nan + np.zeros(shape) sim.h = np.nan + np.zeros(shape) sim.a = np.nan + np.zeros(shape) sim.s = np.zeros(shape) sim.p = np.zeros(shape) sim.wage = np.nan + np.zeros(shape) sim.disp = np.nan + np.zeros(shape) # Shocks used par.eps_w = np.random.lognormal(0, par.sigma_w, shape) par.eps_ts = np.random.rand(par.simT, par.simN) # Initial values sim.m[0, :] = par.m_start sim.k[0, :] = par.k_start shape_inter = (3, par.simN) v_interp = np.nan + np.zeros(shape_inter) c_interp = np.nan + np.zeros(shape_inter) for t in range(par.simT): #for i in range(3): #Range over working full-time, part-time and not working next period [t,:] # Choice specific value v_interp[0, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.v[t, 0], sim.m[t, :], sim.k[t, :]) v_interp[1, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.v[t, 1], sim.m[t, :], sim.k[t, :]) v_interp[2, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.v[t, 2], sim.m[t, :], sim.k[t, :]) # Choice specific consumption c_interp[0, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.c[t, 0], sim.m[t, :], sim.k[t, :]) c_interp[1, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.c[t, 1], sim.m[t, :], sim.k[t, :]) c_interp[2, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.c[t, 2], sim.m[t, :], sim.k[t, :]) # Probabilities _, prob = egm.logsum(v_interp[0], v_interp[1], v_interp[2], par.sigma_epsilon) sim.prob = prob # Chooce h and the corresponding consumption policy function for n in range(par.simN): if par.eps_ts[t, n] <= prob[2, n]: sim.h[t, n] = 1 sim.c[t, n] = c_interp[2, n] elif par.eps_ts[t, n] <= prob[2, n] + prob[ 1, n] and par.eps_ts[t, n] > prob[2, n]: sim.h[t, n] = 0.5 sim.c[t, n] = c_interp[1, n] else: sim.h[t, n] = 0 sim.c[t, n] = c_interp[0, n] if t >= par.Tp: sim.p[t, n] = par.P sim.s[t, n] = par.rho * sim.k[t, n] elif t < par.To: sim.p[t, n] = 0 sim.s[t, n] = 0 else: sim.p[t, n] = 0 sim.s[t, n] = par.rho * sim.k[t, n] # Calculate wages, savings, total income and next period states (human capital and assets) sim.wage[t, :] = par.kappa * sim.k[t, :] * par.eps_w[t, :] sim.a[t, :] = sim.m[t, :] - sim.c[t, :] sim.disp[t, :] = sim.h[t, :] * sim.wage[t, :] + sim.s[ t, :] + sim.p[t, :] if t < par.T - 1: sim.k[t + 1, :] = (1 - par.delta) * sim.k[ t, :] + par.phi1 * sim.h[t, :]**par.phi2 sim.m[t + 1, :] = (1 + par.r) * sim.a[t, :] + sim.h[ t, :] * sim.wage[t, :] + sim.s[t, :] + sim.p[t, :]
def solve_egm(par,sol,sim): # Last period (= consume all) for z in [0, 1]: for i_h in range(par.Nh): sol.m[-1,:,z,i_h] = np.linspace(0,par.a_max,par.Na+1) sol.c[-1,:,z,i_h] = sol.m[-1,:,z,i_h] sol.inv_v[-1,0,z,i_h] = 0.0 sol.inv_v[-1,1:,z,i_h] = 1.0/utility(sol.c[-1,1:,z,i_h],par.rho) # Before last period for t in range(par.T-2,-1,-1): for i_h, h in enumerate(par.grid_h): # i. solve by EGM # loop over end-of-period assets for i_a in range(1,par.Na+1): a = par.grid_a[i_a-1] still_working_next_period = t+1 <= par.TR-1 # a. prep if still_working_next_period: fac_vec = par.G[t]*par.psi_vec w = par.w xi = par.xi_vec if t+1 < par.TH-1: h_plus_vec = np.repeat(0.0, len(fac_vec)) elif t+1 == par.TH-1: h_plus_vec = np.repeat(par.alpha, len(fac_vec)) elif t+1 > par.TH-1 and z == 0: h_plus_vec = np.repeat(((par.d_vec+par.delta-1)/fac_vec)*h, len(fac_vec)) elif t+1 > par.TH-1 and z == 1: h_plus_vec = np.repeat(0.0, len(fac_vec)) if t+1 == par.TH and z == 1: h_term_vec = ((par.d_vec+par.delta-1)/fac_vec)*h else: h_term_vec = np.repeat(0.0,len(fac_vec)) m_plus_vec = (par.R/fac_vec)*a + xi + h_term_vec inv_v_plus_vec = tools.interp_2d_vec(sol.m[t+1,:,z,i_h], par.grid_h, sol.inv_v[t+1,:,z,:], m_plus_vec, h_plus_vec) # b. future m and c c_plus_vec = tools.interp_2d_vec(sol.m[t+1,:,z,i_h], par.grid_h, sol.c[t+1,:,z,:], m_plus_vec, h_plus_vec) v_plus_vec = 1.0/inv_v_plus_vec # c. average future marginal utility marg_u_plus_vec = marg_utility(fac_vec*c_plus_vec,par.rho) avg_marg_u_plus_vec = np.sum(w*marg_u_plus_vec) avg_v_plus_vec = np.sum(w*(fac_vec**(1-par.rho))*v_plus_vec) # d. current c sol.c[t,i_a,z,i_h] = inv_marg_utility(par.beta*par.R*avg_marg_u_plus_vec,par.rho) # e. current m sol.m[t,i_a,z,i_h] = a + sol.c[t,i_a,z,i_h] # f. current v if sol.c[t,i_a,z,i_h] > 0: sol.inv_v[t,i_a,z,i_h] = 1.0/(utility(sol.c[t,i_a,z,i_h],par.rho) + par.beta*avg_v_plus_vec) else: sol.inv_v[t,i_a,z,i_h] = 0 else: fac = par.G[t] if t+1 == par.TR and z == 0: h_term = (par.delta/fac)*h else: h_term = 0.0 m_plus = (par.R/fac)*a + 1 + h_term inv_v_plus = tools.interp_2d(sol.m[t+1,:,z,i_h], par.grid_h, sol.inv_v[t+1,:,z,:], m_plus, 0.0) # b. future m and c c_plus = tools.interp_2d(sol.m[t+1,:,z,i_h], par.grid_h, sol.c[t+1,:,z,:], m_plus, 0.0) v_plus = 1.0/inv_v_plus # c. average future marginal utility marg_u_plus = marg_utility(fac*c_plus,par.rho) avg_marg_u_plus = marg_u_plus avg_v_plus = (fac**(1-par.rho))*v_plus # d. current c sol.c[t,i_a,z,i_h] = inv_marg_utility(par.beta*par.R*avg_marg_u_plus,par.rho) # e. current m sol.m[t,i_a,z,i_h] = a + sol.c[t,i_a,z,i_h] # f. current v if sol.c[t,i_a,z,i_h] > 0: sol.inv_v[t,i_a,z,i_h] = 1.0/(utility(sol.c[t,i_a,z,i_h],par.rho) + par.beta*avg_v_plus) else: sol.inv_v[t,i_a,z,i_h] = 0 # ii. add zero consumption sol.m[t,0,z,i_h] = 0.0 sol.c[t,0,z,i_h] = 0.0 sol.inv_v[t,0,z,i_h] = 0.0
def simulate2(self): par = self.par sol = self.sol sim = self.sim # Initialize shape = (par.simT, par.simN) sim.m = np.nan + np.zeros(shape) sim.k = np.nan + np.zeros(shape) sim.c = np.nan + np.zeros(shape) sim.h = np.nan + np.zeros(shape) sim.a = np.nan + np.zeros(shape) sim.s = np.nan + np.zeros(shape) sim.p = np.nan + np.zeros(shape) sim.wage = np.nan + np.zeros(shape) # Shocks used par.eps_w = np.random.lognormal(0, par.sigma_w, shape) par.eps_ts = np.random.rand(par.simT, par.simN) # Initial values sim.m[0, :] = par.m_start sim.k[0, :] = par.k_start shape_inter = (3, par.simN) v_interp = np.nan + np.zeros(shape_inter) c_interp = np.nan + np.zeros(shape_inter) for t in range(par.simT): #for i in range(3): #Range over working full-time, part-time and not working next period [t,:] # Choice specific value v_interp[0, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.v[t, 0], sim.m[t, :], sim.k[t, :]) v_interp[1, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.v[t, 1], sim.m[t, :], sim.k[t, :]) v_interp[2, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.v[t, 2], sim.m[t, :], sim.k[t, :]) # Choice specific consumption c_interp[0, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.c[t, 0], sim.m[t, :], sim.k[t, :]) c_interp[1, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.c[t, 1], sim.m[t, :], sim.k[t, :]) c_interp[2, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.c[t, 2], sim.m[t, :], sim.k[t, :]) # Probabilities _, prob = egm.logsum(v_interp[0], v_interp[1], v_interp[2], par.sigma_epsilon) if par.eps_ts[t, :] <= prob[2, :]: F = 1 if par.eps_ts[t, :] <= prob[2, :] + prob[1, :]: E = 1 if E == 1 and F != 1: P = 1 if E != 1: NW = 1 sim.c[t, F] = c_interp[2, :] sim.c[t, P] = c_interp[1, :] sim.c[t, NW] = c_interp[0, :] sim.h[t, F] = 1 sim.h[t, P] = 0.5 sim.h[t, NW] = 0 sim.wage[t, :] = par.kappa * sim.k[t, :] * par.eps_w[t, :] if t >= par.To: sim.s[t, :] = par.rho * sim.k[t, :] else: sim.s[t, :] = 0 if t >= par.Tp and sim.h[t, :] == 0: sim.p[t, :] = par.P else: sim.p[t, :] = 0 sim.a[t, :] = sim.m[t, :] - sim.c[t, :] if t < par.T: sim.k[t + 1, :] = sim.k[t, :] + par.phi1 * pow( sim.h[t, :], par.phi2) sim.m[t + 1, :] = (1 + par.r) * sim.a[t, :] + sim.h[ t, :] * sim.wage[t, :] + sim.s[t, :] + sim.p[t, :] return sim
def DCEGM_(sol, h, a, k, t, par): # We need to look at their working fucntion since this is the choice with discrete choices! #this is the code for that #First this code finds w-raw, avg. marginal utility: #NEED CODE FOR P & S! #FINDING THE WAR FILES #xi = np.tile(par.xi,par.Na) #w = np.tile(par.xi_w,(par.Na,1)) #a = np.repeat(par.grid_a[t],par.Nxi) #k = np.repeat(k,par.Na) # Next period states k_plus = k + par.phi1 * h**par.phi2 # We need to include P and S, in the first round i try including them both at age Tsp(65) if t > 45: #par.Ts m_plus = (1 + par.r ) * a + par.kappa * par.xi * k * h + par.P + par.rho * k_plus else: m_plus = (1 + par.r) * a + par.kappa * par.xi * k * h # Value, consumption, marg_util shape = (3, m_plus.size) v_plus = np.nan + np.zeros(shape) c_plus = np.nan + np.zeros(shape) marg_u_plus = np.nan + np.zeros(shape) # next period ressources given todays work (m_plus) for h_plus in range(3): #Range over h for next period # Choice specific value v_plus[h_plus, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.v[t + 1, a, k, h_plus], m_plus, k_plus) # Choice specific consumption c_plus[h_plus, :] = tools.interp_2d_vec(par.grid_m, par.grid_k, sol.v[t + 1, a, k, h_plus], m_plus, k_plus) # Choice specific Marginal utility marg_u_plus[h_plus, :] = marg_util(c_plus[h_plus, :], par) # Expected value V_plus, prob = logsum(v_plus[0], v_plus[1], v_plus[2], par.sigma_epsilon) w_raw = par.xi_w * np.reshape(V_plus, (par.Na, par.Nxi)) w_raw = np.sum(w_raw, 1) marg_u_plus = prob[0, :] * marg_u_plus[0] + prob[ 1, :] * marg_u_plus[1] + prob[2, :] * marg_u_plus[2] #Expected average marg. utility avg_marg_u_plus = par.xi_w * np.reshape(marg_u_plus, (par.Na, par.Nxi)) avg_marg_u_plus = np.sum(avg_marg_u_plus, 1) # takes the raw consumption, m and v # raw c, m and v: c_raw = inv_marg_util(par.beta * (1 + par.r) * avg_marg_u_plus, par) m_raw = c_raw + par.grid_a[t, :] m = m_raw #v_raw = c_raw #These are used in the upper envelope to find the optimal consumotion and value! # Upper Envelope c, v = upper_envelope(t, h, c_raw, m_raw, w_raw, par) return c, v, m
def solve_egm(par, sol, sim): for z in [0, 1]: for i_h in range(par.Nh): sol.m[-1, :, z, i_h] = np.linspace(0, par.a_max, par.Na + 1) sol.c[-1, :, z, i_h] = sol.m[-1, :, z, i_h] # Before last period for t in range(par.T - 2, -1, -1): for i_h, h in enumerate(par.grid_h): if t >= par.TR and i_h != 0: # After retirement, solution is independent of z and h sol.c[t, :, z, i_h] = sol.c[t, :, 0, 0] sol.m[t, :, z, i_h] = sol.m[t, :, 0, 0] elif t >= par.TH and z == 1 and i_h != 0: # After early holiday pay, solution is independent of h sol.c[t, :, z, i_h] = sol.c[t, :, z, 0] sol.m[t, :, z, i_h] = sol.m[t, :, z, 0] elif t < par.TH - 1 and i_h != 0: # Before holiday pay decision, solution is independent of z and h sol.c[t, :, z, i_h] = sol.c[t, :, 0, 0] sol.m[t, :, z, i_h] = sol.m[t, :, 0, 0] else: # Loop over end-of-period assets for i_a in range(1, par.Na + 1): a = par.grid_a[i_a - 1] still_working_next_period = t + 1 <= par.TR - 1 if still_working_next_period: fac_vec = par.G[t] * par.psi_vec w = par.w xi = par.xi_vec if t + 1 < par.TH - 1: h_plus_vec = np.repeat(0.0, len(fac_vec)) elif t + 1 == par.TH - 1: h_plus_vec = np.repeat( par.alpha, len(fac_vec)) elif t + 1 > par.TH - 1 and z == 0: h_plus_vec = np.repeat( ((par.d_vec + par.delta - 1) / fac_vec) * h, len(fac_vec)) elif t + 1 > par.TH - 1 and z == 1: h_plus_vec = np.repeat(0.0, len(fac_vec)) if t + 1 == par.TH and z == 1: h_term_vec = ((par.d_vec + par.delta - 1) / fac_vec) * h else: h_term_vec = np.repeat(0.0, len(fac_vec)) m_plus_vec = (par.R / fac_vec) * a + xi + h_term_vec # Future c c_plus_vec = tools.interp_2d_vec( sol.m[t + 1, :, z, i_h], par.grid_h, sol.c[t + 1, :, z, :], m_plus_vec, h_plus_vec) # Average future marginal utility marg_u_plus_vec = marg_utility( fac_vec * c_plus_vec, par.rho) avg_marg_u_plus_vec = np.sum(w * marg_u_plus_vec) # Current c sol.c[t, i_a, z, i_h] = inv_marg_utility( par.beta * par.R * avg_marg_u_plus_vec, par.rho) # Current m sol.m[t, i_a, z, i_h] = a + sol.c[t, i_a, z, i_h] else: fac = par.G[t] if t + 1 == par.TR and z == 0: h_term = (par.delta / fac) * h else: h_term = 0.0 m_plus = (par.R / fac) * a + 1 + h_term # Future c c_plus = tools.interp_2d( sol.m[t + 1, :, z, i_h], par.grid_h, sol.c[t + 1, :, z, :], m_plus, 0.0) # Average future marginal utility marg_u_plus = marg_utility( fac * c_plus, par.rho) avg_marg_u_plus = marg_u_plus # Current c sol.c[t, i_a, z, i_h] = inv_marg_utility( par.beta * par.R * avg_marg_u_plus, par.rho) # Current m sol.m[t, i_a, z, i_h] = a + sol.c[t, i_a, z, i_h] # Add zero consumption sol.m[t, 0, z, i_h] = 0.0 sol.c[t, 0, z, i_h] = 0.0