Skip to content

Commit 9cf3364

Browse files
committed
Worked hard to figure out timing of variables in computation of derivatives. Can now pass timing consumption at instantiation time
1 parent 810fcc4 commit 9cf3364

File tree

4 files changed

+119
-29
lines changed

4 files changed

+119
-29
lines changed

pymaclab/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def db_graph(dbase,tseries):
4646
P.show()
4747

4848
def newMOD(txtfile=None,dbase=None,initlev=3,mesg=False,ncpus=ncpus,\
49-
mk_hessian=True,use_focs=False,ssidic=None,sstate=None):
49+
mk_hessian=True,use_focs=False,ssidic=None,sstate=None,vtiming={'exo':[-1,0],'endo':[-1,0],'con':[0,1]}):
5050
'''
5151
Model's second intialisation method called by newMOD() function call. The model's
5252
__init__() method only creates the instance and adds information, but does no
@@ -59,7 +59,7 @@ def newMOD(txtfile=None,dbase=None,initlev=3,mesg=False,ncpus=ncpus,\
5959
'''
6060
modobj = macrolab.DSGEmodel(txtfile,dbase=dbase,initlev=initlev,mesg=mesg,ncpus=ncpus,\
6161
mk_hessian=mk_hessian,use_focs=use_focs,\
62-
ssidic=ssidic,sstate=sstate)
62+
ssidic=ssidic,sstate=sstate,vtiming=vtiming)
6363
modobj.init1()
6464
modobj.init1a()
6565
modobj.init1b()

pymaclab/dsge/macrolab.py

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,13 @@ class DSGEmodel(object):
123123
jobserver = pp.Server(ppservers=ppservers)
124124
# Initializes the absolute basics, errors difficult to occur
125125
def __init__(self,ffile=None,dbase=None,initlev=2,mesg=False,ncpus='auto',mk_hessian=True,\
126-
use_focs=False,ssidic=None,sstate=None):
126+
use_focs=False,ssidic=None,sstate=None,vtiming={'exo':[-1,0],'endo':[-1,0],'con':[0,1]}):
127127
# Make sure the jobserver has done his global jobs each time you instantiate a new instance
128128
jobserver.wait()
129129
if sstate != None:
130130
self._sstate = deepcopy(sstate)
131131
self._initlev = initlev #TODO: remove this as an option
132+
self._vtiming = vtiming
132133
self._mesg = mesg
133134
self._ncpus = ncpus
134135
self._mk_hessian = mk_hessian
@@ -290,10 +291,11 @@ def init1c(self,no_wrap=False):
290291
self = populate_model_stage_one_bb(self,secs)
291292

292293
if not no_wrap:
293-
# Wrap foceqs
294-
self.updaters.foceqs = listwrap(self,'self.foceqs',initlev)
295-
# Wrap foceqs
296-
self.updaters_queued.foceqs = listwrap(self,'self.foceqs',initlev)
294+
if 'foceqs' in dir(self):
295+
# Wrap foceqs
296+
self.updaters.foceqs = listwrap(self,'self.foceqs',initlev)
297+
# Wrap foceqs
298+
self.updaters_queued.foceqs = listwrap(self,'self.foceqs',initlev)
297299

298300
# Allow for numerical SS to be calculated using only FOCs
299301
if self._use_focs and self._ssidic != None:
@@ -568,7 +570,7 @@ def init5(self,update=False):
568570
self.modsolvers = MODsolvers()
569571
######################## LINEAR METHODS !!! ############################
570572
# see if there are any log-linearized equations
571-
if any([False if 'None' in x else True for x in secs['modeq'][0]]):
573+
if all([False if 'None' in x else True for x in secs['modeq'][0]]):
572574
from solvers.modsolvers import PyUhlig, MatUhlig, MatKlein, MatKleinD, ForKlein
573575
if mesg: print "INIT: Computing DSGE model's log-linearized solution using Uhlig's Toolbox..."
574576

@@ -613,7 +615,7 @@ def init5(self,update=False):
613615
sess1)
614616
self.modsolvers.forklein = ForKlein(intup)
615617
################## 1ST-ORDER NON-LINEAR METHODS !!! ##################
616-
if any([False if 'None' in x else True for x in secs['focs'][0]]):
618+
if all([False if 'None' in x else True for x in secs['focs'][0]]):
617619
from solvers.modsolvers import (MatWood, ForKleinD)
618620

