def compute_child_support_transitions(self,*,child_support_share): from interp_np import interp # this computes sets of transition matrices when in married couple # that breaks male gives away part of his income to wife. In this # setup that means that productivity of male decreases and # productivity of female increases. # structure: for each t there are indices of zf, probabilities of # zf, indices of zm, probabilities of zm p = self.pars transitions = list() for t in range(p['T']): trans_t = dict() trend_f = p['f_wage_trend'][t] trend_m = p['m_wage_trend'][t] zf_all = self.exogrid.zf_t[t] zm_all = self.exogrid.zm_t[t] if zf_all.size > 1 and zm_all.size>1: income_fem = np.exp(trend_f + zf_all) income_mal = np.exp(trend_m + zm_all) child_support = child_support_share*income_mal income_fem_adj = income_fem[:,None] + child_support[None,:] income_mal_adj = income_mal - child_support z_fem_adj = np.log(income_fem_adj) - trend_f z_mal_adj = np.log(income_mal_adj) - trend_m #von_fem = VecOnGrid(zf_all,z_fem_adj) trans_t['i_this_fem'], trans_t['w_this_fem'] = \ interp(zf_all,z_fem_adj,return_wnext=False,trim=True) #von_mal = VecOnGrid(zm_all,z_mal_adj) trans_t['i_this_mal'], trans_t['w_this_mal'] = \ interp(zm_all,z_mal_adj,return_wnext=False,trim=True) else: fill = np.array([-1],dtype=np.int16), np.array([0.0],dtype=self.dtype) trans_t['i_this_fem'], trans_t['w_this_fem'] = fill trans_t['i_this_mal'], trans_t['w_this_mal'] = fill transitions.append(trans_t) self.child_support_transitions = transitions
def __init__(self, grid, values, iwn=None, trim=True): # this assumes grid is strictly increasing o/w unpredictable self.val = values self.val_trimmed = np.clip(values, grid[0], grid[-1]) self.grid = grid if iwn is None: self.i, self.wnext = interp(self.grid, self.val, return_wnext=True, trim=trim) else: self.i, self.wnext = iwn if np.any(self.i < 0): # manual correction to avoid -1 ichange = (self.i < 0) assert np.allclose(self.wnext[ichange], 1.0) self.i[ichange] = 0 self.wnext[ichange] = 0.0 self.wnext = self.wnext.astype(grid.dtype) self.n = self.i.size self.one = np.array(1).astype(grid.dtype) # sorry self.wthis = self.one - self.wnext self.trim = trim assert np.allclose(self.val_trimmed, self.apply_crude(grid))
def update(self, where, values): # this replaces values at positions where with values passed to the # function and recomputes interpolation weights where, values = num_to_nparray( where, values) # safety check in case of singletons assert (where.size == values.size) or (values.size == 1) if values.size == 1: values = values * np.ones(where.shape) self.val[where] = values self.i[where], self.wnext[where] = \ interp(self.grid,self.val[where],return_wnext=True,trim=self.trim) self.wnext[where] = self.wnext[where].astype(self.dtype) self.wthis[where] = self.one - self.wnext[where]
def v_compare(agrid, v_base, v_compare, *, a_mult): ia0 = 0 names = [ 'extra assets in base to reach 0 in compare', 'extra assets in compare to reach 0 in base' ] i = 0 aall = list() amin = agrid.min() amax = agrid.max() for (v0, v1), name in zip([(v_base, v_compare), (v_compare, v_base)], names): print('') print(name) print('') print('v0 is larger in {} cases'.format(np.sum(v0 > v1))) print('v0 is smaller in {} cases'.format(np.sum(v0 < v1))) alist = list() for iz in range(v0.shape[1]): j, wn = interp(v0[:, iz], v1[ia0, iz], return_wnext=True) if j <= -1: a = 0.0 else: a = agrid[j] * (1 - wn) + agrid[j + 1] * wn a = np.clip(a, amin, amax) alist.append(a_mult * a) i += 1 aall.append(np.array(alist)) return aall[1] - aall[0]