Ejemplo n.º 1
0
    def get_diffmodel(self):
        ''' Returns a model which calculates the partial derivatives of a model'''
        def makelag(var):
            vterm = udtryk_parse(var)[0]
            if vterm.lag:
                if vterm.lag[0] == '-':
                    return f'{vterm.var}___lag___{vterm.lag[1:]}'
                elif vterm.lag[0] == '+':
                    return f'{vterm.var}___lead___{vterm.lag[1:]}'
                else:
                    return f'{vterm.var}___per___{vterm.lag}'
            else:
                return f'{vterm.var}___lag___0'

        with ttimer(
                'Generates a model which calculatews the derivatives for a model',
                self.timeit):
            out = '\n'.join([
                f'{lhsvar}__p__{makelag(rhsvar)} = {self.diffendocur[lhsvar][rhsvar]}  '
                for lhsvar in sorted(self.diffendocur)
                for rhsvar in sorted(self.diffendocur[lhsvar])
            ])
            dmodel = self.newmodel(out,
                                   funks=self.mmodel.funks,
                                   straight=True,
                                   modelname=self.mmodel.name +
                                   ' Derivatives ' + ' no lags and leads' if
                                   self.onlyendocur else ' all lags and leads')
        return dmodel
Ejemplo n.º 2
0
 def get_diff_values_all(self, periode=None, df=None, asdf=False):
     ''' stuff the values of derivatives into nested dic '''
     dmelt = self.get_diff_melted_var(periode=periode, df=df)
     with ttimer('Prepare numpy input to sparse matrix', self.timeit):
         self.diffvalues = defaultdict(lambda: defaultdict(dict))
         grouped = dmelt.groupby(by=['var', 'pvar', 'lag'])
         for (var, pvar, lag), df in grouped:
             res = df.pivot(index='pvar', columns='dates', values='value')
             pvar_name = tovarlag(pvar, int(lag))
             #reakpoint()
             # #csc_matrix((data, (row_ind, col_ind)), [shape=(M, N)])
             # print(f'endo:{endo} ,date:{date}, lag:{lag}, \n df')
             self.diffvalues[var][pvar_name] = res
     return self.diffvalues
Ejemplo n.º 3
0
    def get_diff_mat_all_1per(self, periode=None, df=None, asdf=False):
        dmelt = self.get_diff_melted_var(periode=periode, df=df)
        with ttimer('Prepare numpy input to sparse matrix', self.timeit):
            outdic = defaultdict(lambda: defaultdict(dict))
            grouped = dmelt.groupby(by=['pvar_endo', 'dates', 'lag'])
            for (endo, date, lag), df in grouped:
                values = df.value.values
                # breakpoint()
                # #csc_matrix((data, (row_ind, col_ind)), [shape=(M, N)])
                # print(f'endo:{endo} ,date:{date}, lag:{lag}, \n df')
                if endo:
                    indicies = (df.var_plac.values, df.pvar_plac.values)
                    this = sp.sparse.csc_matrix(
                        (values, indicies),
                        shape=(len(self.declared_endo_list),
                               len(self.declared_endo_list)))

                    if asdf:
                        outdic[date]['endo'][f'lag={lag}'] = pd.DataFrame(
                            this.toarray(),
                            columns=self.declared_endo_list,
                            index=self.declared_endo_list)
                    else:
                        outdic[date]['endo'][f'lag={lag}'] = this
                else:
                    indicies = (df.var_plac.values, df.pvar_exo_plac.values)
                    this = sp.sparse.csc_matrix(
                        (values, indicies),
                        shape=(len(self.endovar), len(self.exovar)))
                    if asdf:
                        outdic[date]['exo'][f'lag={lag}'] = pd.DataFrame(
                            this.toarray(),
                            columns=self.exovar,
                            index=self.declared_endo_list)
                    else:
                        outdic[date]['exo'][f'lag={lag}'] = this

        return outdic
