Table Of Contents

Source code for dolo.compiler.compiler_python

from dolo.misc.caching import memoized


[docs]class GModel(object): '''Generic compiled model object :param model: (SModel) a symbolic model :param model_type: (str) model type (e.g. ``"fg"`` or ``"fga"`` :param recipes: (dict) dictionary of recipes (must contain ``model_type`` as a key) :param compiler: (str) compiler to use. One of ``numpy``, ``numexpr``, ``theano`` The class contains the following fields: :attr symbols: (dict) symbol groups -> list of symbol names defining each group :attr functions: (dict) equation names -> compiled functions :attr calibration: (dict) symbol groups -> vector of calibrated values for each group :attr model: (optional) link to the original symbolic model ''' model = None calibration = None functions = None symbols = None @property def variables(self): vars = [] for vg in self.symbols: if vg not in ('parameters','shocks'): vars.extend( self.symbols[vg] ) return vars def __init__(self, model, model_type=None, recipes=None, compiler=None, order='rows'): # this part is actually common to all compilers if model_type is None: model_type = model.__data__['model_type'] self.model = model from dolo.symbolic.validator import validate if isinstance(model_type, str): from dolo.symbolic.recipes import recipes as recipes_dict if recipes is not None: recipes_dict.update(recipes) self.recipe = recipes_dict[model_type] validate(model, self.recipe) else: # if model_type is not a string, we assume it is a recipe (why ?) self.recipe = model_type self.model_type = self.recipe['model_type'] self.__create_functions__(compiler, order=order) def __create_functions__(self, compiler, order='rows'): recipe = self.recipe model = self.model parms = model.symbols_s['parameters'] if compiler == 'numexpr': from dolo.compiler.function_compiler_numexpr import compile_multiargument_function elif compiler == 'theano': from dolo.compiler.function_compiler_theano import compile_multiargument_function elif compiler == 'numba': from dolo.compiler.function_compiler_numba import compile_multiargument_function elif compiler == 'numba_gpu': from dolo.compiler.function_compiler_numba_gpu import compile_multiargument_function else: from dolo.compiler.function_compiler import compile_multiargument_function functions = {} for eqg in self.model.equations_groups: args = [] is_a_definition = 'definition' in recipe['equation_type'][eqg] if is_a_definition: arg_specs = recipe['equation_type'][eqg]['rhs'] else: arg_specs = recipe['equation_type'][eqg] arg_names = [] for syms in arg_specs: [sgn,time] = syms if syms[0] == 'shocks': args.append( [ s(time) for s in model.symbols_s['shocks'] ] ) else: args.append( [ s(time) for s in model.symbols_s[sgn] ] ) if time == 1: stime = '_f' elif time == -1: stime = '_p' else: stime = '' arg_names.append( sgn + stime) equations = self.model.equations_groups[eqg] if is_a_definition: from dolo.compiler.common import solve_recursive_block equations = solve_recursive_block(equations) equations = [eq.rhs for eq in equations] else: equations = [eq.gap for eq in equations] functions[eqg] = compile_multiargument_function(equations, args, arg_names, parms, fname = eqg, order=order) self.__update_calibration__() from collections import OrderedDict l = [ (vg, [str(s) for s in model.symbols_s[vg]] ) for vg in (recipe['variable_type'] + ['shocks','parameters']) ] symbols = OrderedDict( l ) self.symbols = symbols self.functions = functions def __update_calibration__(self): import numpy from collections import OrderedDict calibration = self.model.calibration for k,v in calibration.iteritems(): if isinstance(v, OrderedDict): for l in v: v[l] = numpy.array(v[l], dtype=numpy.double) else: calibration[k] = numpy.array(calibration[k], dtype=numpy.double) self.calibration = calibration
[docs] def set_calibration(self,*args): """Updates the model calibration while respecting dependences between parameters. :param args: either two parameters ``key``, ``value`` or a dictionary mapping several keys to several values each key must be a string among the symbols of the model """ if len(args) == 2: d = {args[0]:args[1]} else: d = args[0] self.model.set_calibration(d) self.__update_calibration__()
[docs] def get_calibration(self,name): """Get the calibrated value for one or several variables :param name: string or list of string with the parameter names to query :return: parameter(s) name(s) """ is_iterable = isinstance( name, (list,tuple) ) if is_iterable: return [self.get_calibration(n) for n in name] name = str(name) # get symbol group containing name group = [sg for sg in self.symbols if name in self.symbols[sg]] if len(group)==0: raise Exception('Symbol {} is not defined for this model'.format(name)) assert(len(group)==1) group = group[0] ind = self.symbols[group].index(name) return self.calibration[group][ind]
@property @memoized
[docs] def x_bounds(self): model = self.model states = model.symbols_s['states'] parameters = model.parameters from dolo.compiler.function_compiler import compile_multiargument_function [lower_bounds_symbolic, upper_bounds_symbolic] = self.model.get_complementarities()['arbitrage'] lb = compile_multiargument_function( lower_bounds_symbolic, [states], ['s'], parameters, fname='lb') ub = compile_multiargument_function( upper_bounds_symbolic, [states], ['s'], parameters, fname='ub' ) return [lb,ub]
if __name__ == '__main__': from dolo import * import numpy gm = yaml_import('examples/global_models/rbc.yaml', compiler='numpy') # print(model.__class__) # gm = GModel(model, compiler='numexpr') # # gm = GModel(model, compiler='theano') # gm = GModel(model) ss = gm.calibration['states'] xx = gm.calibration['controls'] aa = gm.calibration['auxiliary'] p = gm.calibration['parameters'] ee = numpy.array([0],dtype=numpy.double) N = 1000000 ss = numpy.ascontiguousarray( numpy.tile(numpy.atleast_2d(ss).T, (1,N)) ) xx = numpy.ascontiguousarray( numpy.tile(numpy.atleast_2d(xx).T, (1,N)) ) aa = numpy.ascontiguousarray( numpy.tile(numpy.atleast_2d(aa).T, (1,N)) ) ee = numpy.ascontiguousarray( numpy.tile(numpy.atleast_2d(ee).T, (1,N)) ) print(ss.shape) g = gm.functions['transition'] f = gm.functions['arbitrage'] import time tmp = g(ss,xx,aa,ee,p) t1 = time.time() for i in range(50): tmp = g(ss,xx,aa,ee,p) t2 = time.time() print(tmp.shape) tmp = f(ss,xx,aa,ss,xx,aa,p) t3 = time.time() for i in range(50): tmp = f(ss,xx,aa,ss,xx,aa,p) t4 = time.time() print('first {}'.format(t2-t1)) print('second {}'.format(t4-t3)) print(gm)