619621
if not update:
@@ -673,7 +675,7 @@ def init5(self,update=False):
673675
self.modsolvers.forkleind.B = self.jBB
674676

675677
################## 2ND-ORDER NON-LINEAR METHODS !!! ##################
676-
if any([False if 'None' in x else True for x in secs['vcvm'][0]]) and 'numh' in dir(self):
678+
if all([False if 'None' in x else True for x in secs['vcvm'][0]]) and 'numh' in dir(self):
677679
from solvers.modsolvers import (PyKlein2D, MatKlein2D)
678680
# Open the MatKlein2D object
679681
if 'nlsubsys' in dir(self):
@@ -1597,6 +1599,38 @@ def mkhes(jrows=jrows,jcols=jcols,trans_dic=None):
15971599

15981600
self.jAA = self.numj[:,:int(len(intup)/2)]
15991601
self.jBB = -self.numj[:,int(len(intup)/2):]
1602+
1603+
# Get rid of pointless keys in jdicc (and hdicc)
1604+
jdicc_copy = deepcopy(jdicc)
1605+
for keyo in jdicc_copy:
1606+
for keyo2 in jdicc_copy[keyo]:
1607+
if type(keyo2) == type(1): jdicc[keyo].pop(keyo2)
1608+
if mk_hessian:
1609+
hdicc_copy = deepcopy(hdicc)
1610+
if 'hdicc' in dir():
1611+
for keyo in hdicc_copy:
1612+
for keyo2 in hdicc_copy[keyo]:
1613+
if type(keyo2) == type(1): hdicc[keyo].pop(keyo2)
1614+
1615+
# Build string As and Bs
1616+
sAA = deepcopy(self.jAA.astype(str))
1617+
sBB = deepcopy(self.jBB.astype(str))
1618+
sAA = np.matrix(sAA,dtype=np.object_)
1619+
sBB = np.matrix(sBB,dtype=np.object_)
1620+
for elem in range(self.jAA.shape[0]):
1621+
for i1,elem2 in enumerate(exo_1+endo_1+con_1):
1622+
sAA[elem,i1] = jdicc[elem][elem2]
1623+
for i2,elem2 in enumerate(exo_0+endo_0+con_0):
1624+
if jdicc != '0':
1625+
sBB[elem,i2] = '-('+jdicc[elem][elem2]+')'
1626+
else:
1627+
sBB[elem,i2] = jdicc[elem][elem2]
1628+
self.sAA = deepcopy(sAA)
1629+
self.sBB = deepcopy(sBB)
1630+
self.iA = deepcopy(exo_1+endo_1+con_1)
1631+
self.iB = deepcopy(exo_0+endo_0+con_0)
1632+
1633+
16001634
# The parallelized mkjahe version using parallel python
16011635

