def test_denhaan_errors(self): from dolo.misc.yamlfile import yaml_import from dolo.numeric.global_solve import global_solve model = yaml_import('examples/global_models/rbc.yaml') from dolo.compiler.compiler_global import CModel from dolo.numeric.perturbations_to_states import approximate_controls dr = approximate_controls(model) dr_global = global_solve(model, smolyak_order=4, verbose=False, pert_order=1) sigma = model.read_covariances() cmodel = CModel(model) cmodel.sigma = sigma s_0 = dr.S_bar from dolo.numeric.error_measures import denhaanerrors [error_1, error_2] = denhaanerrors(cmodel, dr, s_0) [error_1_glob, error_2_glob] = denhaanerrors(cmodel, dr_global, s_0) print(error_1) print(error_1_glob) assert( max(error_1_glob) < 10-7) # errors with solyak colocations at order 4 are very small assert( max(error_2_glob) < 10-7)
def global_solve(model, bounds=None, verbose=False, initial_dr=None, pert_order=2, interp_type='smolyak', smolyak_order=3, interp_orders=None, maxit=500, numdiff=True, polish=True, tol=1e-8, integration='gauss-hermite', integration_orders=[], compiler='numpy', memory_hungry=True, T=200, n_s=2, N_e=40 ): def vprint(t): if verbose: print(t) [y, x, parms] = model.read_calibration() sigma = model.read_covariances() if initial_dr == None: initial_dr = approximate_controls(model, order=pert_order) if interp_type == 'perturbations': return initial_dr if bounds is not None: pass elif 'approximation' in model['original_data']: vprint('Using bounds specified by model') # this should be moved to the compiler ssmin = model['original_data']['approximation']['bounds']['smin'] ssmax = model['original_data']['approximation']['bounds']['smax'] ssmin = [model.eval_string(str(e)) for e in ssmin] ssmax = [model.eval_string(str(e)) for e in ssmax] ssmin = [model.eval_string(str(e)) for e in ssmin] ssmax = [model.eval_string(str(e)) for e in ssmax] [y, x, p] = model.read_calibration() d = {v: y[i] for i, v in enumerate(model.variables)} d.update({v: p[i] for i, v in enumerate(model.parameters)}) smin = [expr.subs(d) for expr in ssmin] smax = [expr.subs(d) for expr in ssmax] smin = numpy.array(smin, dtype=numpy.float) smax = numpy.array(smax, dtype=numpy.float) bounds = numpy.row_stack([smin, smax]) bounds = numpy.array(bounds, dtype=float) else: vprint('Using bounds given by second order solution.') from dolo.numeric.timeseries import asymptotic_variance # this will work only if initial_dr is a Taylor expansion Q = asymptotic_variance(initial_dr.A.real, initial_dr.B.real, initial_dr.sigma, T=T) devs = numpy.sqrt(numpy.diag(Q)) bounds = numpy.row_stack([ initial_dr.S_bar - devs * n_s, initial_dr.S_bar + devs * n_s, ]) smin = bounds[0, :] smax = bounds[1, :] if interp_orders == None: interp_orders = [5] * bounds.shape[1] if interp_type == 'smolyak': from dolo.numeric.interpolation.smolyak import SmolyakGrid dr = SmolyakGrid(bounds[0, :], bounds[1, :], smolyak_order) elif interp_type == 'spline': from dolo.numeric.interpolation.splines import MultivariateSplines dr = MultivariateSplines(bounds[0, :], bounds[1, :], interp_orders) elif interp_type == 'multilinear': from dolo.numeric.interpolation.multilinear import MultilinearInterpolator dr = MultilinearInterpolator(bounds[0, :], bounds[1, :], interp_orders) elif interp_type == 'sparse_linear': from dolo.numeric.interpolation.interpolation import SparseLinear dr = SparseLinear(bounds[0, :], bounds[1, :], smolyak_order) elif interp_type == 'linear': from dolo.numeric.interpolation.interpolation import LinearTriangulation, TriangulatedDomain, RectangularDomain rec = RectangularDomain(smin, smax, interp_orders) domain = TriangulatedDomain(rec.grid) dr = LinearTriangulation(domain) from dolo.compiler.compiler_global import CModel cm = CModel(model, solve_systems=True, compiler=compiler) cm = cm.as_type('fg') if integration == 'optimal_quantization': from dolo.numeric.quantization import quantization_nodes # number of shocks [epsilons, weights] = quantization_nodes(N_e, sigma) elif integration == 'gauss-hermite': from dolo.numeric.quadrature import gauss_hermite_nodes if not integration_orders: integration_orders = [3] * sigma.shape[0] [epsilons, weights] = gauss_hermite_nodes(integration_orders, sigma) vprint('Starting time iteration') from dolo.numeric.global_solution import time_iteration from dolo.numeric.global_solution import stochastic_residuals_2, stochastic_residuals_3 xinit = initial_dr(dr.grid) xinit = xinit.real # just in case... dr = time_iteration(dr.grid, dr, xinit, cm.f, cm.g, parms, epsilons, weights, x_bounds=cm.x_bounds, maxit=maxit, tol=tol, nmaxit=50, numdiff=numdiff, verbose=verbose) if polish and interp_type == 'smolyak': # this works with smolyak only vprint('\nStarting global optimization') import time t1 = time.time() if cm.x_bounds is not None: lb = cm.x_bounds[0](dr.grid, parms) ub = cm.x_bounds[1](dr.grid, parms) else: lb = None ub = None xinit = dr(dr.grid) dr.set_values(xinit) shape = xinit.shape if not memory_hungry: fobj = lambda t: stochastic_residuals_3(dr.grid, t, dr, cm.f, cm.g, parms, epsilons, weights, shape, deriv=False) dfobj = lambda t: stochastic_residuals_3(dr.grid, t, dr, cm.f, cm.g, parms, epsilons, weights, shape, deriv=True)[1] else: fobj = lambda t: stochastic_residuals_2(dr.grid, t, dr, cm.f, cm.g, parms, epsilons, weights, shape, deriv=False) dfobj = lambda t: stochastic_residuals_2(dr.grid, t, dr, cm.f, cm.g, parms, epsilons, weights, shape, deriv=True)[1] from dolo.numeric.solver import solver x = solver(fobj, xinit, lb=lb, ub=ub, jac=dfobj, verbose=verbose, method='ncpsolve', serial_problem=False) dr.set_values(x) # just in case t2 = time.time() # test solution res = stochastic_residuals_2(dr.grid, x, dr, cm.f, cm.g, parms, epsilons, weights, shape, deriv=False) if numpy.isinf(res.flatten()).sum() > 0: raise ( Exception('Non finite values in residuals.')) vprint('Finished in {} s'.format(t2 - t1)) return dr
pyplot.xlabel(state) if __name__ == '__main__': from dolo import yaml_import, approximate_controls model = yaml_import('../../examples/global_models/capital.yaml') dr = approximate_controls(model) [y, x, parms] = model.read_calibration() sigma = model.read_covariances() from dolo.compiler.compiler_global import CModel import numpy cmodel = CModel(model) s0 = numpy.atleast_2d(dr.S_bar).T horizon = 50 simul = simulate(cmodel, dr, s0, sigma, n_exp=500, parms=parms, seed=1, horizon=horizon) from dolo.numeric.quantization import quantization_nodes N = 80 [x, w] = quantization_nodes(N, sigma)
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
bounds[:, 1] += s0[1] print('bounds') print bounds P = eigs[1] sg = SmolyakGrid(bounds, 5, P) [y, x, parms] = model.read_calibration() xinit = dr(sg.grid) sg.fit_values(xinit) from dolo.compiler.compiler_global import CModel, time_iteration, deterministic_residuals gc = CModel(model) res = deterministic_residuals(sg.grid, xinit, sg, gc.f, gc.g, dr.sigma, parms) n_e = 5 epsilons = np.zeros((1, n_e)) weights = np.ones(n_e) / n_e dr_smol = time_iteration(sg.grid, sg, xinit, gc.f, gc.g, parms, epsilons, weights,