Ejemplo n.º 4
0
    def get_diff_melted(self, periode=None, df=None):
        '''returns a tall matrix with all values to construct jacobimatrix(es)  '''
        def get_lagnr(l):
            ''' extract lag/lead from variable name and returns a signed lag (leads are positive'''
            #breakpoint()
            return int('-' * (l.split('___')[0] == 'LAG') + l.split('___')[1])

        def get_elm(vartuples, i):
            ''' returns a list of lags  list of tupels '''
            return [v[i] for v in vartuples]

        _per_first = periode if type(periode) != type(
            None) else self.mmodel.current_per

        if hasattr(_per_first, '__iter__'):
            _per = _per_first
        else:
            _per = [_per_first]

        _df = self.df if type(df) != pd.DataFrame else df
        _df = _df.pipe(
            lambda df0: df0.rename(columns={c: c.upper()
                                            for c in df0.columns}))

        self.diff_model.current_per = _per
        # breakpoint()
        with ttimer('calculate derivatives', self.timeit):
            self.difres = self.diff_model.res(
                _df,
                silent=self.silent,
                stats=0,
                ljit=self.ljit,
                chunk=self.nchunk).loc[_per, self.diff_model.endogene]
        with ttimer('Prepare wide input to sparse matrix', self.timeit):

            cname = namedtuple('cname', 'var,pvar,lag')
            self.coltup = [
                cname(
                    i.rsplit('__P__', 1)[0],
                    i.rsplit('__P__', 1)[1].split('___', 1)[0],
                    get_lagnr(i.rsplit('__P__', 1)[1].split('___', 1)[1]))
                for i in self.difres.columns
            ]
            # breakpoint()
            self.coltupnum = [
                (self.placdic[var],
                 self.placdic[pvar + '___RES' if
                              (pvar +
                               '___RES' in self.mmodel.endogene) else pvar],
                 lag) for var, pvar, lag in self.coltup
            ]

            self.difres.columns = self.coltupnum
            self.numbers = [i for i, n in enumerate(self.difres.index)]
            self.maxnumber = max(self.numbers)
            self.numbers_to_date = {
                i: n
                for i, n in enumerate(self.difres.index)
            }
            self.nvar = len(self.endovar)
            self.difres.loc[:, 'number'] = self.numbers

        with ttimer('melt the wide input to sparse matrix', self.timeit):
            dmelt = self.difres.melt(id_vars='number')
            dmelt.loc[:, 'value'] = dmelt['value'].astype('float')

        with ttimer('assign tall input to sparse matrix', self.timeit):
            # breakpoint()
            dmelt = dmelt.assign(var=lambda x: get_elm(x.variable, 0),
                                 pvar=lambda x: get_elm(x.variable, 1),
                                 lag=lambda x: get_elm(x.variable, 2))
        return dmelt