16021636
def mkjahepp(self):
@@ -1959,6 +1993,36 @@ def mkjaheseq(lcount,func2,jcols,symdic,tmpli,paramdic,sstate,evaldic,suba_dic,m
19591993

19601994
self.jAA = self.numj[:,:int(len(intup)/2)]
19611995
self.jBB = -self.numj[:,int(len(intup)/2):]
1996+
1997+
# Get rid of pointless keys in jdicc (and hdicc)
1998+
jdicc_copy = deepcopy(jdicc)
1999+
for keyo in jdicc_copy:
2000+
for keyo2 in jdicc_copy[keyo]:
2001+
if type(keyo2) == type(1): jdicc[keyo].pop(keyo2)
2002+
if mk_hessian:
2003+
hdicc_copy = deepcopy(hdicc)
2004+
if 'hdicc' in dir():
2005+
for keyo in hdicc_copy:
2006+
for keyo2 in hdicc_copy[keyo]:
2007+
if type(keyo2) == type(1): hdicc[keyo].pop(keyo2)
2008+
2009+
# Build string As and Bs
2010+
sAA = deepcopy(self.jAA.astype(str))
2011+
sBB = deepcopy(self.jBB.astype(str))
2012+
sAA = np.matrix(sAA,dtype=np.object_)
2013+
sBB = np.matrix(sBB,dtype=np.object_)
2014+
for elem in range(self.jAA.shape[0]):
2015+
for i1,elem2 in enumerate(exo_1+endo_1+con_1):
2016+
sAA[elem,i1] = jdicc[elem][elem2]
2017+
for i2,elem2 in enumerate(exo_0+endo_0+con_0):
2018+
if jdicc != '0':
2019+
sBB[elem,i2] = '-('+jdicc[elem][elem2]+')'
2020+
else:
2021+
sBB[elem,i2] = jdicc[elem][elem2]
2022+
self.sAA = deepcopy(sAA)
2023+
self.sBB = deepcopy(sBB)
2024+
self.iA = deepcopy(exo_1+endo_1+con_1)
2025+
self.iB = deepcopy(exo_0+endo_0+con_0)
19622026

19632027
# The numerical (Paul Klein) Jacobian and Hessian computation method (uses matlab)
19642028
def mkjahenmat(self,msess=sess1):

pymaclab/dsge/parsers/_dsgeparser.py

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import re
1212
from copy import deepcopy
1313
import numpy.matlib as mat
14+
import numpy as np
1415
import sys
1516
import os
1617
# This used to import sympycore, but should now also work with sympy
@@ -23,6 +24,9 @@ def populate_model_stage_one(self, secs):
2324
1st stage population of DSGE model. Does not need Steady State.
2425
"""
2526

27+
# Establish the timing convention of variables in the model file
28+
self = def_timing(self,**self._vtiming)
29+
2630
# This is a special dictionary which can be handed over to the template engines (i.e. Jinja2)
2731
if 'template_paramdic' not in dir(self): self.template_paramdic = {}
2832

@@ -284,7 +288,7 @@ def populate_model_stage_one(self, secs):
284288

285289

286290
############# BELOW HERE IS ALL FOR 2ND STAGE ###########
287-
def def_timing(self,endo=[-1,0],exo=[-1,0],con=[0,1]):
291+
def def_timing(self,exo=[-1,0],endo=[-1,0],con=[0,1]):
288292
'''
289293
A small method which can be used in order to set the timings in stone.
290294
This will then be used in other parts of the code, also in macrolab package
@@ -480,7 +484,7 @@ def mkaug1(self, insys,othersys):
480484
# Now change the system to include possible augmented variables
481485
endo_r = filter(lambda x: x[1] != endotime, spvdic2['endo'])
482486
if endo_r:
483-
endo_r = [[x[0],[abs(x[1][0]+1),x[1][1]]] for x in endo_r ]
487+
endo_r = [[x[0],[abs(x[1][0])-abs(endotime[0]),x[1][1]-abs(endotime[1])]] for x in endo_r ]
484488
# Create lags and forwards equations
485489
for vari in endo_r:
486490
for lag in range(abs(vari[1][0])):
@@ -503,7 +507,7 @@ def mkaug1(self, insys,othersys):
503507
list_tmp1.append(vari[0][0].split('(')[0]+'_F'+tind+'(t)'+' - '+'E(t)|'+vari[0][0].split('(')[0]+'_F'+tind1+'(t+1)')
504508
exo_r = filter(lambda x: x[1] != exotime, spvdic2['exo'])
505509
if exo_r:
506-
exo_r = [[x[0],[abs(x[1][0])-1,x[1][1]]] for x in exo_r ]
510+
exo_r = [[x[0],[abs(x[1][0])-abs(exotime[0]),x[1][1]-abs(exotime[1])]] for x in exo_r ]
507511
# Create lags and forwards equations
508512
for vari in exo_r:
509513
for lag in range(abs(vari[1][0])):
@@ -527,7 +531,7 @@ def mkaug1(self, insys,othersys):
527531
list_tmp1.append(vari[0][0].split('(')[0]+'_F'+tind+'(t)'+' - '+'E(t)|'+vari[0][0].split('(')[0]+'_F'+tind1+'(t+1)')
528532
con_r = filter(lambda x: x[1] != contime, spvdic2['con'])
529533
if con_r:
530-
con_r = [[x[0],[abs(x[1][0]),x[1][1]-1]] for x in con_r ]
534+
con_r = [[x[0],[abs(x[1][0])-abs(contime[0]),x[1][1]-abs(contime[1])]] for x in con_r ]
531535
# Create lags and forwards equations
532536
for vari in con_r:
533537
for lag in range(abs(vari[1][0])):
@@ -739,7 +743,7 @@ def mkaug2(self, insys):
739743
# Now change the system to include possible augmented variables
740744
endo_r = filter(lambda x: x[1] != endotime, spvdic2['endo'])
741745
if endo_r:
742-
endo_r = [[x[0],[abs(x[1][0]+1),x[1][1]]] for x in endo_r ]
746+
endo_r = [[x[0],[abs(x[1][0])-abs(endotime[0]),x[1][1]-abs(endotime[1])]] for x in endo_r ]
743747
# Create lags and forwards equations
744748
for vari in endo_r:
745749
for lag in range(abs(vari[1][0])):
@@ -762,7 +766,7 @@ def mkaug2(self, insys):
762766
list_tmp1.append(vari[0][0].split('(')[0]+'_F'+tind+'(t)'+' - '+'E(t)|'+vari[0][0].split('(')[0]+'_F'+tind1+'(t+1)')
763767
exo_r = filter(lambda x: x[1] != exotime, spvdic2['exo'])
764768
if exo_r:
765-
exo_r = [[x[0],[abs(x[1][0])-1,x[1][1]]] for x in exo_r ]
769+
exo_r = [[x[0],[abs(x[1][0])-abs(exotime[0]),x[1][1]-abs(exotime[1])]] for x in exo_r ]
766770
# Create lags and forwards equations
767771
for vari in exo_r:
768772
for lag in range(abs(vari[1][0])):
@@ -786,7 +790,7 @@ def mkaug2(self, insys):
786790
list_tmp1.append(vari[0][0].split('(')[0]+'_F'+tind+'(t)'+' - '+'E(t)|'+vari[0][0].split('(')[0]+'_F'+tind1+'(t+1)')
787791
con_r = filter(lambda x: x[1] != contime, spvdic2['con'])
788792
if con_r:
789-
con_r = [[x[0],[abs(x[1][0]),x[1][1]-1]] for x in con_r ]
793+
con_r = [[x[0],[abs(x[1][0])-abs(contime[0]),x[1][1]-abs(contime[1])]] for x in con_r ]
790794
# Create lags and forwards equations
791795
for vari in con_r:
792796
for lag in range(abs(vari[1][0])):
@@ -1702,8 +1706,6 @@ def mknonlinsys(self, secs):
17021706
Create Non-Linear FOC System
17031707
"""
17041708
list_tmp1 = deepcopy(self.foceqs2)
1705-
# Establish the timing convention of variables in the model file
1706-
self = def_timing(self)
17071709
self, list_tmp1 = mkaug2(self, list_tmp1)
17081710

17091711
if any([False if 'None' in x else True for x in secs['vsfocs'][0]]):
@@ -1763,7 +1765,7 @@ def mknonlinsys(self, secs):
17631765
self.nlsys_list = list_tmp1
17641766
return self
17651767

1766-
def mkloglinsys2(inlist):
1768+
def mkloglinsys2(self, inlist):
17671769
"""
17681770
This function simply takes the left-hand side
17691771
of each equation and takes it over to the
@@ -1866,6 +1868,14 @@ def mkloglinsys2(inlist):
18661868
self.nlsys_list = deepcopy(list_tmp1)
18671869
return list_tmp1
18681870

1871+
def subs_in_loglinsys(self):
1872+
list_tmp1 = deepcopy(self.llsys_list)
1873+
subsdic = deepcopy(self.nlsubs)
1874+
for i1,eqo in enumerate(list_tmp1):
1875+
while "@" in list_tmp1[i1]:
1876+
for keyo in subsdic.keys():
1877+
if keyo in list_tmp1[i1]: list_tmp1[i1] = list_tmp1[i1].replace(keyo,subsdic[keyo])
1878+
return list_tmp1
18691879

18701880
# Creates the log-linear system
18711881
def mkloglinsys1(secs):
@@ -1944,13 +1954,19 @@ def mkeqtype(self):
19441954

19451955
# Make symbolic system and numeric as well
19461956
def mksymsys(self):
1957+
_mreg = 'E{1,1}[^(]'
1958+
mreg = re.compile(_mreg)
19471959
func = []
19481960
subli = []
19491961
patup = ('{-10,10}|None','all','{-10,10}')
19501962
for x in self.sstate.keys()+self.paramdic.keys():
19511963
locals()[x] = eval("SP.Symbol('"+x+"')")
19521964
for y in self.llsys_list:
19531965
str_tmp = y[:]
1966+
while 'EXP(' in str_tmp:
1967+
str_tmp = str_tmp.replace('EXP(','SP.exp(')
1968+
while 'LOG(' in str_tmp:
1969+
str_tmp = str_tmp.replace('LOG(','SP.log(')
19541970
vali = [x[0] for x in self.vreg(patup,y,True,'min')]
19551971
vali2 = [[x,'sub'+str(u)] for x,u in zip(vali,range(0,len(vali),1))]
19561972
vali3 = [(x[0],x[3]) for x in self.vreg(patup,str_tmp,True,'max')]
@@ -1978,7 +1994,16 @@ def mksymsys(self):
19781994
tmpdic={}
19791995
for y in x.keys():
19801996
# tmpdic[y] = eval(x[y].tostr())
1981-
tmpdic[y] = eval(str(x[y]))
1997+
str_tmp2 = str(x[y])
1998+
while mreg.search(str_tmp2):
1999+
maout = [por for por in mreg.finditer(str_tmp2)]
2000+
maout.reverse()
2001+
for mato in maout:
2002+
starts = mato.span()[0]
2003+
ends = mato.span()[1]
2004+
expo = mato.group()
2005+
str_tmp2 = str_tmp2[:starts]+'np.exp(1)'+str_tmp2[ends-1:]
2006+
tmpdic[y] = eval(str_tmp2)
19822007

19832008
diffli2.append(tmpdic)
19842009
self.diffli2 = diffli2
@@ -2112,12 +2137,11 @@ def populate_model_stage_one_bb(self, secs):
21122137
self.foceqs2 = deepcopy(self.foceqs)
21132138
# Also create a steady state version
21142139
self = mk_steady2(self)
2140+
# Also save a copy of the focs with replaced substitutions
2141+
self.template_paramdic['focs_list2'] = deepcopy(self.foceqs2)
21152142
else:
21162143
# Save for template instantiation
21172144
self.template_paramdic['focs_list'] = False
2118-
2119-
# Also save a copy of the focs with replaced substitutions
2120-
self.template_paramdic['focs_list2'] = deepcopy(self.foceqs2)
21212145
return self
21222146

21232147

@@ -2126,13 +2150,14 @@ def populate_model_stage_two(self, secs):
21262150
2nd stage population of DSGE model. Needs Steady State.
21272151
"""
21282152
# Creates nonlinear foc system
2129-
if any([False if 'None' in x else True for x in secs['focs'][0]]):
2153+
if all([False if 'None' in x else True for x in secs['focs'][0]]):
21302154
self = mknonlinsys(self, secs)
21312155

21322156
# Creates loglinear system
2133-
if any([False if 'None' in x else True for x in secs['modeq'][0]]):
2157+
if all([False if 'None' in x else True for x in secs['modeq'][0]]):
21342158
llsys_list = mkloglinsys1(secs)
2135-
self.llsys_list = mkloglinsys2(llsys_list)
2159+
self.llsys_list = mkloglinsys2(self,llsys_list)
2160+
self.llsys_list = subs_in_loglinsys(self)
21362161
# Save for template instantiation
21372162
self.template_paramdic['llsys_list'] = deepcopy(self.llsys_list)
21382163
self = mksymsys(self) # creates symbolic and numerical system
@@ -2142,7 +2167,7 @@ def populate_model_stage_two(self, secs):
21422167
self.template_paramdic['llsys_list'] = False
21432168

21442169
# Creates variance/covariance
2145-
if any([False if 'None' in x else True for x in secs['vcvm'][0]]) and\
2170+
if all([False if 'None' in x else True for x in secs['vcvm'][0]]) and\
21462171
'sstate' in dir(self):
21472172
self.sigma = mksigmat(self, secs)
21482173
# Save for template instantiation

pymaclab/dsge/updaters/queued.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,8 @@ def __init__(self,other=None):
354354
# The paramdic
355355
self.paramdic = deepcopy(other.updaters_queued.paramdic.wrapobj)
356356
# The foceqs
357-
self.foceqs = deepcopy(other.updaters_queued.foceqs.wrapobj)
357+
if 'foceqs' in dir(other):
358+
self.foceqs = deepcopy(other.updaters_queued.foceqs.wrapobj)
358359
# The manss_sys
359360
if 'manss_sys' in dir(other.updaters_queued):
360361
self.manss_sys = deepcopy(other.updaters_queued.manss_sys.wrapobj)

0 commit comments

Comments
 (0)