def compute_expectations_psi( cm, dr_x, dr_z, s, x, p, nodes, weights): N = s.shape[1] n_s = s.shape[0] n_x = x.shape[0] n_h = len(cm.model['variables_groups']['expectations']) Q = len(weights) ss = tile(s, (1,Q)) xx = tile(x, (1,Q)) ee = repeat(nodes, N , axis=1) SS = cm.g(ss,xx,ee,p) xxstart = dr_x(SS) ZZ = dr_z(SS) ff = lambda xt: cm.f(SS,xt,ZZ,p) [XX,nit] = newton_solver(ff , xxstart, numdiff=True,infos=True) hh = cm.h(SS,XX,p) z = np.zeros( (n_x,N) ) for i in range(Q): z += weights[i] * hh[:,N*i:N*(i+1)] return z
def pea_solve( cm, grid, dr_x, dr_z, p, nodes, weights ): tol = 1e-9 err = 10 maxit = 500 it = 0 x0 = dr_x(grid) z0 = dr_z(grid) # z0 = compute_expectations_phi( cm, dr_x, grid, x0, p, nodes, weights) while err > tol and it < maxit: it += 1 fobj = lambda x: cm.f( grid, x, z0, p ) x1 = newton_solver( fobj, x0, numdiff=True) dr_x.set_values(x1) # I don't really need it z1 = compute_expectations_psi(cm, dr_x, dr_h, grid, x1, params, nodes, weights) dr_z.set_values(z1) err = abs(z1 - z0).max() err2 = abs(x1 - x0).max() print(err, err2) x0 = x1 z0 = z1 print('finished in {} iterations'.format(it)) return [x0,z0]
def pea_solve(cm, grid, dr_x, dr_z, p, nodes, weights): tol = 1e-9 err = 10 maxit = 500 it = 0 x0 = dr_x(grid) z0 = dr_z(grid) # z0 = compute_expectations_phi( cm, dr_x, grid, x0, p, nodes, weights) while err > tol and it < maxit: it += 1 fobj = lambda x: cm.f(grid, x, z0, p) x1 = newton_solver(fobj, x0, numdiff=True) dr_x.set_values(x1) # I don't really need it z1 = compute_expectations_psi(cm, dr_x, dr_h, grid, x1, params, nodes, weights) dr_z.set_values(z1) err = abs(z1 - z0).max() err2 = abs(x1 - x0).max() print(err, err2) x0 = x1 z0 = z1 print('finished in {} iterations'.format(it)) return [x0, z0]
def compute_expectations_psi(cm, dr_x, dr_z, s, x, p, nodes, weights): N = s.shape[1] n_s = s.shape[0] n_x = x.shape[0] n_h = len(cm.model['variables_groups']['expectations']) Q = len(weights) ss = tile(s, (1, Q)) xx = tile(x, (1, Q)) ee = repeat(nodes, N, axis=1) SS = cm.g(ss, xx, ee, p) xxstart = dr_x(SS) ZZ = dr_z(SS) ff = lambda xt: cm.f(SS, xt, ZZ, p) [XX, nit] = newton_solver(ff, xxstart, numdiff=True, infos=True) hh = cm.h(SS, XX, p) z = np.zeros((n_x, N)) for i in range(Q): z += weights[i] * hh[:, N * i:N * (i + 1)] return z
def simulate(cmodel, dr, s0=None, sigma=None, n_exp=0, horizon=40, parms=None, seed=1, discard=False, stack_series=True, solve_expectations=False, nodes=None, weights=None, use_pandas=True): ''' :param cmodel: compiled model :param dr: decision rule :param s0: initial state where all simulations start :param sigma: covariance matrix of the normal multivariate distribution describing the random shocks :param n_exp: number of draws to simulate. Use 0 for impulse-response functions :param horizon: horizon for the simulation :param parms: (vector) value for the parameters of the model :param seed: used to initialize the random number generator. Use it to replicate exact same results among simulations :param discard: (default: False) if True, then all simulations containing at least one non finite value are discarded :param stack_series: return simulated series for different types of variables separately (in a list) :return: a ``n_s x n_exp x horizon`` array where ``n_s`` is the number of states. The second dimension is omitted if n_exp = 0. ''' if n_exp == 0: irf = True n_exp = 1 else: irf = False calib = cmodel.calibration if parms is None: parms = numpy.array( calib['parameters']) # TODO : remove reference to symbolic model if sigma is None: sigma = numpy.array(calib['covariances']) if s0 is None: s0 = numpy.array(calib['states']) s0 = numpy.atleast_2d(s0.flatten()).T x0 = dr(s0) s_simul = numpy.zeros((s0.shape[0], n_exp, horizon)) x_simul = numpy.zeros((x0.shape[0], n_exp, horizon)) s_simul[:, :, 0] = s0 x_simul[:, :, 0] = x0 fun = cmodel.functions if cmodel.model_type == 'fga': ff = fun['arbitrage'] gg = fun['transition'] aa = fun['auxiliary'] g = lambda s, x, e, p: gg(s, x, aa(s, x, p), e, p) f = lambda s, x, e, S, X, p: ff(s, x, aa(s, x, p), S, X, aa(S, X, p), p ) else: f = cmodel.functions['arbitrage'] g = cmodel.functions['transition'] numpy.random.seed(seed) for i in range(horizon): mean = numpy.zeros(sigma.shape[0]) if irf: epsilons = numpy.zeros((sigma.shape[0], 1)) else: epsilons = numpy.random.multivariate_normal(mean, sigma, n_exp).T s = s_simul[:, :, i] x = dr(s) if solve_expectations: from dolo.numeric.solver import solver from dolo.numeric.newton import newton_solver fobj = lambda t: step_residual( s, t, dr, f, g, parms, nodes, weights, with_derivatives=False ) # # x = solver(fobj, x, serial_problem=True) x = newton_solver(fobj, x, numdiff=True) x_simul[:, :, i] = x ss = g(s, x, epsilons, parms) if i < (horizon - 1): s_simul[:, :, i + 1] = ss from numpy import any, isnan, all if not 'auxiliary' in fun: # TODO: find a better test than this l = [s_simul, x_simul] varnames = cmodel.symbols['states'] = cmodel.symbols['controls'] else: aux = fun['auxiliary'] n_s = s_simul.shape[0] n_x = x_simul.shape[0] a_simul = aux(s_simul.reshape((n_s, n_exp * horizon)), x_simul.reshape((n_x, n_exp * horizon)), parms) n_a = a_simul.shape[0] a_simul = a_simul.reshape(n_a, n_exp, horizon) l = [s_simul, x_simul, a_simul] varnames = cmodel.symbols['states'] + cmodel.symbols[ 'controls'] + cmodel.symbols['auxiliary'] if not stack_series: return l else: simul = numpy.row_stack(l) if discard: iA = -isnan(x_simul) valid = all(all(iA, axis=0), axis=1) simul = simul[:, valid, :] n_kept = s_simul.shape[1] if n_exp > n_kept: print('Discarded {}/{}'.format(n_exp - n_kept, n_exp)) if irf: simul = simul[:, 0, :] if use_pandas: import pandas ts = pandas.DataFrame(simul.T, columns=varnames) return ts return simul
def simulate(cmodel, dr, s0=None, sigma=None, n_exp=0, horizon=40, parms=None, seed=1, discard=False, stack_series=True, solve_expectations=False, nodes=None, weights=None, use_pandas=True): ''' :param cmodel: compiled model :param dr: decision rule :param s0: initial state where all simulations start :param sigma: covariance matrix of the normal multivariate distribution describing the random shocks :param n_exp: number of draws to simulate. Use 0 for impulse-response functions :param horizon: horizon for the simulation :param parms: (vector) value for the parameters of the model :param seed: used to initialize the random number generator. Use it to replicate exact same results among simulations :param discard: (default: False) if True, then all simulations containing at least one non finite value are discarded :param stack_series: return simulated series for different types of variables separately (in a list) :return: a ``n_s x n_exp x horizon`` array where ``n_s`` is the number of states. The second dimension is omitted if n_exp = 0. ''' if n_exp ==0: irf = True n_exp = 1 else: irf = False calib = cmodel.calibration if parms is None: parms = numpy.array( calib['parameters'] ) # TODO : remove reference to symbolic model if sigma is None: sigma = numpy.array( calib['covariances'] ) if s0 is None: s0 = numpy.array( calib['states'] ) s0 = numpy.atleast_2d(s0.flatten()).T x0 = dr(s0) s_simul = numpy.zeros( (s0.shape[0],n_exp,horizon) ) x_simul = numpy.zeros( (x0.shape[0],n_exp,horizon) ) s_simul[:,:,0] = s0 x_simul[:,:,0] = x0 fun = cmodel.functions if cmodel.model_type == 'fga': ff = fun['arbitrage'] gg = fun['transition'] aa = fun['auxiliary'] g = lambda s,x,e,p : gg(s,x,aa(s,x,p),e,p) f = lambda s,x,e,S,X,p : ff(s,x,aa(s,x,p),S,X,aa(S,X,p),p) else: f = cmodel.functions['arbitrage'] g = cmodel.functions['transition'] numpy.random.seed(seed) for i in range(horizon): mean = numpy.zeros(sigma.shape[0]) if irf: epsilons = numpy.zeros( (sigma.shape[0],1) ) else: epsilons = numpy.random.multivariate_normal(mean, sigma, n_exp).T s = s_simul[:,:,i] x = dr(s) if solve_expectations: from dolo.numeric.solver import solver from dolo.numeric.newton import newton_solver fobj = lambda t: step_residual(s, t, dr, f, g, parms, nodes, weights, with_derivatives=False) # # x = solver(fobj, x, serial_problem=True) x = newton_solver(fobj, x, numdiff=True) x_simul[:,:,i] = x ss = g(s,x,epsilons,parms) if i<(horizon-1): s_simul[:,:,i+1] = ss from numpy import any,isnan,all if not 'auxiliary' in fun: # TODO: find a better test than this l = [s_simul, x_simul] varnames = cmodel.symbols['states'] = cmodel.symbols['controls'] else: aux = fun['auxiliary'] n_s = s_simul.shape[0] n_x = x_simul.shape[0] a_simul = aux( s_simul.reshape((n_s,n_exp*horizon)), x_simul.reshape( (n_x,n_exp*horizon) ), parms) n_a = a_simul.shape[0] a_simul = a_simul.reshape(n_a,n_exp,horizon) l = [s_simul, x_simul, a_simul] varnames = cmodel.symbols['states'] + cmodel.symbols['controls'] + cmodel.symbols['auxiliary'] if not stack_series: return l else: simul = numpy.row_stack(l) if discard: iA = -isnan(x_simul) valid = all( all( iA, axis=0 ), axis=1 ) simul = simul[:,valid,:] n_kept = s_simul.shape[1] if n_exp > n_kept: print( 'Discarded {}/{}'.format(n_exp-n_kept,n_exp)) if irf: simul = simul[:,0,:] if use_pandas: import pandas ts = pandas.DataFrame(simul.T, columns=varnames) return ts return simul
def solver(fobj, x0, lb=None, ub=None, jac=None, method='lmmcp', infos=False, serial_problem=False, verbose=False, options={}): in_shape = x0.shape if serial_problem: ffobj = fobj else: ffobj = lambda x: fobj(x.reshape(in_shape)).flatten() # standardize jacobian if jac is not None: if not serial_problem: pp = np.prod(in_shape) def Dffobj(t): tt = t.reshape(in_shape) dval = jac(tt) return dval.reshape((pp, pp)) else: Dffobj = jac elif serial_problem: from dolo.numeric.newton import SerialDifferentiableFunction Dffobj = SerialDifferentiableFunction(fobj, in_shape) else: Dffobj = MyJacobian(ffobj) if lb == None: lb = -np.inf * np.ones(len(x0.flatten())) if ub == None: ub = np.inf * np.ones(len(x0.flatten())).flatten() if not serial_problem: lb = lb.flatten() ub = ub.flatten() if not serial_problem: x0 = x0.flatten() if method == 'fsolve': import scipy.optimize as optimize factor = options.get('factor') factor = factor if factor else 1 [sol, infodict, ier, msg] = optimize.fsolve(ffobj, x0, fprime=Dffobj, factor=factor, full_output=True, xtol=1e-10, epsfcn=1e-9) if ier != 1: print(msg) elif method == 'newton': from dolo.numeric.newton import serial_newton as newton_solver fun = lambda x: [ffobj(x), Dffobj(x)] [sol, nit] = newton_solver(fun, x0, verbose=verbose) elif method == 'lmmcp': from dolo.numeric.extern.lmmcp import lmmcp sol = lmmcp(lambda t: -ffobj(t), lambda u: -Dffobj(u), x0, lb, ub, verbose=verbose, options=options) elif method == 'ncpsolve': from dolo.numeric.ncpsolve import ncpsolve fun = lambda x: [ffobj(x), Dffobj(x)] if serial_problem: jactype = 'serial' [sol, nit] = ncpsolve(fun, lb, ub, x0, verbose=verbose, infos=True, jactype='serial') else: raise Exception('Unknown method : ' + str(method)) sol = sol.reshape(in_shape) if infos: return [sol, nit] else: return sol
def simulate(cmodel, dr, s0=None, sigma=None, n_exp=0, horizon=40, parms=None, seed=1, discard=False, stack_series=True, solve_expectations=False, nodes=None, weights=None): ''' :param cmodel: compiled model :param dr: decision rule :param s0: initial state where all simulations start :param sigma: covariance matrix of the normal multivariate distribution describing the random shocks :param n_exp: number of draws to simulate. Use 0 for impulse-response functions :param horizon: horizon for the simulation :param parms: (vector) value for the parameters of the model :param seed: used to initialize the random number generator. Use it to replicate exact same results among simulations :param discard: (default: False) if True, then all simulations containing at least one non finite value are discarded :param stack_series: return simulated series for different types of variables separately (in a list) :return: a ``n_s x n_exp x horizon`` array where ``n_s`` is the number of states. The second dimension is omitted if n_exp = 0. ''' from dolo.compiler.compiler_global import CModel from dolo.symbolic.model import Model if isinstance(cmodel, Model): from dolo.symbolic.model import Model model = cmodel cmodel = CModel(model) [y,x,parms] = model.read_calibration() else: cmodel = cmodel.as_type('fg') if n_exp ==0: irf = True n_exp = 1 else: irf = False calib = cmodel.model.calibration if parms is None: parms = numpy.array( calib['parameters'] ) # TODO : remove reference to symbolic model if sigma is None: sigma = numpy.array( calib['sigma'] ) if s0 is None: s0 = numpy.array( calib['steady_state']['states'] ) s0 = numpy.atleast_2d(s0.flatten()).T x0 = dr(s0) s_simul = numpy.zeros( (s0.shape[0],n_exp,horizon) ) x_simul = numpy.zeros( (x0.shape[0],n_exp,horizon) ) s_simul[:,:,0] = s0 x_simul[:,:,0] = x0 numpy.random.seed(seed) for i in range(horizon): mean = numpy.zeros(sigma.shape[0]) if irf: epsilons = numpy.zeros( (sigma.shape[0],1) ) else: epsilons = numpy.random.multivariate_normal(mean, sigma, n_exp).T s = s_simul[:,:,i] x = dr(s) if solve_expectations: from dolo.numeric.solver import solver from dolo.numeric.newton import newton_solver fobj = lambda t: step_residual(s, t, dr, cmodel.f, cmodel.g, parms, nodes, weights, with_derivatives=False) # # x = solver(fobj, x, serial_problem=True) x = newton_solver(fobj, x, numdiff=True) x_simul[:,:,i] = x ss = cmodel.g(s,x,epsilons,parms) if i<(horizon-1): s_simul[:,:,i+1] = ss from numpy import any,isnan,all if not hasattr(cmodel,'__a__'): # TODO: find a better test than this l = [s_simul, x_simul] else: n_s = s_simul.shape[0] n_x = x_simul.shape[0] a_simul = cmodel.a( s_simul.reshape((n_s,n_exp*horizon)), x_simul.reshape( (n_x,n_exp*horizon) ), parms) n_a = a_simul.shape[0] a_simul = a_simul.reshape(n_a,n_exp,horizon) l = [s_simul, x_simul, a_simul] if not stack_series: return l else: simul = numpy.row_stack(l) if discard: iA = -isnan(x_simul) valid = all( all( iA, axis=0 ), axis=1 ) simul = simul[:,valid,:] n_kept = s_simul.shape[1] if n_exp > n_kept: print( 'Discarded {}/{}'.format(n_exp-n_kept,n_exp)) if irf: simul = simul[:,0,:] return simul
def solver(fobj, x0, lb=None, ub=None, jac=None, method='lmmcp', infos=False, serial_problem=False, verbose=False, options={}): in_shape = x0.shape if serial_problem: ffobj = fobj else: ffobj = lambda x: fobj(x.reshape(in_shape)).flatten() # standardize jacobian if jac is not None: if not serial_problem: pp = np.prod(in_shape) def Dffobj(t): tt = t.reshape(in_shape) dval = jac(tt) return dval.reshape( (pp,pp) ) else: Dffobj = jac elif serial_problem: Dffobj = MySerialJacobian(fobj, in_shape) else: Dffobj = MyJacobian(ffobj) if lb == None: lb = -np.inf*np.ones(len(x0.flatten())) if ub == None: ub = np.inf*np.ones(len(x0.flatten())).flatten() if not serial_problem: lb = lb.flatten() ub = ub.flatten() if not serial_problem: x0 = x0.flatten() if method == 'fsolve': import scipy.optimize as optimize factor = options.get('factor') factor = factor if factor else 1 [sol,infodict,ier,msg] = optimize.fsolve(ffobj, x0, fprime=Dffobj, factor=factor, full_output=True, xtol=1e-10, epsfcn=1e-9) if ier != 1: print(msg) elif method == 'newton': from dolo.numeric.newton import newton_solver fun = lambda x: [ffobj(x), Dffobj(x) ] [sol,nit] = newton_solver(fun,x0, verbose=verbose, infos=True) elif method == 'lmmcp': from dolo.numeric.extern.lmmcp import lmmcp sol = lmmcp(lambda t: -ffobj(t), lambda u: -Dffobj(u),x0,lb,ub,verbose=verbose,options=options) elif method == 'ncpsolve': from dolo.numeric.ncpsolve import ncpsolve fun = lambda x: [ffobj(x), Dffobj(x) ] [sol,nit] = ncpsolve(fun,lb,ub,x0, verbose=verbose, infos=True, serial=serial_problem) sol = sol.reshape(in_shape) if infos: return [sol, nit] else: return sol
def time_iteration( grid, interp, xinit, f, g, parms, epsilons, weights, x_bounds=None, options={}, serial_grid=True, verbose=True, method="lmmcp", maxit=500, nmaxit=5, backsteps=10, hook=None, ): from dolo.numeric.solver import solver from dolo.numeric.newton import newton_solver if serial_grid: # fun = lambda x: step_residual(grid, x, interp, f, g, parms, epsilons, weights, x_bounds=x_bounds, with_derivatives=False)[0] # dfun = lambda x: step_residual(grid, x, interp, f, g, parms, epsilons, weights, x_bounds=x_bounds)[1] fun = lambda x: step_residual(grid, x, interp, f, g, parms, epsilons, weights, x_bounds=x_bounds) else: fun = lambda x: step_residual( grid, x, interp, f, g, parms, epsilons, weights, x_bounds=x_bounds, serial_grid=False, with_derivatives=False, )[0] dfun = lambda x: step_residual( grid, x, interp, f, g, parms, epsilons, weights, x_bounds=x_bounds, serial_grid=False )[1] # tol = 1e-8 ## import time t1 = time.time() err = 1 x0 = xinit it = 0 verbit = True if verbose == "full" else False if x_bounds: [lb, ub] = x_bounds(grid, parms) else: lb = None ub = None if verbose: s = "|Iteration\t|\tStep\t\t\t|\tTime (s)\t|" nnn = len(s.replace("\t", " " * 4)) print("-" * nnn) print(s) print("-" * nnn) while err > tol and it < maxit: t_start = time.time() it += 1 interp.fit_values(x0) if serial_grid: [x, nit] = newton_solver(fun, x0, lb=lb, ub=ub, infos=True, backsteps=backsteps, maxit=nmaxit) else: x = solver(fun, x0, lb=lb, ub=ub, method=method, jac=dfun, verbose=verbit, options=options) nit = 0 # we restrict the solution to lie inside the boundaries if x_bounds: x = np.maximum(np.minimum(ub, x), lb) # res = abs(fun(x)).max() err = abs(x - x0).max() t_finish = time.time() elapsed = t_finish - t_start if verbose: print("\t\t{}\t|\t{:e}\t|\t{:f}\t|\t{}".format(it, err, elapsed, nit)) x0 = x0 + (x - x0) if hook: hook(interp, it, err) if False in np.isfinite(x0): print("iteration {} failed : non finite value") return [x0, x] if it == maxit: import warnings warnings.warn(UserWarning("Maximum number of iterations reached")) t2 = time.time() print("Elapsed: {}".format(t2 - t1)) return interp
def time_iteration(grid, interp, xinit, f, g, parms, epsilons, weights, x_bounds=None, options={}, serial_grid=True, verbose=True, method='lmmcp', maxit=500, nmaxit=5, backsteps=10, hook=None): from dolo.numeric.solver import solver from dolo.numeric.newton import newton_solver if serial_grid: #fun = lambda x: step_residual(grid, x, interp, f, g, parms, epsilons, weights, x_bounds=x_bounds, with_derivatives=False)[0] #dfun = lambda x: step_residual(grid, x, interp, f, g, parms, epsilons, weights, x_bounds=x_bounds)[1] fun = lambda x: step_residual(grid, x, interp, f, g, parms, epsilons, weights, x_bounds=x_bounds) else: fun = lambda x: step_residual(grid, x, interp, f, g, parms, epsilons, weights, x_bounds=x_bounds, serial_grid=False, with_derivatives=False)[0] dfun = lambda x: step_residual(grid, x, interp, f, g, parms, epsilons, weights, x_bounds=x_bounds, serial_grid=False)[1] # tol = 1e-8 ## import time t1 = time.time() err = 1 x0 = xinit it = 0 verbit = True if verbose=='full' else False if x_bounds: [lb,ub] = x_bounds(grid,parms) else: lb = None ub = None if verbose: s = "|Iteration\t|\tStep\t\t\t|\tTime (s)\t|" nnn = len(s.replace('\t',' '*4)) print('-'*nnn) print(s) print('-'*nnn) while err > tol and it < maxit: t_start = time.time() it +=1 interp.fit_values(x0) if serial_grid: [x,nit] = newton_solver(fun,x0,lb=lb,ub=ub,infos=True, backsteps=backsteps, maxit=nmaxit) else: x = solver(fun, x0, lb=lb, ub=ub, method=method, jac=dfun, verbose=verbit, options=options) nit = 0 # we restrict the solution to lie inside the boundaries if x_bounds: x = np.maximum(np.minimum(ub,x),lb) # res = abs(fun(x)).max() err = abs(x-x0).max() t_finish = time.time() elapsed = t_finish - t_start if verbose: print("\t\t{}\t|\t{:e}\t|\t{:f}\t|\t{}".format(it,err,elapsed,nit)) x0 = x0 + (x-x0) if hook: hook(interp,it,err) if False in np.isfinite(x0): print('iteration {} failed : non finite value') return [x0, x] if it == maxit: import warnings warnings.warn(UserWarning("Maximum number of iterations reached")) t2 = time.time() print('Elapsed: {}'.format(t2 - t1)) return interp