Ejemplo n.º 5
0
    def modeldiff(self):
        ''' Differentiate relations for self.enovar with respect to endogeneous variable 
        The result is placed in a dictory in the model instanse: model.diffendocur
        '''
        def numdif(model, v, rhv, delta=0.005, silent=True):
            #        print('**',model.allvar[v]['terms']['frml'])
            def tout(t):
                if t.lag:
                    return f'{t.var}({t.lag})'
                return t.op + t.number + t.var

            # breakpoint()
            nt = model.allvar[v]['terms']
            assignpos = nt.index(model.aequalterm)  # find the position of =
            rhsterms = nt[assignpos + 1:-1]
            vterm = udtryk_parse(rhv)[0]
            plusterm = udtryk_parse(f'({rhv}+{delta/2})', funks=model.funks)
            minusterm = udtryk_parse(f'({rhv}-{delta/2})', funks=model.funks)
            plus = itertools.chain.from_iterable(
                [plusterm if t == vterm else [t] for t in rhsterms])
            minus = itertools.chain.from_iterable(
                [minusterm if t == vterm else [t] for t in rhsterms])
            eplus = f'({"".join(tout(t) for t in plus)})'
            eminus = f'({"".join(tout(t) for t in minus)})'
            expression = f'({eplus}-{eminus})/{delta}'
            if (not silent) and False:
                print(expression)
            return expression

        def findallvar(model, v):
            '''Finds all endogenous variables which is on the right side of = in the expresion for variable v
            lagged variables are included if self.onlyendocur == False '''
            # print(v)
            terms = self.mmodel.allvar[v]['terms'][model.
                                                   allvar[v]['assigpos']:-1]
            if self.endoandexo:
                rhsvar = {
                    (nt.var + ('(' + nt.lag + ')' if nt.lag != '' else ''))
                    for nt in terms if nt.var
                }
                rhsvar = {tovarlag(nt.var, nt.lag) for nt in terms if nt.var}
            else:
                if self.onlyendocur:
                    rhsvar = {
                        tovarlag(nt.var, nt.lag)
                        for nt in terms if nt.var and nt.lag == ''
                        and nt.var in self.declared_endo_set
                    }

                else:
                    rhsvar = {
                        tovarlag(nt.var, nt.lag)
                        for nt in terms
                        if nt.var and nt.var in self.declared_endo_set
                    }
            var2 = sorted(list(rhsvar))
            return var2

        with ttimer('Find espressions for partial derivatives', self.timeit):
            clash = {var: Symbol(var) for var in self.mmodel.allvar.keys()}
            diffendocur = {
            }  #defaultdict(defaultdict) #here we wanmt to store the derivativs
            i = 0
            for nvar, v in enumerate(self.endovar):
                if nvar >= self.maxdif:
                    break
                if not self.silent and 0:
                    print(f'Now differentiating {v} {nvar}')

                endocur = findallvar(self.mmodel, v)

                diffendocur[v] = {}
                t = self.mmodel.allvar[v]['frml'].upper()
                a, fr, n, udtryk = split_frml(t)
                udtryk = udtryk
                udtryk = re.sub(
                    r'LOG\(', 'log(',
                    udtryk)  # sympy uses lover case for log and exp
                udtryk = re.sub(r'EXP\(', 'exp(', udtryk)
                lhs, rhs = udtryk.split('=', 1)
                try:
                    if not self.forcenum:
                        # kat=sympify(rhs[0:-1], md._clash) # we take the the $ out _clash1 makes I is not taken as imiganary
                        kat = sympify(
                            rhs[0:-1], clash
                        )  # we take the the $ out _clash1 makes I is not taken as imiganary
                except:
                    # breakpoint()
                    print('* Problem sympify ', lhs, '=', rhs[0:-1])
                for rhv in endocur:
                    try:
                        # breakpoint()
                        if not self.forcenum:
                            # ud=str(kat.diff(sympify(rhv,md._clash)))
                            try:
                                ud = str(kat.diff(sympify(rhv, clash)))
                                ud = re.sub(
                                    pt.namepat + r'(?:(\()([0-9])(\)))',
                                    r'\g<1>\g<2>+\g<3>\g<4>', ud)
                            except:
                                ud = numdif(self.mmodel,
                                            v,
                                            rhv,
                                            silent=self.silent)

                        if self.forcenum or 'Derivative(' in ud:
                            ud = numdif(self.mmodel,
                                        v,
                                        rhv,
                                        silent=self.silent)
                            if not self.silent and 0: print('numdif of {rhv}')
                        diffendocur[v.upper()][rhv.upper()] = ud

                    except:
                        print('we have a serious problem deriving:', lhs, '|',
                              rhv, '\n', lhs, '=', rhs)
                        # breakpoint()

                    i += 1
        if not self.silent:
            print('Model                           :', self.mmodel.name)
            print('Number of endogeneus variables  :', len(diffendocur))
            print('Number of derivatives           :', i)
        return diffendocur