Skip to content

Commit bd3fa31

Browse files
committed
Cleaned up and refactored pymaclab_to_dynare++ translation and solution codes
1 parent bfde842 commit bd3fa31

File tree

12 files changed

+1267
-1637
lines changed

12 files changed

+1267
-1637
lines changed

pymaclab.wpu

Lines changed: 1030 additions & 1535 deletions
Large diffs are not rendered by default.

pymaclab/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
ncpus = jobserver.get_ncpus()
3131
del jobserver
3232
del ppservers
33-
print "PyMacLab started with parallel jobserver using "+str(ncpus)+" cores..."
33+
print "PyMacLab library loaded with parallel jobserver using "+str(ncpus)+" cores..."
3434

3535

3636
# Some helper functions

pymaclab/dsge/macrolab.py

Lines changed: 39 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class which was supposed to be an advanced data carrier class to be passed to th
1515
import copy
1616
from copy import deepcopy
1717
import os
18+
import subprocess
1819
import sys
1920
import re
2021
from helpers import now_is
@@ -31,6 +32,15 @@ class which was supposed to be an advanced data carrier class to be passed to th
3132
# Import PP, now comes supplied and installed with pymaclab
3233
import pp
3334

35+
# Check if dynare++ is installed and in your path
36+
dynare_flag = False
37+
try:
38+
dynret = subprocess.call('dynare++',stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
39+
dynare_flag = True
40+
print 'Dynare++ found on your system path, accessible from PyMacLab...'
41+
except:
42+
dynare_flag = False
43+
3444
#NOTE: Imports from the refactor
3545
from pymaclab.filters._hpfilter import hpfilter
3646
from pymaclab.filters._bkfilter import bkfilter
@@ -42,6 +52,7 @@ class which was supposed to be an advanced data carrier class to be passed to th
4252
from updaters.one_off import Updaters, dicwrap, dicwrap_deep, listwrap, matwrap
4353
from updaters.queued import Updaters_Queued, dicwrap_queued, dicwrap_deep_queued, listwrap_queued,\
4454
matwrap_queued, Process_Queue, queue
55+
from pymaclab.dsge.translators.translators import Translators
4556

4657
#Define a list of the Greek Alphabet for Latex
4758
greek_alph = ['alpha','beta','gamma','delta','epsilon',
@@ -75,23 +86,26 @@ class which was supposed to be an advanced data carrier class to be passed to th
7586
# Open mlab session
7687
if use_matlab:
7788
sess1 = mlabraw.open('matlab - nojvm -nosplash')
89+
90+
# Empty locdic for the locate helper function
91+
locdic = {}
7892

7993
# Shell class for derivatives branch
8094
class Derivatives(object):
8195
pass
8296

83-
# Shell class for derivatives branch
97+
8498
class Inits(object):
8599
'''
86-
This is the factored-out macrolab DSGEmodel Initialisation class. This used to be part of the DSGEmodel
100+
This is the factored-out macrolab DSGEmodel Initialisation class. This is used to be part of the DSGEmodel
87101
class itself in the form of methods, but has been factored out into a separate class which takes a newly
88102
instantiated DSGEmodel instance as and argument. It then possess several init methods which "work on the
89-
instance" and produce desired attributes
103+
instance" and produce desired attributes to different depths of solution levels.
90104
91105
.. note::
92106
93-
Notice that the various init method, i.e. init1, init1a, etc. are not called here, but they are called externally in the
94-
pymaclab package when instantiating a new DSGE model using pymaclab.newMOD().
107+
Notice that the various init method, i.e. init1, init1a, etc. are not called here, but they are called
108+
externally in the pymaclab package when instantiating a new DSGE model using pymaclab.newMOD().
95109
96110
:param other: The DSGEmodel instance to be passed to the Inits instance
97111
:type other: DSGEmodel
@@ -304,7 +318,7 @@ def init2(self):
304318
alldic = {}
305319
alldic.update(other.paramdic)
306320
intup = (other.manss_sys,alldic)
307-
other.sssolvers.manss = ManualSteadyState(intup,other=other)
321+
other.sssolvers.manss = ManualSteadyState(intup,other=other)
308322
##################################### FULL PARSING AND UPDATER WRAPPING DONE #############################
309323
def init3(self):
310324
'''
@@ -510,6 +524,9 @@ def init4(self,no_wrap=False):
510524
# We can also already compute a dictionary holding all the vars w.r.t which derivatives will be taken
511525
# This will attach a dictionary to the model instance called self.differvardic
512526
other.def_differ_periods()
527+
# Open the translators branch on the DSGE model instance
528+
# This should be done here, so that the passed "other" model instance has the translator branch
529+
other.translators = Translators(other=other)
513530

514531
if not no_wrap:
515532
# Need to wrap variance covariance matrix here
@@ -542,8 +559,13 @@ def init5(self,update=False):
542559
#TODO: delay above and only import if needed
543560
from solvers.modsolvers import MODsolvers
544561
# Open the model solution tree branch
545-
other.modsolvers = MODsolvers()
546-
######################## LINEAR METHODS !!! ############################
562+
other.modsolvers = MODsolvers()
563+
################################### DYNARE++ ####################################
564+
# Open the dynare branch if dynare++ is installed on the system and in your PATH
565+
if dynare_flag:
566+
from solvers.modsolvers import Dynarepp
567+
other.modsolvers.dynarepp = Dynarepp({'_other':other,'_mesg':other._mesg})
568+
############################# LINEAR METHODS !!! ################################
547569
# see if there are any log-linearized equations
548570
if all([False if 'None' in x else True for x in secs['modeq'][0]]):
549571
from solvers.modsolvers import PyUhlig, MatUhlig, MatKlein, MatKleinD, ForKlein
@@ -693,12 +715,10 @@ def init_out(self):
693715
694716
'''
695717
other = self._other
696-
initlev = other._initlev
718+
initlev = other._initlev
697719
# Make sure the jobserver has done his jobs
698720
jobserver.wait()
699721

700-
# Empty locdic for the locate helper function
701-
locdic = {}
702722

703723
##################THE DSGE MODEL CLASS (WORKS)#####################
704724
class DSGEmodel(object):
@@ -745,8 +765,6 @@ class DSGEmodel(object):
745765
# Initializes the absolute basics, errors difficult to occur
746766
def __init__(self,ffile=None,dbase=None,initlev=2,mesg=False,ncpus='auto',mk_hessian=True,\
747767
use_focs=False,ssidic=None,sstate=None,vtiming={'exo':[-1,0],'endo':[-1,0],'con':[0,1]}):
748-
# Open the inits branch
749-
self.inits = Inits(other=self)
750768
# Make sure the jobserver has done his global jobs each time you instantiate a new instance
751769
jobserver.wait()
752770
if sstate != None:
@@ -770,83 +788,9 @@ def __init__(self,ffile=None,dbase=None,initlev=2,mesg=False,ncpus='auto',mk_hes
770788
# Attach some model attributes
771789
self.modfile = ffile
772790
self.dbase = dbase
791+
# Open the inits branch at the end
792+
self.inits = Inits(other=self)
773793

774-
775-
def mk_dynare(self,order=1,centralize=False,fpath=None,focli=None):
776-
# Import the template and other stuff
777-
from pymaclab.modfiles.templates import mako_dynare_template
778-
from scipy import io
779-
from solvers.modsolvers import Dynare
780-
import tempfile
781-
import os
782-
import glob
783-
template_dic = deepcopy(self.template_paramdic)
784-
785-
# Render the template to be passed to dynare++
786-
tmp_dic = {}
787-
tmp_dic['focli'] = focli
788-
template_dic.update(tmp_dic)
789-
modstr = mako_dynare_template.render(**template_dic)
790-
791-
# If a filepath has been passed then just write the Dynare++ modfile, but no more!
792-
if fpath != None:
793-
filo = open(fpath,'w')
794-
filo.write(modstr)
795-
filo.flush()
796-
filo.close()
797-
return
798-
799-
filo = tempfile.NamedTemporaryFile()
800-
fname = filo.name
801-
fname2 = fname.split('/')[-1]
802-
'''
803-
filo2 = open(os.path.join(os.getcwd(),'test.mod'),'w')
804-
filo2.write(modstr)
805-
filo2.flush()
806-
filo2.close()
807-
'''
808-
filo.file.write(modstr)
809-
filo.file.flush()
810-
self.modsolvers.dynare = Dynare({})
811-
self.modsolvers.dynare.__setattr__('modfile',modstr)
812-
if not centralize:
813-
os.system('dynare++ --no-centralize --order '+str(order)+' '+filo.name)
814-
else:
815-
os.system('dynare++ --order '+str(order)+' '+filo.name)
816-
dynret = io.loadmat(os.path.join(os.getcwd(),filo.name.split('/')[-1]+'.mat'))
817-
# Check if solution has been computed and attache all solution matrices to dynare instance
818-
if dynret.has_key('dyn_g_1'):
819-
self.modsolvers.dynare.__init__(dynret)
820-
else:
821-
print "FAIL: Dynare could not determine solution."
822-
filo.close()
823-
# Delete all of the files
824-
for filor in glob.glob(fname2+'*.*'):
825-
os.remove(filor)
826-
827-
# Create some other objects on dynare branch
828-
self.modsolvers.dynare.sstate = {}
829-
self.modsolvers.dynare.dynorder = []
830-
self.modsolvers.dynare.dynsorder = []
831-
for i1,elem in enumerate(self.modsolvers.dynare.dyn_vars):
832-
self.modsolvers.dynare.dynorder.append(str(elem).strip()+'(t)')
833-
if str(elem).strip()+'_bar' in self.sstate.keys():
834-
self.modsolvers.dynare.sstate[str(elem).strip()+'_bar'] = self.modsolvers.dynare.dyn_ss[i1,0]
835-
for i1,elem in enumerate(self.modsolvers.dynare.dyn_state_vars):
836-
self.modsolvers.dynare.dynsorder.append(str(elem).strip()+'(t)')
837-
838-
# Create PP and FF matrix reflecting ordering of pymaclab
839-
P = np.matlib.zeros([self.nstat,self.nstat])
840-
F = np.matlib.zeros([self.ncon,self.nstat])
841-
listo = [x[0] for x in self.vdic['exo']]+[x[0] for x in self.vdic['endo']]
842-
for i1,elem in enumerate(listo):
843-
for i2,elem2 in enumerate(listo):
844-
P[i1,i2] = self.modsolvers.dynare.dyn_g_1[self.modsolvers.dynare.dynorder.index(elem),self.modsolvers.dynare.dynsorder.index(elem2)]
845-
for i1,elem in enumerate([x[0] for x in self.vdic['con']]):
846-
for i2,elem2 in enumerate(listo):
847-
F[i1,i2] = self.modsolvers.dynare.dyn_g_1[self.modsolvers.dynare.dynorder.index(elem),self.modsolvers.dynare.dynsorder.index(elem2)]
848-
self.modsolvers.dynare.PP = deepcopy(P)
849-
self.modsolvers.dynare.FF = deepcopy(F)
850794

851795
def find_rss(self,mesg=False,rootm='hybr',scale=0.0):
852796
'''
@@ -1862,6 +1806,12 @@ def mkjahepp(self):
18621806
pos = ma.span()[0]
18631807
poe = ma.span()[1]
18641808
str_tmp = str_tmp[:pos]+'sympycore.exp('+str_tmp[poe:]
1809+
eexp2 = re.compile('(?<!sympycore\.)E\*\*')
1810+
while eexp2.search(str_tmp):
1811+
ma = eexp2.search(str_tmp)
1812+
pos = ma.span()[0]
1813+
poe = ma.span()[1]
1814+
str_tmp = str_tmp[:pos]+'sympycore.E**'+str_tmp[poe:]
18651815
try:
18661816
func.append(eval(str_tmp))
18671817
except:

pymaclab/dsge/parsers/_dsgeparser.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1728,16 +1728,23 @@ def premknonlinsys2(self, secs):
17281728
# substitute out in main nonlinear equation system
17291729
list_tmp2 = deepcopy(self.nlsubs_list)
17301730
mreg = re.compile('@(E\(t.*?\)\|){0,1}.*?\(t.*?\)')
1731+
# This (below) regex pattern is used to get rid of E**var(t) expressions and replace with EXP(var(t)) instead
1732+
# this is done so that the pymaclab-to-dynare++ translation can proceed more easily
1733+
mreg2 = re.compile('E\*\*(?P<varo>.*?(\({0,1}.*?\)){0,1})(?=\+|-|\*|/|\*\*)')
17311734
for i,x in enumerate(list_tmp1):
17321735
rhs_eq = list_tmp1[i]
17331736
while mreg.search(rhs_eq):
17341737
ma = mreg.search(rhs_eq)
17351738
subv = ma.group()
17361739
if subv not in subs_found: subs_found.append(subv)
1737-
pos, poe = ma.span()
1740+
pos,poe = ma.span()
17381741
indx = variables.index(subv)
1739-
rhs_eq = rhs_eq[:pos]+'('+list_tmp2[indx][1]+')'+\
1740-
rhs_eq[poe:]
1742+
rhs_eq = rhs_eq[:pos]+'('+list_tmp2[indx][1]+')'+rhs_eq[poe:]
1743+
while mreg2.search(rhs_eq):
1744+
ma = mreg2.search(rhs_eq)
1745+
subv = ma.group('varo')
1746+
pos,poe = ma.span()
1747+
rhs_eq = rhs_eq[:pos]+'EXP('+subv+')'+rhs_eq[poe:]
17411748
list_tmp1[i] = rhs_eq
17421749
i1+=1
17431750
self.foceqs2 = deepcopy(list_tmp1)
@@ -2108,8 +2115,8 @@ def mk_mssidic_subs(self):
21082115
str_tmp = ma.group()
21092116
tmp_list[i1][1] = tmp_list[i1][1].replace(str_tmp,'('+sub_dic[str_tmp]+')')
21102117
locals().update(self.paramdic)
2111-
tmp_dic = {}
2112-
tmp_dic[tmp_list[i1][0]] = eval(tmp_list[i1][1])
2118+
tmp_dic = {}
2119+
tmp_dic[tmp_list[i1][0]] = eval(tmp_list[i1][1].replace('EXP(','np.exp(').replace('LOG(','np.log('))
21132120
locals().update(tmp_dic)
21142121
# Update ssidic
21152122
self.ssidic.update(tmp_dic)

pymaclab/dsge/setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ def configuration(parent_package='',top_path=None):
55
config = Configuration('dsge', parent_package, top_path)
66
config.add_subpackage('solvers')
77
config.add_subpackage('parsers')
8+
config.add_subpackage('translators')
89
config.add_subpackage('updaters')
910
return config
1011

0 commit comments

Comments
 (0)