Merge remote-tracking branch 'community/master' into enterprise
commit
cbb59fe6f8
|
@ -1,6 +1,7 @@
|
|||
((nil .
|
||||
((c-file-style . "gnu")
|
||||
(indent-tabs-mode . nil)
|
||||
(fill-column . 79)))
|
||||
(c-mode . (c-basic-offset 2))
|
||||
(makefile-mode . ((indent-tabs-mode . t))))
|
||||
((c-mode . ((indent-tabs-mode . nil)
|
||||
(c-file-style . "gnu")))
|
||||
(c++-mode . ((indent-tabs-mode . nil)
|
||||
(c-file-style . "gnu")))
|
||||
(makefile-mode . ((indent-tabs-mode . t)))
|
||||
(octave-mode . ((indent-tabs-mode . nil)
|
||||
(octave-block-offset . 4))))
|
||||
|
|
|
@ -11,13 +11,12 @@
|
|||
\#*\#
|
||||
TAGS
|
||||
*.mat
|
||||
*.xls
|
||||
*.xlsx
|
||||
|
||||
# Build system rules
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
confdefs.h
|
||||
configure
|
||||
config.log
|
||||
config.status
|
||||
|
@ -56,48 +55,18 @@ checksum
|
|||
*.bbl
|
||||
*.blg
|
||||
*.lof
|
||||
/doc/dynare.html
|
||||
/doc/dynare.info
|
||||
/doc/dynare.info-1
|
||||
/doc/dynare.info-2
|
||||
/doc/dynare.info-3
|
||||
/doc/dynare.cp
|
||||
/doc/dynare.fn
|
||||
/doc/dynare.fns
|
||||
/doc/dynare.vrs
|
||||
/doc/dynare.ky
|
||||
/doc/dynare.pg
|
||||
/doc/dynare.tp
|
||||
/doc/dynare.vr
|
||||
/doc/dynare.t2p/*
|
||||
/doc/texinfo.tex
|
||||
/doc/version.texi
|
||||
/doc/mdate-sh
|
||||
/doc/stamp-vti
|
||||
/doc/manual/build
|
||||
/doc/manual/utils/version.py
|
||||
/doc/manual/utils/__pycache__/*
|
||||
!/doc/guide.bbl
|
||||
!/doc/userguide/P_ModStruct3.pdf
|
||||
!/doc/userguide/P_MH2.pdf
|
||||
!/doc/userguide/P_flowest.pdf
|
||||
!/doc/userguide/P_ModStruct4.pdf
|
||||
!/doc/userguide/Graphics/DynareFigures.key/droppedImage-2.pdf
|
||||
!/doc/userguide/Graphics/DynareFigures.key/droppedImage.pdf
|
||||
!/doc/userguide/Graphics/DynareFigures.key/droppedImage-1.pdf
|
||||
!/doc/userguide/Graphics/DynareTitle.pdf
|
||||
!/doc/userguide/P_ModStruct5.pdf
|
||||
!/doc/userguide/P_DynareStruct2.pdf
|
||||
!/doc/userguide/P_SchorfMod.pdf
|
||||
!/doc/userguide/P_ModStruct2.pdf
|
||||
!/doc/userguide/P_ShockModel2.pdf
|
||||
!/doc/parallel/AvenueParadigm.pdf
|
||||
!/doc/parallel/iVaNo_*.pdf
|
||||
!/doc/parallel/netbook_*.pdf
|
||||
!/doc/parallel/quest_*.pdf
|
||||
!/doc/parallel/RWMH_quest1_*.pdf
|
||||
!/doc/parallel/waitbars*.pdf
|
||||
doc/m2html
|
||||
doc/internals/*.html
|
||||
doc/internals/ltxpng
|
||||
mex/build/matlab/run_m2html.m
|
||||
|
||||
# MATLAB dir
|
||||
/matlab/preprocessor*
|
||||
|
@ -108,7 +77,6 @@ mex/build/matlab/run_m2html.m
|
|||
|
||||
# DLL rules
|
||||
*.mex
|
||||
*.dll
|
||||
*.oct
|
||||
*.mexglx
|
||||
*.mexa64
|
||||
|
@ -119,21 +87,22 @@ mex/build/matlab/run_m2html.m
|
|||
/mex/matlab/
|
||||
/mex/octave/
|
||||
|
||||
# Symbolic links created for building MEX files
|
||||
/mex/build/matlab/*/*.c
|
||||
/mex/build/matlab/*/*.cc
|
||||
/mex/build/octave/*/*.c
|
||||
/mex/build/octave/*/*.cc
|
||||
|
||||
# Dynare++
|
||||
/dynare++/integ/cc/*.cpp
|
||||
/dynare++/integ/cc/*.h
|
||||
/dynare++/integ/cc/main.tex
|
||||
/dynare++/integ/src/quadrature-points.dSYM/
|
||||
/dynare++/src/dynare++.dSYM/
|
||||
/dynare++/integ/src/quadrature-points
|
||||
/dynare++/integ/src/quadrature-points.exe
|
||||
/dynare++/integ/testing/tests
|
||||
/dynare++/kord/*.cpp
|
||||
!/dynare++/kord/tests.cpp
|
||||
/dynare++/kord/*.h
|
||||
/dynare++/kord/main.tex
|
||||
/dynare++/integ/testing/tests.exe
|
||||
/dynare++/kord/tests
|
||||
/dynare++/kord/tests.exe
|
||||
/dynare++/kord/out.txt
|
||||
/dynare++/sylv/testing/*.mm
|
||||
/dynare++/sylv/testing/tests
|
||||
/dynare++/sylv/testing/tests.exe
|
||||
/dynare++/parser/cc/*_ll.cc
|
||||
|
@ -144,38 +113,39 @@ mex/build/matlab/run_m2html.m
|
|||
/dynare++/src/dynglob_ll.cc
|
||||
/dynare++/src/dynglob_tab.cc
|
||||
/dynare++/src/dynglob_tab.hh
|
||||
/dynare++/tl/cc/*.cpp
|
||||
/dynare++/tl/cc/*.h
|
||||
/dynare++/tl/cc/main.tex
|
||||
/dynare++/tl/testing/tests
|
||||
/dynare++/tl/testing/tests.exe
|
||||
/dynare++/tests/*.jnl
|
||||
/dynare++/tests/*.m
|
||||
/dynare++/tests/*.mat
|
||||
/dynare++/tests/*.dump
|
||||
!/dynare++/extern/R/Makefile
|
||||
|
||||
# Windows
|
||||
/windows/dynare-version.nsi
|
||||
|
||||
# Estimation DLL tests
|
||||
/mex/sources/estimation/tests/test-dr
|
||||
/mex/sources/estimation/tests/test-dr.exe
|
||||
/mex/sources/estimation/tests/testModelSolution
|
||||
/mex/sources/estimation/tests/testModelSolution.exe
|
||||
/mex/sources/estimation/tests/testInitKalman
|
||||
/mex/sources/estimation/tests/testInitKalman.exe
|
||||
/mex/sources/estimation/tests/testKalman
|
||||
/mex/sources/estimation/tests/testKalman.exe
|
||||
/mex/sources/estimation/tests/testPDF
|
||||
/mex/sources/estimation/tests/testPDF.exe
|
||||
/mex/sources/estimation/libmat/tests/test-qr
|
||||
/mex/sources/estimation/libmat/tests/test-qr.exe
|
||||
/mex/sources/estimation/libmat/tests/test-gsd
|
||||
/mex/sources/estimation/libmat/tests/test-gsd.exe
|
||||
/mex/sources/estimation/libmat/tests/test-lu
|
||||
/mex/sources/estimation/libmat/tests/test-lu.exe
|
||||
/mex/sources/estimation/libmat/tests/test-repmat
|
||||
/mex/sources/estimation/libmat/tests/test-repmat.exe
|
||||
!/windows/Makefile
|
||||
!/windows/deps/Makefile
|
||||
windows/deps/lib32/
|
||||
windows/deps/lib64/
|
||||
windows/deps/lib32-msys2/
|
||||
windows/deps/lib64-msys2/
|
||||
windows/deps/matlab32/
|
||||
windows/deps/matlab64/
|
||||
windows/deps/mingw32/
|
||||
windows/deps/mingw64/
|
||||
windows/deps/octave32/
|
||||
windows/deps/octave64/
|
||||
windows/deps/sources32/
|
||||
windows/deps/sources64/
|
||||
windows/deps/tarballs/
|
||||
windows/exe/
|
||||
windows/7z/
|
||||
windows/zip/
|
||||
dynare++/32-bit/
|
||||
dynare++/64-bit/
|
||||
|
||||
# MacOS stuff
|
||||
.DS_Store
|
||||
macOS/pkg/
|
||||
|
||||
# Emacs stuff
|
||||
scripts/dynare.elc
|
||||
|
@ -185,6 +155,7 @@ scripts/dynare.elc
|
|||
/contrib/ms-sbvar/*.dat
|
||||
/contrib/ms-sbvar/sbvar_commandline
|
||||
/contrib/ms-sbvar/sbvar_init_file
|
||||
!/contrib/ms-sbvar/Makefile
|
||||
/tests/ms-sbvar/*.tmp
|
||||
|
||||
# Reporting
|
||||
|
@ -199,3 +170,5 @@ octave-workspace
|
|||
|
||||
# VERSION generated file
|
||||
VERSION
|
||||
|
||||
matlab/supported_octave_version.m
|
||||
|
|
188
.gitlab-ci.yml
188
.gitlab-ci.yml
|
@ -2,22 +2,47 @@ variables:
|
|||
GIT_SUBMODULE_STRATEGY: normal
|
||||
TERM: linux
|
||||
|
||||
# The next stanza creates the version number used for the source tarball and the
|
||||
# binary packages. Here are the following possible cases:
|
||||
# - if VERSION was already set (when manually running a pipeline), use it
|
||||
# - if we are in the official Dynare repository:
|
||||
# + if on a tag: use the tag
|
||||
# + if on master: use 4.6-unstable-$TIMESTAMP-$COMMIT
|
||||
# + on another branch: use $BRANCH-$TIMESTAMP-$COMMIT
|
||||
# - if in a personal repository: use $USER-$TIMESTAMP-$COMMIT
|
||||
before_script:
|
||||
- wget http://www.dynare.org/x13/x13.zip
|
||||
- unzip x13.zip
|
||||
- cp -r binaries/linux matlab/modules/dseries/externals/x13
|
||||
- '[[ -z $VERSION ]] && [[ $CI_PROJECT_NAMESPACE == Dynare ]] && [[ -n $CI_COMMIT_TAG ]] && export VERSION=$CI_COMMIT_TAG'
|
||||
- '[[ -z $VERSION ]] && [[ $CI_PROJECT_NAMESPACE == Dynare ]] && [[ $CI_COMMIT_REF_NAME == master ]] && export VERSION=4.6-unstable-$(date +%F-%H%M)-$CI_COMMIT_SHORT_SHA'
|
||||
- '[[ -z $VERSION ]] && [[ $CI_PROJECT_NAMESPACE == Dynare ]] && export VERSION=$CI_COMMIT_REF_NAME-$(date +%F-%H%M)-$CI_COMMIT_SHORT_SHA'
|
||||
- '[[ -z $VERSION ]] && export VERSION=$CI_PROJECT_NAMESPACE-$(date +%F-%H%M)-$CI_COMMIT_SHORT_SHA'
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test_and_pkg
|
||||
- deploy
|
||||
|
||||
build_binaries:
|
||||
stage: build
|
||||
script:
|
||||
- autoreconf -si
|
||||
- './configure --with-matlab=$(dirname $(dirname $(readlink -f `which matlab`))) MATLAB_VERSION=$(echo version | matlab -nodesktop -nodisplay -nosplash 2>/dev/null | sed -En "/ans\ =/!d;n;n;s/^[^0-9]*([0-9]+\.[0-9]+).*$/\1/;p")'
|
||||
- './configure --with-matlab=$(dirname $(dirname $(readlink -f $(which matlab)))) MATLAB_VERSION=$(echo version | matlab -nodesktop -nodisplay -nosplash 2>/dev/null | sed -En "/ans\ =/!d;n;n;s/^[^0-9]*([0-9]+\.[0-9]+).*$/\1/;p")'
|
||||
- make -j $(nproc) LN_S="cp -p"
|
||||
artifacts:
|
||||
paths:
|
||||
- matlab/preprocessor*/*
|
||||
- mex/octave/
|
||||
- mex/matlab/
|
||||
- dynare++/parser/cc/*_tab.cc
|
||||
- dynare++/parser/cc/*_tab.hh
|
||||
- dynare++/parser/cc/*_ll.cc
|
||||
- dynare++/src/*_tab.cc
|
||||
- dynare++/src/*_tab.hh
|
||||
- dynare++/src/*_ll.cc
|
||||
- dynare++/*/*.o
|
||||
- dynare++/*/*.a
|
||||
- dynare++/*/*/*.o
|
||||
- dynare++/*/*/*.a
|
||||
- dynare++/integ/src/quadrature-points
|
||||
- dynare++/src/dynare++
|
||||
expire_in: 1 week
|
||||
|
||||
|
@ -26,34 +51,102 @@ build_doc:
|
|||
script:
|
||||
- autoreconf -si
|
||||
- ./configure --disable-matlab --disable-octave
|
||||
- make -j $(nproc) info pdf html
|
||||
- make -j $(nproc) pdf html
|
||||
artifacts:
|
||||
paths:
|
||||
- doc/dynare.info*
|
||||
- doc/dynare.html
|
||||
- doc/dynare.pdf
|
||||
- doc/manual/build/
|
||||
- doc/*.pdf
|
||||
- doc/*/*.pdf
|
||||
- dynare++/doc/*.pdf
|
||||
- preprocessor/doc/*/*.pdf
|
||||
expire_in: 1 week
|
||||
|
||||
testsuite_matlab:
|
||||
stage: test
|
||||
pkg_source:
|
||||
stage: test_and_pkg
|
||||
script:
|
||||
- 'for f in configure.ac preprocessor/configure.ac mex/build/matlab/configure.ac mex/build/octave/configure.ac; do sed -i "s/^AC_INIT(\[\(.*\)\],\s*\[\(.*\)\])/AC_INIT([\1], [$VERSION])/" $f; done'
|
||||
- autoreconf -si
|
||||
- './configure --disable-octave --with-matlab=$(dirname $(dirname $(readlink -f `which matlab`))) MATLAB_VERSION=$(echo version | matlab -nodesktop -nodisplay -nosplash 2>/dev/null | sed -En "/ans\ =/!d;n;n;s/^[^0-9]*([0-9]+\.[0-9]+).*$/\1/;p")'
|
||||
- make -j $(($(nproc) * 3 / 4)) -C tests check-matlab
|
||||
- ./configure
|
||||
- make dist
|
||||
artifacts:
|
||||
paths:
|
||||
- dynare-*.tar.xz
|
||||
expire_in: 1 week
|
||||
dependencies: []
|
||||
|
||||
pkg_windows:
|
||||
stage: test_and_pkg
|
||||
script:
|
||||
- ln -s ~/tarballs windows/deps/
|
||||
- make -C windows
|
||||
cache:
|
||||
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
paths:
|
||||
- windows/deps/sources32/
|
||||
- windows/deps/sources64/
|
||||
- windows/deps/lib32/
|
||||
- windows/deps/lib64/
|
||||
# We do not cache lib{32,64}-msys2, mingw{32,64}, octave{32,64} and
|
||||
# matlab{32,64}, because those are simply extracted from a tarball. It
|
||||
# would be a waste of space and of (re-compression) time.
|
||||
artifacts:
|
||||
paths:
|
||||
- windows/exe/*
|
||||
- windows/7z/*
|
||||
- windows/zip/*
|
||||
expire_in: 1 week
|
||||
dependencies:
|
||||
- build_doc
|
||||
|
||||
pkg_macOS:
|
||||
stage: test_and_pkg
|
||||
script:
|
||||
- make -C macOS
|
||||
tags:
|
||||
- macOS
|
||||
artifacts:
|
||||
paths:
|
||||
- macOS/pkg/*
|
||||
expire_in: 1 week
|
||||
dependencies:
|
||||
- build_doc
|
||||
|
||||
.test_matlab_template:
|
||||
stage: test_and_pkg
|
||||
artifacts:
|
||||
paths:
|
||||
- tests/*.m.log
|
||||
- tests/*.m.trs
|
||||
- tests/*/*.m.log
|
||||
- tests/*/*.m.trs
|
||||
- tests/*/*.jnl
|
||||
- tests/*/*/*.m.log
|
||||
- tests/*/*/*.m.trs
|
||||
- tests/*/*/*.jnl
|
||||
- tests/run_test_matlab_output.txt
|
||||
when: always
|
||||
dependencies:
|
||||
- build_binaries
|
||||
|
||||
.testsuite_octave_template:
|
||||
stage: test
|
||||
test_matlab:
|
||||
extends: .test_matlab_template
|
||||
script:
|
||||
- autoreconf -si
|
||||
- './configure --disable-octave --with-matlab=$(dirname $(dirname $(readlink -f $(which matlab)))) MATLAB_VERSION=$(echo version | matlab -nodesktop -nodisplay -nosplash 2>/dev/null | sed -En "/ans\ =/!d;n;n;s/^[^0-9]*([0-9]+\.[0-9]+).*$/\1/;p")'
|
||||
- make -j $(($(nproc) * 3 / 4)) -C tests check-matlab
|
||||
|
||||
test_old_matlab:
|
||||
extends: .test_matlab_template
|
||||
script:
|
||||
- autoreconf -si
|
||||
- './configure --disable-octave --with-matlab=/usr/local/MATLAB/R2009b MATLAB_VERSION=R2009b'
|
||||
- make -C mex/build/matlab clean
|
||||
- make -j $(nproc) -C mex/build/matlab
|
||||
- make -j $(($(nproc) * 3 / 4)) -C tests check-matlab
|
||||
when: manual
|
||||
|
||||
test_octave:
|
||||
stage: test_and_pkg
|
||||
variables:
|
||||
OPENBLAS_NUM_THREADS: 1
|
||||
script:
|
||||
|
@ -66,22 +159,65 @@ testsuite_matlab:
|
|||
- tests/*.o.trs
|
||||
- tests/*/*.o.log
|
||||
- tests/*/*.o.trs
|
||||
- tests/*/*.jnl
|
||||
- tests/*/*/*.o.log
|
||||
- tests/*/*/*.o.trs
|
||||
- tests/*/*/*.jnl
|
||||
- tests/run_test_octave_output.txt
|
||||
when: always
|
||||
dependencies:
|
||||
- build_binaries
|
||||
|
||||
testsuite_octave_auto:
|
||||
extends: .testsuite_octave_template
|
||||
only:
|
||||
- tags
|
||||
- schedules
|
||||
|
||||
testsuite_octave_manual:
|
||||
extends: .testsuite_octave_template
|
||||
except:
|
||||
- tags
|
||||
- schedules
|
||||
when: manual
|
||||
|
||||
test_dynare++:
|
||||
stage: test_and_pkg
|
||||
script:
|
||||
- autoreconf -si
|
||||
- ./configure --disable-matlab --disable-octave
|
||||
- touch dynare++/parser/cc/*_tab.cc dynare++/parser/cc/*_tab.hh dynare++/parser/cc/*_ll.cc dynare++/src/*_tab.cc dynare++/src/*_tab.hh dynare++/src/*_ll.cc
|
||||
- touch dynare++/*/*.o dynare++/*/*/*.o
|
||||
- touch dynare++/*/*.a dynare++/*/*/*.a
|
||||
- touch dynare++/integ/src/quadrature-points dynare++/src/dynare++
|
||||
- make -C dynare++ check
|
||||
dependencies:
|
||||
- build_binaries
|
||||
artifacts:
|
||||
paths:
|
||||
- dynare++/kord/out.txt
|
||||
- dynare++/tests/*.jnl
|
||||
- dynare++/tests/*.m
|
||||
- dynare++/tests/*.mat
|
||||
- dynare++/tests/*.dump
|
||||
|
||||
deploy_manual_unstable:
|
||||
stage: deploy
|
||||
only:
|
||||
- master@Dynare/dynare
|
||||
tags:
|
||||
- restricted
|
||||
dependencies:
|
||||
- build_doc
|
||||
script:
|
||||
- rm -rf doc/manual/build/html/_static/mathjax
|
||||
- ln -s /usr/share/javascript/mathjax doc/manual/build/html/_static/mathjax
|
||||
- rsync --recursive --links --delete doc/manual/build/html/ /srv/www.dynare.org/manual-unstable/
|
||||
|
||||
deploy_snapshot_unstable:
|
||||
stage: deploy
|
||||
only:
|
||||
- master@Dynare/dynare
|
||||
tags:
|
||||
- restricted
|
||||
dependencies:
|
||||
- pkg_source
|
||||
- pkg_windows
|
||||
- pkg_macOS
|
||||
script:
|
||||
- f=(windows/exe/*) && osslsigncode sign -pkcs12 ~/dynare-object-signing.p12 -n Dynare -i https://www.dynare.org -in ${f[0]} -out ${f[0]}.signed && mv ${f[0]}.signed ${f[0]}
|
||||
- cp *.tar.xz /srv/www.dynare.org/snapshot/source/ && ln -sf *.tar.xz /srv/www.dynare.org/snapshot/source/dynare-latest-src.tar.xz
|
||||
- f=(windows/exe/*) && cp ${f[0]} /srv/www.dynare.org/snapshot/windows/ && ln -sf ${f[0]##*/} /srv/www.dynare.org/snapshot/windows/dynare-latest-win.exe
|
||||
- f=(windows/7z/*) && cp ${f[0]} /srv/www.dynare.org/snapshot/windows-7z/ && ln -sf ${f[0]##*/} /srv/www.dynare.org/snapshot/windows-7z/dynare-latest-win.7z
|
||||
- f=(windows/zip/*) && cp ${f[0]} /srv/www.dynare.org/snapshot/windows-zip/ && ln -sf ${f[0]##*/} /srv/www.dynare.org/snapshot/windows-zip/dynare-latest-win.zip
|
||||
- f=(macOS/pkg/*) && cp ${f[0]} /srv/www.dynare.org/snapshot/macos/ && ln -sf ${f[0]##*/} /srv/www.dynare.org/snapshot/macos/dynare-latest-macos.pkg
|
||||
- ~/update-snapshot-list.sh
|
||||
- curl -X POST -F token="$WEBSITE_PIPELINE_TRIGGER_TOKEN" -F ref=master https://git.dynare.org/api/v4/projects/40/trigger/pipeline
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
[submodule "contrib/ms-sbvar/utilities_dw"]
|
||||
path = contrib/ms-sbvar/utilities_dw
|
||||
url = https://git.dynare.org/contrib/utilities_dw.git
|
||||
url = ../../contrib/utilities_dw.git
|
||||
[submodule "contrib/ms-sbvar/switch_dw"]
|
||||
path = contrib/ms-sbvar/switch_dw
|
||||
url = https://git.dynare.org/contrib/switch_dw.git
|
||||
url = ../../contrib/switch_dw.git
|
||||
[submodule "contrib/ms-sbvar/TZcode"]
|
||||
path = contrib/ms-sbvar/TZcode
|
||||
url = https://git.dynare.org/contrib/TZcode.git
|
||||
url = ../../contrib/TZcode.git
|
||||
[submodule "contrib/dmm"]
|
||||
path = contrib/dmm
|
||||
url = https://git.dynare.org/contrib/dmm.git
|
||||
url = ../../contrib/dmm.git
|
||||
[submodule "matlab/utilities/tests"]
|
||||
path = matlab/utilities/tests
|
||||
url = https://git.dynare.org/Dynare/m-unit-tests.git
|
||||
url = ../../Dynare/m-unit-tests.git
|
||||
[submodule "matlab/particles"]
|
||||
path = matlab/particles
|
||||
url = https://git.dynare.org/Dynare/particles.git
|
||||
url = ../../Dynare/particles.git
|
||||
[submodule "matlab/modules/dseries"]
|
||||
path = matlab/modules/dseries
|
||||
url = ../../Enterprise/dseries.git
|
||||
branch = enterprise
|
||||
[submodule "matlab/modules/reporting"]
|
||||
path = matlab/modules/reporting
|
||||
url = https://git.dynare.org/Dynare/reporting.git
|
||||
url = ../../Dynare/reporting.git
|
||||
[submodule "contrib/jsonlab"]
|
||||
path = contrib/jsonlab
|
||||
url = https://github.com/fangq/jsonlab.git
|
||||
[submodule "preprocessor"]
|
||||
path = preprocessor
|
||||
url = https://git.dynare.org/Dynare/preprocessor.git
|
||||
url = ../../Dynare/preprocessor.git
|
||||
|
|
|
@ -45,7 +45,7 @@ So, now you've reported the bug or asked for an enhancemnt by creating a GitHub
|
|||
Now, if you want to go the extra mile, you'll volunteer to contribute code to fix the GitHub issue you created above. Once we've agreed that you'll do it, please do the following:
|
||||
|
||||
1. Clone the Dynare repository:
|
||||
* `git clone https://git.dynare.org/Dynare/dynare.git`
|
||||
* `git clone --recurse-submodules https://git.dynare.org/Dynare/dynare.git`
|
||||
1. [Fork the Dynare repository](https://help.github.com/articles/fork-a-repo)
|
||||
1. Change into the `dynare` folder and add the forked repository as a remote:
|
||||
* `cd dynare`
|
||||
|
|
32
Makefile.am
32
Makefile.am
|
@ -28,23 +28,21 @@ EXTRA_DIST = \
|
|||
CONTRIBUTING.md \
|
||||
windows/dynare.nsi \
|
||||
windows/README.txt \
|
||||
osx \
|
||||
macOS \
|
||||
examples \
|
||||
scripts \
|
||||
.dir-locals.el
|
||||
|
||||
all-local: preprocessor/src/dynare_m
|
||||
{ \
|
||||
if [ -z "`file preprocessor/src/dynare_m | grep x86.64`" ]; then \
|
||||
ARCH="32"; \
|
||||
else \
|
||||
all-local: preprocessor/src/dynare_m$(EXEEXT)
|
||||
if file preprocessor/src/dynare_m$(EXEEXT) | grep -q x86.64; then \
|
||||
ARCH="64"; \
|
||||
else \
|
||||
ARCH="32"; \
|
||||
fi; \
|
||||
mkdir -p $(abs_srcdir)/matlab/preprocessor$$ARCH; \
|
||||
$(LN_S) -f $(abs_srcdir)/preprocessor/src/dynare_m $(abs_srcdir)/matlab/preprocessor$$ARCH; \
|
||||
mkdir -p $(abs_srcdir)/julia/preprocessor$$ARCH ; \
|
||||
$(LN_S) -f $(abs_srcdir)/preprocessor/src/dynare_m $(abs_srcdir)/julia/preprocessor$$ARCH; \
|
||||
}
|
||||
mkdir -p $(abs_srcdir)/matlab/preprocessor$$ARCH && \
|
||||
$(LN_S) -f $(abs_builddir)/preprocessor/src/dynare_m$(EXEEXT) $(abs_srcdir)/matlab/preprocessor$$ARCH && \
|
||||
mkdir -p $(abs_srcdir)/julia/preprocessor$$ARCH && \
|
||||
$(LN_S) -f $(abs_builddir)/preprocessor/src/dynare_m$(EXEEXT) $(abs_srcdir)/julia/preprocessor$$ARCH
|
||||
|
||||
dist-hook:
|
||||
rm -rf `find $(distdir)/matlab $(distdir)/examples -name *~`
|
||||
|
@ -61,15 +59,13 @@ install-exec-local:
|
|||
cp -r matlab $(DESTDIR)$(pkglibdir)
|
||||
find $(DESTDIR)$(pkglibdir) -name LICENSE.md -delete
|
||||
rm -rf $(DESTDIR)$(pkglibdir)/matlab/preprocessor*
|
||||
{ \
|
||||
if [ -z "`file preprocessor/src/dynare_m | grep x86.64`" ]; then \
|
||||
ARCH="32"; \
|
||||
else \
|
||||
if file preprocessor/src/dynare_m | grep -q x86.64; then \
|
||||
ARCH="64"; \
|
||||
else \
|
||||
ARCH="32"; \
|
||||
fi; \
|
||||
mkdir -p $(DESTDIR)$(pkglibdir)/matlab/preprocessor$$ARCH; \
|
||||
cp preprocessor/src/dynare_m $(DESTDIR)$(pkglibdir)/matlab/preprocessor$$ARCH; \
|
||||
}
|
||||
mkdir -p $(DESTDIR)$(pkglibdir)/matlab/preprocessor$$ARCH && \
|
||||
cp preprocessor/src/dynare_m $(DESTDIR)$(pkglibdir)/matlab/preprocessor$$ARCH
|
||||
|
||||
uninstall-local:
|
||||
rm -f $(DESTDIR)$(bindir)/dynare++
|
||||
|
|
77
NEWS
77
NEWS
|
@ -1,3 +1,80 @@
|
|||
Announcement for Dynare 4.5.7 (on 2019-02-06)
|
||||
=============================================
|
||||
|
||||
We are pleased to announce the release of Dynare 4.5.7.
|
||||
|
||||
This is a bugfix release.
|
||||
|
||||
The Windows packages are already available for download at:
|
||||
|
||||
http://www.dynare.org/download/dynare-stable
|
||||
|
||||
The Mac and GNU/Linux packages (for Debian and Ubuntu LTS) should follow soon.
|
||||
|
||||
This release is compatible with MATLAB versions 7.5 (R2007b) to 9.4 (R2018b)
|
||||
and with GNU Octave versions 4.4.1.
|
||||
|
||||
Here is a list of the problems identified in version 4.5.6 and that have been
|
||||
fixed in version 4.5.7:
|
||||
|
||||
- The mex-file conducting the QZ decomposition erroneously applied
|
||||
the `qz_criterium` to the square absolute value of eigenvalues
|
||||
instead of the absolute value itself (as done in mjdgges.m and the
|
||||
AIM solver).
|
||||
|
||||
- In pathological cases, `mode_compute=5` (`newrat`) might enter an
|
||||
infinite loop.
|
||||
|
||||
- `discretionary_policy` might erroneously state that the derivatives
|
||||
of the objective function are non-zero if there are NaN present.
|
||||
|
||||
- Dynare++, when conducting the QZ decomposition, erroneously applied
|
||||
the `qz_criterium` to the square absolute value of eigenvalues
|
||||
instead of the absolute value itself.
|
||||
|
||||
- Dynare++: IRFs were incorrectly computed.
|
||||
|
||||
- `dynare_sensitivity` did not display the figures of
|
||||
`irf_calibration`, it only stored them on the disk.
|
||||
|
||||
- Scatter plots generated by `dynare_sensitivity` did not correctly
|
||||
display LaTeX names.
|
||||
|
||||
- Parameter updating via steady state files did not correctly work in
|
||||
case of using [static]/[dynamic] equation tags.
|
||||
|
||||
- Memory leaks in `k_order_pert` (used by higher order stochastic
|
||||
simulations) could lead to crashes.
|
||||
|
||||
- Predetermined variables were not properly set when used in model
|
||||
local variables.
|
||||
|
||||
- Posterior moment computation did not correctly update the
|
||||
covariance matrix of exogenous shocks during posterior sampling.
|
||||
|
||||
- Dynare was crashing with a cryptic message if a non estimated
|
||||
parameter was initialized in the `estimated_params_init` block.
|
||||
|
||||
- The `forecast` command crashed if the model was declared as linear
|
||||
and contained deterministic exogenous variables.
|
||||
|
||||
- Block decomposition is broken when used in conjunction with
|
||||
`varexo_det`.
|
||||
|
||||
- The model was not correctly specified when `identification` was run
|
||||
without another stochastic command in the `.mod` file
|
||||
(e.g. `estimation`, `stoch_simul`, etc.).
|
||||
|
||||
- Realtime annualized shock decompositions added the wrong steady state
|
||||
value.
|
||||
|
||||
- `mh_recover` option crashed when using slice sampler.
|
||||
|
||||
- x-axis values in plots of moment restrictions were wrong for
|
||||
autocovariances.
|
||||
|
||||
|
||||
|
||||
Announcement for Dynare 4.5.6 (on 2018-07-25)
|
||||
=============================================
|
||||
|
||||
|
|
129
README.md
129
README.md
|
@ -1,16 +1,16 @@
|
|||
<a name="logo"/>
|
||||
<div align="center">
|
||||
<a href="http://www.dynare.org/" target="_blank">
|
||||
<img src="http://www.dynare.org/img/dynare.png" alt="Dynare Logo"></img>
|
||||
<a href="https://www.dynare.org/" target="_blank">
|
||||
<img src="https://www.dynare.org/assets/images/logo/dlogo.svg" alt="Dynare Logo"></img>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
# Dynare
|
||||
|
||||
Described on the homepage: <http://www.dynare.org/>
|
||||
Described on the homepage: <https://www.dynare.org/>
|
||||
|
||||
Most users should use the precompiled package available for your OS, also
|
||||
available via the Dynare homepage: <http://www.dynare.org/download/dynare-stable>.
|
||||
Most users should use the precompiled package available for their OS, also
|
||||
available via the Dynare homepage: <https://www.dynare.org/download/>.
|
||||
|
||||
# Contributions
|
||||
|
||||
|
@ -31,20 +31,26 @@ Here, we explain how to build from source:
|
|||
|
||||
This source can be retrieved in three forms:
|
||||
- via git, at <https://git.dynare.org/Dynare/dynare.git>
|
||||
- using the stable source archive of the latest Dynare version (currently 4.4) from <http://www.dynare.org/download/dynare-stable/>
|
||||
- using a source snapshot of the unstable version, from <http://www.dynare.org/download/dynare-unstable/source-snapshot>
|
||||
- using the stable source archive of the latest Dynare version from <https://www.dynare.org/download/>
|
||||
- using a source snapshot of the unstable version, also from <https://www.dynare.org/download/>
|
||||
|
||||
Note that if you obtain the source code via git, you will need to install more tools (see below).
|
||||
|
||||
The first section of this page gives general instructions, which apply to all platforms. Then some specific platforms are discussed.
|
||||
|
||||
**Note:** Here, when we refer to 32-bit or 64-bit, we refer to the type of MATLAB installation, not the type of Windows installation. It is perfectly possible to run a 32-bit MATLAB on a 64-bit Windows: in that case, instructions for Windows 32-bit should be followed. To determine the type of your MATLAB installation, type:
|
||||
**Note:** Here, when we refer to 32-bit or 64-bit, we refer to the type of
|
||||
MATLAB or Octave installation, not the type of operating system installation.
|
||||
For example, it is perfectly possible to run a 32-bit MATLAB on a 64-bit
|
||||
Windows: in that case, instructions for Windows 32-bit should be followed. To
|
||||
determine the type of your MATLAB/Octave installation, type:
|
||||
```matlab
|
||||
>> computer
|
||||
```
|
||||
at the MATLAB prompt: if it returns `PCWIN64`, `GLNX64` or `MACI64`, then you
|
||||
have a 64-bit MATLAB; if it returns `PCWIN`, `MACI` or `GLNX`, then you have a
|
||||
32-bit MATLAB.
|
||||
at the MATLAB/Octave prompt. Under MATLAB, if it returns `PCWIN64`, `GLNX64` or
|
||||
`MACI64`, then it is a 64-bit MATLAB; if it returns `PCWIN`, `MACI` or `GLNX`,
|
||||
then it is a 32-bit MATLAB. Under Octave, if it returns a string that begins
|
||||
with `x86_64`, it is a 64-bit Octave; if the strings begins with `i686`, it is
|
||||
a 32-bit Octave.
|
||||
|
||||
**Contents**
|
||||
|
||||
|
@ -60,29 +66,26 @@ have a 64-bit MATLAB; if it returns `PCWIN`, `MACI` or `GLNX`, then you have a
|
|||
A number of tools and libraries are needed in order to recompile everything. You don't necessarily need to install everything, depending on what you want to compile.
|
||||
|
||||
- A POSIX compliant shell and an implementation of Make (mandatory)
|
||||
- The [GNU Compiler Collection](http://gcc.gnu.org/), with gcc, g++ and gfortran (mandatory)
|
||||
- The [GNU Compiler Collection](http://gcc.gnu.org/), version 8 or later, with
|
||||
gcc, g++ and gfortran (mandatory)
|
||||
- MATLAB (if you want to compile the MEX for MATLAB)
|
||||
- [GNU Octave](http://www.octave.org), with the development headers (if you
|
||||
want to compile the MEX for Octave)
|
||||
- [Boost libraries](http://www.boost.org), version 1.36 or later (with the filesystem library compiled)
|
||||
- [Bison](http://www.gnu.org/software/bison/), version 3.0 or later (only if you get the source through Git)
|
||||
- [Boost libraries](http://www.boost.org), version 1.36 or later
|
||||
- [Bison](http://www.gnu.org/software/bison/), version 3.2 or later (only if you get the source through Git)
|
||||
- [Flex](http://flex.sourceforge.net/), version 2.5.4 or later (only if you get the source through Git)
|
||||
- [Autoconf](http://www.gnu.org/software/autoconf/), version 2.62 or later (only if you get the source through Git) (see [Installing an updated version of Autoconf in your own directory, in GNU/Linux](http://www.dynare.org/DynareWiki/AutoMake))
|
||||
- [Automake](http://www.gnu.org/software/automake/), version 1.11.2 or later (only if you get the source through Git) (see [Installing an updated version of AutoMake in your own directory, in GNU/Linux](http://www.dynare.org/DynareWiki/AutoMake))
|
||||
- [CWEB](http://www-cs-faculty.stanford.edu/%7Eknuth/cweb.html), with its tools
|
||||
`ctangle` and `cweave` (only if you want to build the k-order DLL or Dynare++, and get the source through Git)
|
||||
- [Autoconf](http://www.gnu.org/software/autoconf/), version 2.62 or later (only if you get the source through Git)
|
||||
- [Automake](http://www.gnu.org/software/automake/), version 1.11.2 or later (only if you get the source through Git)
|
||||
- An implementation of BLAS and LAPACK: either [ATLAS](http://math-atlas.sourceforge.net/), [OpenBLAS](http://xianyi.github.com/OpenBLAS/), Netlib ([BLAS](http://www.netlib.org/blas/), [LAPACK](http://www.netlib.org/lapack/)) or [MKL](http://software.intel.com/en-us/intel-mkl/) (only if you want to build Dynare++)
|
||||
- An implementation of [POSIX Threads](http://en.wikipedia.org/wiki/POSIX_Threads) (optional, for taking advantage of multi-core)
|
||||
- [MAT File I/O library](http://sourceforge.net/projects/matio/) (if you want to compile Markov-Switching code, the estimation DLL, k-order DLL and Dynare++)
|
||||
- [MAT File I/O library](http://sourceforge.net/projects/matio/), version 1.5 or later (if you want to compile Markov-Switching code, the estimation DLL, k-order DLL and Dynare++)
|
||||
- [SLICOT](http://www.slicot.org) (if you want to compile the Kalman steady state DLL)
|
||||
- [GSL library](http://www.gnu.org/software/gsl/) (if you want to compile Markov-Switching code)
|
||||
- A decent LaTeX distribution (if you want to compile PDF documentation). The following extra components may be needed:
|
||||
- [Eplain](http://www.tug.org/eplain/) TeX macros (only if you want to build Dynare++ source documentation)
|
||||
- [Beamer](http://latex-beamer.sourceforge.net/) (for some PDF presentations)
|
||||
- A decent LaTeX distribution (if you want to compile PDF documentation),
|
||||
ideally with Beamer
|
||||
- For building the reference manual:
|
||||
- [GNU Texinfo](http://www.gnu.org/software/texinfo/)
|
||||
- [Latex2HTML](http://www.latex2html.org), if you want nice mathematical formulas in HTML output
|
||||
- [Doxygen](http://www.stack.nl/%7Edimitri/doxygen/) (if you want to build Dynare preprocessor source documentation)
|
||||
- [Sphinx](http://www.sphinx-doc.org/)
|
||||
- [MathJax](https://www.mathjax.org/)
|
||||
- [Doxygen](http://www.stack.nl/%7Edimitri/doxygen/) (if you want to build Dynare preprocessor source documentation)
|
||||
- For Octave, the development libraries corresponding to the UMFPACK packaged with Octave
|
||||
|
||||
### Preparing the sources
|
||||
|
@ -91,7 +94,7 @@ If you have downloaded the sources from an official source archive or the source
|
|||
|
||||
If you want to use Git, do the following from a terminal:
|
||||
|
||||
git clone --recursive https://git.dynare.org/Dynare/dynare.git
|
||||
git clone --recurse-submodules https://git.dynare.org/Dynare/dynare.git
|
||||
cd dynare
|
||||
autoreconf -si
|
||||
|
||||
|
@ -105,28 +108,39 @@ Simply launch the configure script from a terminal:
|
|||
```
|
||||
If you have MATLAB, you need to indicate both the MATLAB location and version. For example, on GNU/Linux:
|
||||
```
|
||||
./configure --with-matlab=/usr/local/MATLAB/R2013a MATLAB_VERSION=8.1
|
||||
./configure --with-matlab=/usr/local/MATLAB/R2019a MATLAB_VERSION=9.6
|
||||
```
|
||||
Note that the MATLAB version can also be specified via the MATLAB family product release (R2009a, R2008b, ...).
|
||||
Note that the MATLAB version can also be specified via the MATLAB family product release (R2019a, R2018b, …).
|
||||
|
||||
Alternatively, you can disable the compilation of MEX files for MATLAB with the `--disable-matlab` flag, and MEX files for Octave with `--disable-octave`.
|
||||
|
||||
You may need to specify additional options to the configure script, see the platform specific instructions below.
|
||||
You may need to specify additional options to the configure script, see the
|
||||
output of the `--help` option, and also the platform specific instructions
|
||||
below.
|
||||
|
||||
Note that if you don't want to compile the C/C++ programs with debugging information, you can specify the `CFLAGS` and `CXXFLAGS` variables to the configure script, such as:
|
||||
```
|
||||
./configure CFLAGS="-O3" CXXFLAGS="-O3"
|
||||
```
|
||||
To remove debugging information for MATLAB MEX functions, the analagous call would be:
|
||||
To remove debugging information for MATLAB MEX functions, the analogous call would be:
|
||||
```
|
||||
./configure MATLAB_MEX_CFLAGS="-O3" MATLAB_MEX_CXXFLAGS="-O3"
|
||||
```
|
||||
|
||||
If you want to give a try to the parallelized versions of some mex files (`A_times_B_kronecker_C` and `sparse_hessian_times_B_kronecker_C` used to get the reduced form of the second order approximation of the model) you can add the `--enable-openmp` flag, for instance:
|
||||
If the configuration goes well, the script will tell you which components are
|
||||
correctly configured and will be built.
|
||||
|
||||
Note that it is possible that some MEX files cannot be compiled, due to missing
|
||||
build dependencies. If you find no way of installing the missing dependencies,
|
||||
a workaround can be to give up on compiling these MEX files and rather use
|
||||
slower implementations (in the MATLAB/Octave language) that are available under
|
||||
the `matlab/missing/mex/` subdirectories. For example, if you fail to compile
|
||||
the gensylv MEX, you can type the following at the MATLAB/Octave prompt before
|
||||
running Dynare:
|
||||
```matlab
|
||||
addpath <DYNARE_ROOT>/matlab/missing/mex/gensylv
|
||||
```
|
||||
./configure --with-matlab=/usr/local/MATLAB/R2013a MATLAB_VERSION=8.1 --enable-openmp
|
||||
```
|
||||
If the configuration goes well, the script will tell you which components are correctly configured and will be built.
|
||||
(where you need to replace `<DYNARE_ROOT>` with the full path to your Dynare copy).
|
||||
|
||||
### Building
|
||||
|
||||
|
@ -154,7 +168,7 @@ The Git source comes with unit tests (in the MATLAB functions) and integration t
|
|||
make check
|
||||
```
|
||||
In the `tests` subfolder. If Dynare has been compiled against MATLAB and Octave, the tests will be run with MATLAB and Octave. Depending on
|
||||
your PC, this can take several hours. It is possible to run the tests only with MATLAB:
|
||||
the performance of your machine, this can take several hours. It is possible to run the tests only with MATLAB:
|
||||
```
|
||||
make check-matlab
|
||||
```
|
||||
|
@ -205,7 +219,7 @@ All the prerequisites are packaged:
|
|||
- `build-essential` (for gcc, g++ and make)
|
||||
- `gfortran`
|
||||
- `liboctave-dev`
|
||||
- `libboost-graph-dev` and `libboost-filesystem-dev`
|
||||
- `libboost-graph-dev`
|
||||
- `libgsl-dev`
|
||||
- `libmatio-dev`
|
||||
- `libslicot-dev` and `libslicot-pic`
|
||||
|
@ -216,25 +230,25 @@ All the prerequisites are packaged:
|
|||
- `automake`
|
||||
- `texlive`
|
||||
- `texlive-publishers` (for Econometrica bibliographic style)
|
||||
- `texlive-extra-utils` (for CWEB)
|
||||
- `texlive-formats-extra` (for Eplain)
|
||||
- `texlive-latex-extra` (for fullpage.sty)
|
||||
- `texlive-fonts-extra` (for ccicons)
|
||||
- `texlive-latex-recommended`
|
||||
- `texlive-science` (for amstex)
|
||||
- `texinfo`
|
||||
- `texlive-generic-extra` (for Sphinx)
|
||||
- `lmodern` (for macroprocessor PDF)
|
||||
- `latex2html`
|
||||
- `python3-sphinx`
|
||||
- `libjs-mathjax`
|
||||
- `doxygen`
|
||||
|
||||
You can install them all at once with:
|
||||
```
|
||||
apt install build-essential gfortran liboctave-dev libboost-graph-dev libboost-filesystem-dev libgsl-dev libmatio-dev libslicot-dev libslicot-pic libsuitesparse-dev flex bison autoconf automake texlive texlive-publishers texlive-extra-utils texlive-formats-extra texlive-latex-extra texlive-fonts-extra texlive-latex-recommended texlive-science texinfo lmodern latex2html doxygen
|
||||
apt install build-essential gfortran liboctave-dev libboost-graph-dev libgsl-dev libmatio-dev libslicot-dev libslicot-pic libsuitesparse-dev flex bison autoconf automake texlive texlive-publishers texlive-latex-extra texlive-fonts-extra texlive-latex-recommended texlive-science texlive-generic-extra lmodern python3-sphinx libjs-mathjax doxygen
|
||||
```
|
||||
|
||||
## Windows
|
||||
|
||||
- Install [MSYS2](http://www.msys2.org) (pick the 64-bit version)
|
||||
- Install [MSYS2](http://www.msys2.org) (pick the 64-bit version, unless you
|
||||
have a 32-bit Windows, in which case see below)
|
||||
- Run a MSYS MinGW 64-bit shell
|
||||
- Update the system:
|
||||
```
|
||||
|
@ -247,18 +261,6 @@ pacman -Syu
|
|||
```
|
||||
pacman -S git autoconf automake-wrapper bison flex make tar texinfo mingw-w64-x86_64-gcc mingw-w64-x86_64-gcc-fortran mingw-w64-x86_64-boost mingw-w64-x86_64-gsl mingw-w64-x86_64-matio mingw-w64-x86_64-openblas
|
||||
```
|
||||
- **(Optional)** compile and install `ctangle`, needed for the k-order MEX file and for
|
||||
Dynare++ (*i.e.* if you want to solve models at order ≥ 3)
|
||||
```
|
||||
wget ftp://ftp.cs.stanford.edu/pub/cweb/cweb.tar.gz
|
||||
mkdir cweb
|
||||
cd cweb
|
||||
tar xf ../cweb.tar.gz
|
||||
make ctangle
|
||||
mkdir -p /usr/local/bin
|
||||
cp ctangle.exe /usr/local/bin/
|
||||
cd ..
|
||||
```
|
||||
- **(Optional)** compile and install SLICOT, needed for the `kalman_steady_state`
|
||||
MEX file
|
||||
```
|
||||
|
@ -272,13 +274,13 @@ cd ..
|
|||
```
|
||||
- Clone and prepare the Dynare sources:
|
||||
```
|
||||
git clone --recursive https://git.dynare.org/Dynare/dynare.git
|
||||
git clone --recurse-submodules https://git.dynare.org/Dynare/dynare.git
|
||||
cd dynare
|
||||
autoreconf -si
|
||||
```
|
||||
- Configure Dynare:
|
||||
```
|
||||
./configure --with-boost-system=boost_system-mt --with-boost-filesystem=boost_filesystem-mt --with-slicot=/usr/local --with-matlab=<…> MATLAB_VERSION=<…> --disable-octave
|
||||
./configure --with-slicot=/usr/local --with-matlab=<…> MATLAB_VERSION=<…> --disable-octave
|
||||
```
|
||||
where the path and version of MATLAB are specified. Note that you should use
|
||||
the MSYS2 notation and not put spaces in the MATLAB path, so you probably want
|
||||
|
@ -306,10 +308,10 @@ currently not supported.
|
|||
## macOS
|
||||
|
||||
To simply use a snapshot of Dynare, you have two choices. On MATLAB, you can
|
||||
use the [snapshot build](http://www.dynare.org/snapshot/macosx/) provided by
|
||||
use the [snapshot build](https://www.dynare.org/snapshot/macos/) provided by
|
||||
Dynare. On Octave, you can simply install [Homebrew](https://brew.sh/) and run
|
||||
```brew install dynare --HEAD``` (See the Install Dynare (unstable) section of
|
||||
[this webpage](http://www.dynare.org/DynareWiki/InstallOnMacOSX) for more
|
||||
[this webpage](https://archives.dynare.org/DynareWiki/InstallOnMacOSX) for more
|
||||
details).
|
||||
|
||||
If you do not wish to use the snapshots provided by Dynare or Homebrew, follow
|
||||
|
@ -327,9 +329,6 @@ compile. They should be entered at the command prompt in Terminal.app.
|
|||
- `brew install automake bison flex boost fftw gcc gsl hdf5 libmatio metis veclibfort`
|
||||
- **(Optional)** To compile Dynare mex files for use on Octave:
|
||||
- `brew install octave`
|
||||
- `brew install suite-sparse`
|
||||
- **(Optional)** To compile Dynare++
|
||||
- `brew install cweb`
|
||||
- **(Optional)** To compile Dynare documentation
|
||||
- Install the latest version of [MacTeX](http://www.tug.org/mactex/), deselecting the option to install Ghostscript
|
||||
- `brew install doxygen latex2html`
|
||||
|
@ -338,13 +337,13 @@ The following commands will download the Dynare source code and compile
|
|||
it. They should be entered at the command prompt in Terminal.app from the
|
||||
folder where you want Dynare installed.
|
||||
|
||||
- `git clone https://git.dynare.org/Dynare/dynare.git`
|
||||
- `git clone --recurse-submodules https://git.dynare.org/Dynare/dynare.git`
|
||||
- `cd dynare`
|
||||
- `PATH="/usr/local/opt/bison/bin:/usr/local/opt/flex/bin:$PATH"`
|
||||
- `autoreconf -si`
|
||||
- `./configure --disable-octave --with-matlab=/Applications/MATLAB_R2017b.app MATLAB_VERSION=R2017b`, adjusting the MATLAB path and version to accord with your local installation. If you don't have MATLAB, simply type `./configure --disable-octave`
|
||||
- `CC=gcc-9 CXX=g++-9 ./configure --disable-octave --with-matlab=/Applications/MATLAB_R2019a.app MATLAB_VERSION=R2019a --with-matio=/usr/local --with-gsl=/usr/local --with-slicot=/usr/local`, adjusting the MATLAB path and version to accord with your local installation. If you don't have MATLAB, simply remove `--with-matlab=/Applications/MATLAB_R2019a.app MATLAB_VERSION=R2019a` from the above command
|
||||
- `make -j`
|
||||
- **(Optional)** To then build mex files for Octave, run
|
||||
- `cd mex/build/octave`
|
||||
- `./configure CXXFLAGS="-std=c++0x"`
|
||||
- `CC=gcc-9 CXX=g++-9 ./configure --with-matio=/usr/local --with-gsl=/usr/local --with-slicot=/usr/local LDFLAGS=-L/usr/local/lib`
|
||||
- `make -j`
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
In branch extended-preprocessor, we develop a version of Dynare
|
||||
preprocessor that produces C and Cuda routine that can be later
|
||||
linked within another program.
|
||||
|
||||
* dynare_m options
|
||||
- new option output=dynamic|first|second|third
|
||||
- output=dynamic generates <fname>_dynamic
|
||||
- output=first generates <fname>_first_derivatives
|
||||
- output=second generates <fname>_first_derivatives and <fname>_second_derivatives
|
||||
- output=third generates <fname>_first_derivatives,
|
||||
<fname>_second_derivatives and <fname>_third_derivatives
|
||||
- routine <fname>_static is always generated
|
||||
- routine <fname>_steady_state is generated if the *.mod file contains a
|
||||
steady_state_model block
|
||||
- routine <fname>_auxiliary_variables_steady_state is always
|
||||
generated but doesn't contain any instruction is the preprocessor
|
||||
didn't add any auxiliary variable
|
||||
* Functions
|
||||
- <fname>_model: returns a structure containting fields describing
|
||||
the model, analogous to the M_ structure in Dynare. This structure
|
||||
is defined in dynare_model.h and must be accessible when compiling
|
||||
the second stage program.
|
||||
- <fname>_dynamic: the historical Dynare dynamic function, returns
|
||||
residuals, first, second and third order derivatives of the model,
|
||||
if needed.
|
||||
- <fname>_static: the historical Dynare static function, returns
|
||||
residuals of the static model
|
||||
- <fname>_steady_state: a function computing the steady state of the
|
||||
model, given the parameters. It comes from parsing a
|
||||
steady_state_model block in the *.mod file. Currently, there is no provision for
|
||||
calling a non-linear solver for a subset of equations/variables.
|
||||
- <fname>_auxiliary_variables_steady_state: a function to compute the steady state
|
||||
values of auxiliary variables automatically added by the
|
||||
preprocessor
|
||||
- <fname>_first_derivatives: returns the Jacobian of the model at the steady
|
||||
state, given the
|
||||
steady state. It is more efficient than <fname>_dynamic. Doesn't
|
||||
exist in Dynare yet.
|
||||
- <fname>_second_derivatives: returns the second order derivatives of
|
||||
the model. There are as many rows as equations and as many column
|
||||
as the square of the number of endogenous and exogenous
|
||||
variables. The matrix is stored in compressed sparse row format. It
|
||||
is more efficient than compressed column format as there many more
|
||||
columns than rows and many columns are empty. Note that the
|
||||
transpose of the second derivatives matrix in compressed column
|
||||
format can be obtained directly from the same function by inverting
|
||||
the role of the two index vectors.
|
||||
- <fname>_third_derivatives: returns the third order derivatives of
|
||||
the model. See above for the storage format of this matrix.
|
||||
* Implementation
|
||||
** C++ version
|
||||
- the routines use C++ and classes from the STL
|
||||
** Cuda version
|
||||
- the routines have the __global__ keyword necessary to create CUDA
|
||||
kernls
|
||||
- vector addressing uses a stride parameter to allow for various
|
||||
storage schemes on the device
|
||||
* Changes with dynare-msdsge
|
||||
- removed erasing previous files as all files should be always
|
||||
written to faciliate application building
|
||||
- added back creating variables with the parameter name (otherwise
|
||||
it doesn't work in Matlab backend) TO BE FIXED
|
||||
* Pre-processor
|
||||
- in DynareMain2.cc, in main2() option output != none calls ModFile::write_external_files()
|
||||
- in ModFile.cc, ModFile::writeExternalFiles() calls
|
||||
- ModFile::writeModelCC()
|
||||
- SteadyStateMode::writeSteadyStateFileCC()
|
||||
- DynamicModel::writeDynamicFile()
|
||||
- StaticModel::writeStaticFile()
|
||||
- DynamicModel::writeResidualsCC()
|
||||
- DynamicModel::writeParamsDerivativesFileCC()
|
||||
- DynamicModel::writeFirstDerivativesCC()
|
||||
- DynamicModel::writeSecondDerivativesCC_csr()
|
||||
- DynamicModel::writeThirdDerivativesCC_csr()
|
||||
|
141
configure.ac
141
configure.ac
|
@ -1,6 +1,6 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
dnl Copyright (C) 2009-2018 Dynare Team
|
||||
dnl Copyright © 2009-2019 Dynare Team
|
||||
dnl
|
||||
dnl This file is part of Dynare.
|
||||
dnl
|
||||
|
@ -26,6 +26,7 @@ AC_CONFIG_SUBDIRS([preprocessor])
|
|||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AX_CXX_COMPILE_STDCXX_17
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
case ${host_os} in
|
||||
|
@ -33,25 +34,23 @@ case ${host_os} in
|
|||
# On Windows, we want Dynare++ to be statically linked
|
||||
AM_LDFLAGS="-static"
|
||||
AC_SUBST([AM_LDFLAGS])
|
||||
have_windows="yes"
|
||||
;;
|
||||
*cygwin*)
|
||||
AC_MSG_WARN([You are compiling for the Cygwin target. This means that the preprocessor will])
|
||||
AC_MSG_WARN([not run from MATLAB unless you add the Cygwin DLL to the path.])
|
||||
AC_MSG_WARN([This is probably not what you want. Consider using a MinGW cross-compiler.])
|
||||
if test "x$F77" = "x"; then
|
||||
if test -z "$F77"; then
|
||||
# On Cygwin 1.7, g77 comes has version 3, and is not compatible with default gcc/g++ which has version 4
|
||||
# And by default, the AC_PROG_F77 will pick up g77 if it is present (even if gfortran is also here)
|
||||
F77=gfortran
|
||||
fi
|
||||
have_windows="yes"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Use C++ for testing headers
|
||||
AC_LANG([C++])
|
||||
|
||||
AM_CXXFLAGS="-Wall -Wno-parentheses"
|
||||
AM_CXXFLAGS="-Wall -Wno-parentheses -Wold-style-cast"
|
||||
AC_SUBST([AM_CXXFLAGS])
|
||||
|
||||
# If default 'ar' is not available, try to find one with a host prefix (see ticket #145)
|
||||
|
@ -64,64 +63,33 @@ AX_PROG_LN_S
|
|||
|
||||
AC_PROG_MKDIR_P
|
||||
|
||||
# We need 1.36 because of unordered_{set,hash} used by Dynare++
|
||||
AX_BOOST_BASE([1.36], [], [AC_MSG_ERROR([Can't find Boost >= 1.36])])
|
||||
AX_CXX11_THREAD
|
||||
|
||||
CPPFLAGS_SAVED="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
|
||||
AC_CHECK_HEADERS([boost/graph/adjacency_list.hpp], [], [AC_MSG_ERROR([Can't find Boost Graph Library])])
|
||||
AC_CHECK_HEADERS([boost/algorithm/string/trim.hpp], [], [AC_MSG_ERROR([Can't find Boost String Library])])
|
||||
AC_CHECK_HEADERS([boost/algorithm/string/split.hpp], [], [AC_MSG_ERROR([Can't find Boost String Library])])
|
||||
AC_CHECK_HEADERS([boost/lexical_cast.hpp], [], [AC_MSG_ERROR([Can't find Boost Lexical Cast Header])])
|
||||
CPPFLAGS="$CPPFLAGS_SAVED"
|
||||
AM_PROG_LEX
|
||||
|
||||
# Don't use deprecated hash structures
|
||||
AC_DEFINE([BOOST_NO_HASH], [], [Don't use deprecated STL hash structures])
|
||||
AC_CHECK_PROG([YACC], [bison], [bison])
|
||||
if test -z "$YACC"; then
|
||||
unset YACC # AM_MISSING_PROG needs an unset variable: an empty variable won't do
|
||||
AM_MISSING_PROG([YACC], [bison])
|
||||
fi
|
||||
|
||||
# Check for libmatio, needed by Dynare++
|
||||
AX_MATIO
|
||||
AM_CONDITIONAL([HAVE_MATIO], [test "x$has_matio" = "xyes"])
|
||||
|
||||
AC_CHECK_PROG([MAKEINFO], [makeinfo], [makeinfo])
|
||||
|
||||
AC_CHECK_PROG([PDFTEX], [pdftex], [pdftex])
|
||||
AM_CONDITIONAL([HAVE_PDFTEX], [test "x$PDFTEX" != "x"])
|
||||
|
||||
AC_CHECK_PROG([PDFETEX], [pdfetex], [pdfetex])
|
||||
AM_CONDITIONAL([HAVE_PDFETEX], [test "x$PDFETEX" != "x"])
|
||||
|
||||
if test "x$PDFTEX" != "x"; then
|
||||
AC_MSG_CHECKING([for eplain])
|
||||
AX_TEX_TEST([\input eplain
|
||||
\end
|
||||
], [ax_tex_have_eplain])
|
||||
AC_MSG_RESULT([$ax_tex_have_eplain])
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_EPLAIN], [test "x$ax_tex_have_eplain" = "xyes"])
|
||||
AM_CONDITIONAL([HAVE_MATIO], [test "$has_matio" = yes])
|
||||
|
||||
AC_CHECK_PROG([PDFLATEX], [pdflatex], [pdflatex])
|
||||
AM_CONDITIONAL([HAVE_PDFLATEX], [test "x$PDFLATEX" != "x"])
|
||||
AM_CONDITIONAL([HAVE_PDFLATEX], [test -n "$PDFLATEX"])
|
||||
|
||||
AC_CHECK_PROG([BIBTEX], [bibtex], [bibtex])
|
||||
AM_CONDITIONAL([HAVE_BIBTEX], [test "x$BIBTEX" != "x"])
|
||||
AM_CONDITIONAL([HAVE_BIBTEX], [test -n "$BIBTEX"])
|
||||
|
||||
AC_CHECK_PROG([LATEX2HTML], [latex2html], [latex2html])
|
||||
AM_CONDITIONAL([HAVE_LATEX2HTML], [test "x$LATEX2HTML" != "x"])
|
||||
AC_CHECK_PROG([SPHINXBUILD], [sphinx-build], [sphinx-build])
|
||||
AM_CONDITIONAL([HAVE_SPHINXBUILD], [test -n "$SPHINXBUILD"])
|
||||
|
||||
if test "x$PDFLATEX" != "x" -a "x$BIBTEX" != "x"; then
|
||||
if test -n "$PDFLATEX" -a -n "$BIBTEX"; then
|
||||
AX_LATEX_CLASS([beamer], [ax_latex_have_beamer])
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_BEAMER], [test "x$ax_latex_have_beamer" = "xyes"])
|
||||
|
||||
AC_CHECK_PROG([CTANGLE], [ctangle], [ctangle])
|
||||
AM_CONDITIONAL([HAVE_CTANGLE], [test "x$CTANGLE" != "x"])
|
||||
if test "x$CTANGLE" = "x"; then
|
||||
unset CTANGLE # AM_MISSING_PROG needs an unset variable: an empty variable won't do
|
||||
AM_MISSING_PROG([CTANGLE], [ctangle])
|
||||
fi
|
||||
|
||||
AC_CHECK_PROG([CWEAVE], [cweave], [cweave])
|
||||
AM_CONDITIONAL([HAVE_CWEAVE], [test "x$CWEAVE" != "x"])
|
||||
AM_CONDITIONAL([HAVE_BEAMER], [test "$ax_latex_have_beamer" = yes])
|
||||
|
||||
AC_PROG_F77
|
||||
AC_F77_LIBRARY_LDFLAGS
|
||||
|
@ -133,25 +101,24 @@ case ${host_os} in
|
|||
;;
|
||||
esac
|
||||
|
||||
if test "x$F77" != "x"; then
|
||||
if test -n "$F77"; then
|
||||
AX_BLAS
|
||||
AX_LAPACK
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_BLAS], [test x"$ax_blas_ok" = "xyes"])
|
||||
AM_CONDITIONAL([HAVE_LAPACK], [test x"$ax_lapack_ok" = "xyes"])
|
||||
|
||||
AX_PTHREAD
|
||||
AM_CONDITIONAL([HAVE_BLAS], [test "$ax_blas_ok" = yes])
|
||||
AM_CONDITIONAL([HAVE_LAPACK], [test "$ax_lapack_ok" = yes])
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
VERSION
|
||||
doc/Makefile
|
||||
doc/manual/Makefile
|
||||
doc/manual/utils/version.py
|
||||
doc/parallel/Makefile
|
||||
doc/internals/Makefile
|
||||
doc/gsa/Makefile
|
||||
doc/dseries-and-reporting/Makefile
|
||||
tests/Makefile
|
||||
matlab/dynare_version.m
|
||||
windows/dynare-version.nsi
|
||||
dynare++/Makefile
|
||||
dynare++/parser/cc/Makefile
|
||||
dynare++/sylv/Makefile
|
||||
|
@ -168,56 +135,41 @@ AC_CONFIG_FILES([Makefile
|
|||
dynare++/integ/testing/Makefile
|
||||
dynare++/kord/Makefile
|
||||
dynare++/src/Makefile
|
||||
dynare++/tests/Makefile
|
||||
mex/sources/Makefile
|
||||
])
|
||||
|
||||
AC_ARG_ENABLE([matlab], AS_HELP_STRING([--disable-matlab], [disable compilation of MEX files for MATLAB]), [], [enable_matlab=yes])
|
||||
if test "x$enable_matlab" = "xyes"; then
|
||||
if test "$enable_matlab" = yes; then
|
||||
AC_CONFIG_SUBDIRS([mex/build/matlab])
|
||||
AX_MATLAB
|
||||
AX_MATLAB_ARCH
|
||||
if test "${MATLAB_ARCH}" = win32 -o "${MATLAB_ARCH}" = win64; then
|
||||
MATLAB_BATCH_OPTIONS='-nosplash -automation -wait -sd "$(CURDIR)"'
|
||||
else
|
||||
MATLAB_BATCH_OPTIONS='-nosplash -nodisplay'
|
||||
fi
|
||||
AC_SUBST([MATLAB_BATCH_OPTIONS])
|
||||
AX_MATLAB_BATCH_OPTIONS
|
||||
fi
|
||||
AM_CONDITIONAL([ENABLE_MATLAB], [test "x$enable_matlab" = "xyes"])
|
||||
AM_CONDITIONAL([HAVE_CMD_LINE_MATLAB], [test "x$ax_enable_matlab" = "xyes" -a "x$have_windows" = "x"])
|
||||
AM_CONDITIONAL([ENABLE_MATLAB], [test "$enable_matlab" = yes])
|
||||
AM_CONDITIONAL([HAVE_MATLAB], [test "$ax_enable_matlab" = yes])
|
||||
|
||||
AC_ARG_ENABLE([octave], AS_HELP_STRING([--disable-octave], [disable compilation of MEX files for Octave]), [], [enable_octave=yes])
|
||||
if test "x$enable_octave" = "xyes"; then
|
||||
if test "$enable_octave" = yes; then
|
||||
AC_CONFIG_SUBDIRS([mex/build/octave])
|
||||
AC_CHECK_PROG([OCTAVE], [octave], [octave])
|
||||
fi
|
||||
AM_CONDITIONAL([ENABLE_OCTAVE], [test "x$enable_octave" = "xyes"])
|
||||
AM_CONDITIONAL([HAVE_OCTAVE], [test "x$enable_octave" = "xyes" -a "x$OCTAVE" != "x"])
|
||||
AM_CONDITIONAL([ENABLE_OCTAVE], [test "$enable_octave" = yes])
|
||||
AM_CONDITIONAL([HAVE_OCTAVE], [test "$enable_octave" = yes -a -n "$OCTAVE"])
|
||||
|
||||
# Enable exporting of Org files
|
||||
# The clean way would be to test for Emacs, Org-mode, latex, dvipng...
|
||||
AC_ARG_ENABLE([org-export], AS_HELP_STRING([--enable-org-export], [enable exporting of Org files (requires Emacs, org-mode and other external programs)]))
|
||||
AM_CONDITIONAL([ENABLE_ORG_EXPORT], [test "x$enable_org_export" != "x"])
|
||||
AM_CONDITIONAL([ENABLE_ORG_EXPORT], [test -n "$enable_org_export"])
|
||||
|
||||
# Construct final output message
|
||||
|
||||
if test "x$ax_blas_ok" = "xyes" -a "x$ax_lapack_ok" = "xyes" -a "x$has_matio" = "xyes"; then
|
||||
if test x"$ax_pthread_ok" = "xyes"; then
|
||||
BUILD_DYNAREPLUSPLUS="yes"
|
||||
else
|
||||
BUILD_DYNAREPLUSPLUS="yes (without POSIX threads)"
|
||||
fi
|
||||
if test "$ax_blas_ok" = yes -a "$ax_lapack_ok" = yes -a "$has_matio" = yes; then
|
||||
BUILD_DYNAREPLUSPLUS="yes"
|
||||
else
|
||||
BUILD_DYNAREPLUSPLUS="no (missing one of: BLAS, LAPACK, MatIO)"
|
||||
fi
|
||||
|
||||
if test "x$CWEAVE" != "x" -a x"$PDFTEX" != "x" -a "x$ax_tex_have_eplain" = "xyes"; then
|
||||
BUILD_DYNAREPLUSPLUS_SRCDOC="yes"
|
||||
else
|
||||
BUILD_DYNAREPLUSPLUS_SRCDOC="no (missing one of: cweave, pdftex, eplain)"
|
||||
fi
|
||||
|
||||
if test "x$PDFLATEX" != "x" -a "x$ax_latex_have_beamer" = "xyes"; then
|
||||
if test -n "$PDFLATEX" -a "$ax_latex_have_beamer" = yes; then
|
||||
BUILD_BEAMER_DOC="yes"
|
||||
else
|
||||
BUILD_BEAMER_DOC="no (missing one of: pdflatex, beamer)"
|
||||
|
@ -229,33 +181,27 @@ else
|
|||
BUILD_OTHER_PDF_DOC="no (missing pdflatex)"
|
||||
fi
|
||||
|
||||
if test "x$enable_org_export" != "x"; then
|
||||
if test -n "$enable_org_export"; then
|
||||
BUILD_DYNARE_INTERNAL_DOC="yes"
|
||||
else
|
||||
BUILD_DYNARE_INTERNAL_DOC="no (Org export not enabled)"
|
||||
fi
|
||||
|
||||
if test "x$MAKEINFO" != "x"; then
|
||||
BUILD_DYNARE_INFO="yes"
|
||||
if test "x$LATEX2HTML" != "x"; then
|
||||
BUILD_DYNARE_HTML_MANUAL="yes"
|
||||
else
|
||||
BUILD_DYNARE_HTML_MANUAL="yes (but with ugly math formulas, missing latex2html)"
|
||||
fi
|
||||
if test -n "$SPHINXBUILD"; then
|
||||
BUILD_DYNARE_HTML_MANUAL="yes"
|
||||
BUILD_DYNARE_PDF_MANUAL="yes"
|
||||
else
|
||||
BUILD_DYNARE_INFO="no (missing makeinfo)"
|
||||
BUILD_DYNARE_HTML_MANUAL="no (missing makeinfo)"
|
||||
BUILD_DYNARE_PDF_MANUAL="no (missing makeinfo)"
|
||||
BUILD_DYNARE_HTML_MANUAL="no (missing sphinx-build)"
|
||||
BUILD_DYNARE_PDF_MANUAL="no (missing sphinx-build)"
|
||||
fi
|
||||
|
||||
if test "x$OCTAVE" != "x"; then
|
||||
if test -n "$OCTAVE"; then
|
||||
TESTSUITE_OCTAVE="yes"
|
||||
else
|
||||
TESTSUITE_OCTAVE="no"
|
||||
fi
|
||||
|
||||
if test "x$ax_blas_ok" = "xyes" -a "x$ax_lapack_ok" = "xyes"; then
|
||||
if test "$ax_blas_ok" = yes -a "$ax_lapack_ok" = yes; then
|
||||
TESTSUITE_DYNAREPLUSPLUS="yes"
|
||||
else
|
||||
TESTSUITE_DYNAREPLUSPLUS="no"
|
||||
|
@ -270,7 +216,6 @@ Binaries (with "make"):
|
|||
|
||||
PDF documentation (with "make pdf"):
|
||||
Dynare reference manual: $BUILD_DYNARE_PDF_MANUAL
|
||||
Dynare++ developer documentation: $BUILD_DYNAREPLUSPLUS_SRCDOC
|
||||
Beamer presentations: $BUILD_BEAMER_DOC
|
||||
Various other documents: $BUILD_OTHER_PDF_DOC
|
||||
|
||||
|
@ -278,8 +223,6 @@ HTML documentation (with "make html"):
|
|||
Dynare reference manual: $BUILD_DYNARE_HTML_MANUAL
|
||||
Dynare internal doc: $BUILD_DYNARE_INTERNAL_DOC
|
||||
|
||||
Info documentation (with "make info"): $BUILD_DYNARE_INFO
|
||||
|
||||
Testsuites (run with "make check"):
|
||||
Dynare for Octave: $TESTSUITE_OCTAVE
|
||||
Dynare++: $TESTSUITE_DYNAREPLUSPLUS
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 31b5bdc283f54733dca6352c760cd363878886e1
|
||||
Subproject commit d2b2421f1d70dae079238c9a6412b5e0825ee0ef
|
|
@ -1 +1 @@
|
|||
Subproject commit ce173d3fa2605957f7208bf624655893a7dc1768
|
||||
Subproject commit f1d0fd61ea6d9c4f8694b373780d6c372e344f6e
|
|
@ -1,15 +1,7 @@
|
|||
SUBDIRS = parallel internals gsa dseries-and-reporting
|
||||
|
||||
info_TEXINFOS = dynare.texi
|
||||
|
||||
if HAVE_LATEX2HTML
|
||||
html-local: dynare.html
|
||||
|
||||
# The temporary directory for latex2html (L2H_TMP) must not contain a dot, so
|
||||
# enforce standard tmp directory instead of defaulting to current directory
|
||||
dynare.html: dynare.texi
|
||||
rm -rf dynare.html
|
||||
texi2any --html --split=section -c L2H=1 -c L2H_TMP=$${TMPDIR:-/tmp} -c PREFIX=dynare.html dynare.texi
|
||||
if HAVE_SPHINXBUILD
|
||||
SUBDIRS += manual
|
||||
endif
|
||||
|
||||
PDF_TARGETS =
|
||||
|
|
15356
doc/dynare.texi
15356
doc/dynare.texi
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,18 @@
|
|||
EXTRA_DIST = source \
|
||||
utils/dynare_dom.py \
|
||||
utils/dynare_lex.py
|
||||
|
||||
SRC = $(wildcard source/*.rst)
|
||||
|
||||
html-local: build/html/index.html
|
||||
|
||||
build/html/index.html: $(SRC) source/conf.py
|
||||
$(SPHINXBUILD) -M html source build
|
||||
|
||||
pdf-local: build/latex/dynare-manual.pdf
|
||||
|
||||
build/latex/dynare-manual.pdf: $(SRC) source/conf.py
|
||||
$(SPHINXBUILD) -M latexpdf source build
|
||||
|
||||
clean-local:
|
||||
rm -rf build
|
|
@ -0,0 +1,41 @@
|
|||
div.sphinxsidebar {
|
||||
float: left;
|
||||
width: 230px;
|
||||
font-size: 90%;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap : break-word;
|
||||
overflow-y: scroll;
|
||||
scrollbar-width: none; /* Firefox */
|
||||
-ms-overflow-style: none; /* IE 10+ */
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar::-webkit-scrollbar { /* WebKit */
|
||||
width: 0px;
|
||||
}
|
||||
|
||||
|
||||
div.sphinxsidebarwrapper p.logo {
|
||||
padding: 0;
|
||||
margin: -10px 0 0 0px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.body {
|
||||
min-width: 450px;
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
.property{
|
||||
display:inline-block;
|
||||
text-decoration: underline;
|
||||
text-decoration-style: double;
|
||||
padding-right: 10px;
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 15px 30px;
|
||||
padding: 0;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86.514pt" height="34.182pt" viewBox="0 0 86.514 34.182" version="1.1">
|
||||
<defs>
|
||||
<g>
|
||||
<symbol overflow="visible" id="glyph0-0">
|
||||
<path style="stroke:none;" d="M 3.09375 -14.140625 L 3.6875 -13.203125 C 3.78125 -13.015625 3.921875 -12.921875 4.140625 -12.921875 C 4.21875 -12.921875 4.328125 -12.953125 4.453125 -13.03125 C 4.5625 -13.109375 4.703125 -13.1875 4.875 -13.28125 C 5.03125 -13.375 5.234375 -13.453125 5.46875 -13.53125 C 5.6875 -13.609375 5.96875 -13.640625 6.3125 -13.640625 C 6.796875 -13.640625 7.171875 -13.515625 7.46875 -13.265625 C 7.765625 -13.015625 7.9375 -12.6875 7.9375 -12.265625 C 7.9375 -11.9375 7.859375 -11.640625 7.734375 -11.40625 C 7.59375 -11.15625 7.4375 -10.953125 7.234375 -10.765625 C 7.03125 -10.5625 6.8125 -10.390625 6.59375 -10.234375 C 6.375 -10.0625 6.15625 -9.890625 5.96875 -9.71875 C 5.78125 -9.546875 5.640625 -9.34375 5.53125 -9.125 C 5.421875 -8.921875 5.390625 -8.671875 5.421875 -8.40625 L 5.578125 -6.953125 L 7.09375 -6.953125 L 7.296875 -8.25 C 7.328125 -8.4375 7.40625 -8.609375 7.5625 -8.765625 C 7.703125 -8.90625 7.875 -9.0625 8.078125 -9.234375 C 8.28125 -9.375 8.484375 -9.546875 8.703125 -9.734375 C 8.9375 -9.90625 9.125 -10.109375 9.3125 -10.359375 C 9.5 -10.609375 9.671875 -10.890625 9.78125 -11.21875 C 9.90625 -11.546875 9.96875 -11.9375 9.96875 -12.40625 C 9.96875 -12.859375 9.890625 -13.28125 9.71875 -13.65625 C 9.546875 -14.03125 9.3125 -14.34375 9.015625 -14.625 C 8.703125 -14.875 8.34375 -15.078125 7.921875 -15.234375 C 7.5 -15.375 7.03125 -15.453125 6.5 -15.453125 C 6.125 -15.453125 5.765625 -15.40625 5.4375 -15.34375 C 5.125 -15.265625 4.8125 -15.171875 4.53125 -15.046875 C 4.25 -14.9375 3.984375 -14.796875 3.75 -14.640625 C 3.515625 -14.484375 3.296875 -14.3125 3.09375 -14.140625 Z M 4.90625 -3.625 C 4.90625 -3.21875 5.03125 -2.90625 5.296875 -2.640625 C 5.53125 -2.375 5.875 -2.25 6.265625 -2.25 C 6.4375 -2.25 6.609375 -2.28125 6.796875 -2.359375 C 6.953125 -2.421875 7.09375 -2.53125 7.21875 -2.65625 C 7.328125 -2.78125 7.421875 -2.90625 7.5 -3.078125 C 7.578125 -3.25 7.609375 -3.421875 7.609375 -3.625 C 7.609375 -3.796875 7.578125 -3.984375 7.5 -4.15625 C 7.421875 -4.328125 7.328125 -4.46875 7.21875 -4.59375 C 7.09375 -4.71875 6.953125 -4.8125 6.796875 -4.875 C 6.609375 -4.953125 6.4375 -5 6.265625 -5 C 5.875 -5 5.53125 -4.859375 5.296875 -4.59375 C 5.03125 -4.328125 4.90625 -4 4.90625 -3.625 Z M 0.5625 -17.75 L 0.5625 0 L 12.625 0 L 12.625 -17.75 Z M 1.171875 -0.671875 L 1.171875 -17.078125 L 11.921875 -17.078125 L 11.921875 -0.671875 Z M 1.171875 -0.671875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-1">
|
||||
<path style="stroke:none;" d="M 17.65625 -8.875 C 17.65625 -10.203125 17.453125 -11.40625 17.03125 -12.5 C 16.609375 -13.59375 16.015625 -14.515625 15.234375 -15.296875 C 14.46875 -16.078125 13.546875 -16.6875 12.46875 -17.109375 C 11.390625 -17.53125 10.203125 -17.75 8.890625 -17.75 L 2.265625 -17.75 L 2.265625 0 L 8.890625 0 C 10.203125 0 11.390625 -0.203125 12.46875 -0.625 C 13.546875 -1.046875 14.46875 -1.65625 15.234375 -2.4375 C 16.015625 -3.203125 16.609375 -4.15625 17.03125 -5.234375 C 17.453125 -6.328125 17.65625 -7.53125 17.65625 -8.875 Z M 15.1875 -8.875 C 15.1875 -7.78125 15.046875 -6.796875 14.75 -5.953125 C 14.453125 -5.078125 14.03125 -4.359375 13.484375 -3.765625 C 12.9375 -3.171875 12.265625 -2.71875 11.5 -2.421875 C 10.71875 -2.09375 9.84375 -1.953125 8.890625 -1.953125 L 4.671875 -1.953125 L 4.671875 -15.8125 L 8.890625 -15.8125 C 9.84375 -15.8125 10.71875 -15.65625 11.5 -15.34375 C 12.265625 -15.015625 12.9375 -14.578125 13.484375 -13.984375 C 14.03125 -13.375 14.453125 -12.65625 14.75 -11.796875 C 15.046875 -10.921875 15.1875 -9.96875 15.1875 -8.875 Z M 15.1875 -8.875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-2">
|
||||
<path style="stroke:none;" d="M 12.578125 -12.546875 L 10.828125 -12.546875 C 10.6875 -12.546875 10.546875 -12.5 10.421875 -12.421875 C 10.296875 -12.328125 10.21875 -12.21875 10.171875 -12.09375 L 6.90625 -4.203125 C 6.78125 -3.859375 6.65625 -3.484375 6.546875 -3.09375 C 6.4375 -3.46875 6.328125 -3.84375 6.203125 -4.1875 L 2.84375 -12.09375 C 2.796875 -12.203125 2.71875 -12.296875 2.609375 -12.40625 C 2.5 -12.5 2.359375 -12.546875 2.171875 -12.546875 L 0.265625 -12.546875 L 5.4375 -0.734375 L 3.140625 4.25 L 4.78125 4.25 C 5 4.25 5.171875 4.203125 5.296875 4.09375 C 5.40625 4 5.5 3.875 5.578125 3.703125 Z M 12.578125 -12.546875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-3">
|
||||
<path style="stroke:none;" d="M 3.828125 -10.734375 L 3.65625 -12.09375 C 3.578125 -12.390625 3.375 -12.546875 3.078125 -12.546875 L 1.75 -12.546875 L 1.75 0 L 3.96875 0 L 3.96875 -9.25 C 4.4375 -9.78125 4.953125 -10.203125 5.53125 -10.515625 C 6.09375 -10.828125 6.703125 -10.984375 7.359375 -10.984375 C 8.234375 -10.984375 8.890625 -10.71875 9.328125 -10.203125 C 9.765625 -9.671875 9.984375 -8.9375 9.984375 -7.984375 L 9.984375 0 L 12.203125 0 L 12.203125 -7.984375 C 12.203125 -8.703125 12.109375 -9.34375 11.9375 -9.9375 C 11.75 -10.515625 11.46875 -11.015625 11.125 -11.4375 C 10.78125 -11.859375 10.328125 -12.1875 9.8125 -12.40625 C 9.296875 -12.625 8.6875 -12.75 8 -12.75 C 7.5625 -12.75 7.140625 -12.703125 6.75 -12.59375 C 6.375 -12.5 6.015625 -12.359375 5.65625 -12.1875 C 5.3125 -12.015625 5 -11.8125 4.703125 -11.5625 C 4.390625 -11.3125 4.09375 -11.03125 3.828125 -10.734375 Z M 3.828125 -10.734375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-4">
|
||||
<path style="stroke:none;" d="M 8.546875 -5.65625 L 8.546875 -3.046875 C 8.296875 -2.78125 8.046875 -2.546875 7.78125 -2.34375 C 7.515625 -2.125 7.25 -1.953125 6.96875 -1.8125 C 6.671875 -1.65625 6.375 -1.53125 6.0625 -1.46875 C 5.734375 -1.390625 5.375 -1.34375 5 -1.34375 C 4.703125 -1.34375 4.421875 -1.375 4.171875 -1.453125 C 3.921875 -1.53125 3.703125 -1.640625 3.515625 -1.78125 C 3.328125 -1.9375 3.1875 -2.125 3.078125 -2.375 C 2.96875 -2.609375 2.921875 -2.90625 2.921875 -3.234375 C 2.921875 -3.578125 3.015625 -3.890625 3.21875 -4.171875 C 3.421875 -4.453125 3.75 -4.703125 4.203125 -4.90625 C 4.640625 -5.109375 5.234375 -5.28125 5.953125 -5.40625 C 6.671875 -5.53125 7.53125 -5.609375 8.546875 -5.65625 Z M 1.421875 -10.78125 L 1.828125 -10.078125 C 1.890625 -9.953125 1.984375 -9.84375 2.09375 -9.78125 C 2.1875 -9.703125 2.328125 -9.671875 2.484375 -9.671875 C 2.65625 -9.671875 2.84375 -9.734375 3.046875 -9.859375 C 3.25 -10 3.46875 -10.140625 3.734375 -10.328125 C 4.015625 -10.5 4.328125 -10.640625 4.703125 -10.78125 C 5.0625 -10.921875 5.53125 -10.984375 6.078125 -10.984375 C 6.875 -10.984375 7.5 -10.734375 7.921875 -10.234375 C 8.34375 -9.734375 8.546875 -9 8.546875 -8.03125 L 8.546875 -7.046875 C 7.109375 -7.015625 5.90625 -6.875 4.9375 -6.65625 C 3.9375 -6.4375 3.140625 -6.140625 2.546875 -5.78125 C 1.921875 -5.421875 1.484375 -5.015625 1.21875 -4.5625 C 0.9375 -4.09375 0.8125 -3.625 0.8125 -3.140625 C 0.8125 -2.5625 0.890625 -2.0625 1.078125 -1.640625 C 1.265625 -1.234375 1.515625 -0.890625 1.828125 -0.625 C 2.15625 -0.34375 2.53125 -0.140625 2.96875 0 C 3.375 0.140625 3.84375 0.203125 4.34375 0.203125 C 4.8125 0.203125 5.234375 0.15625 5.640625 0.078125 C 6.03125 -0.015625 6.40625 -0.140625 6.75 -0.296875 C 7.09375 -0.453125 7.421875 -0.65625 7.75 -0.890625 C 8.046875 -1.125 8.375 -1.40625 8.703125 -1.703125 L 8.953125 -0.515625 C 9.015625 -0.3125 9.109375 -0.171875 9.234375 -0.09375 C 9.34375 -0.03125 9.5 0 9.734375 0 L 10.703125 0 L 10.703125 -8.03125 C 10.703125 -8.71875 10.609375 -9.375 10.421875 -9.96875 C 10.21875 -10.546875 9.953125 -11.046875 9.578125 -11.46875 C 9.203125 -11.875 8.75 -12.1875 8.203125 -12.421875 C 7.65625 -12.65625 7.03125 -12.78125 6.328125 -12.78125 C 5.359375 -12.78125 4.453125 -12.59375 3.671875 -12.28125 C 2.859375 -11.9375 2.125 -11.453125 1.421875 -10.78125 Z M 1.421875 -10.78125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-5">
|
||||
<path style="stroke:none;" d="M 3.84375 -10.03125 L 3.6875 -11.9375 C 3.65625 -12.171875 3.59375 -12.3125 3.5 -12.421875 C 3.40625 -12.5 3.25 -12.546875 3.015625 -12.546875 L 1.75 -12.546875 L 1.75 0 L 3.96875 0 L 3.96875 -7.9375 C 4.109375 -8.34375 4.28125 -8.734375 4.484375 -9.0625 C 4.6875 -9.40625 4.890625 -9.6875 5.140625 -9.90625 C 5.390625 -10.140625 5.65625 -10.3125 5.96875 -10.4375 C 6.28125 -10.546875 6.640625 -10.609375 7.03125 -10.609375 C 7.3125 -10.609375 7.578125 -10.578125 7.796875 -10.53125 C 8.015625 -10.484375 8.171875 -10.453125 8.296875 -10.453125 C 8.5 -10.453125 8.625 -10.5625 8.671875 -10.765625 L 8.828125 -12.421875 C 8.640625 -12.546875 8.421875 -12.625 8.171875 -12.6875 C 7.9375 -12.734375 7.6875 -12.78125 7.421875 -12.78125 C 6.578125 -12.78125 5.875 -12.53125 5.296875 -12.046875 C 4.71875 -11.5625 4.234375 -10.890625 3.84375 -10.03125 Z M 3.84375 -10.03125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-6">
|
||||
<path style="stroke:none;" d="M 10.140625 -7.640625 L 3.28125 -7.640625 C 3.4375 -8.734375 3.796875 -9.578125 4.421875 -10.203125 C 5.046875 -10.8125 5.875 -11.125 6.9375 -11.125 C 7.4375 -11.125 7.890625 -11.046875 8.296875 -10.859375 C 8.6875 -10.6875 9.015625 -10.453125 9.296875 -10.140625 C 9.5625 -9.84375 9.78125 -9.46875 9.921875 -9.046875 C 10.078125 -8.625 10.140625 -8.15625 10.140625 -7.640625 Z M 11.9375 -1.765625 L 11.3125 -2.5625 C 11.21875 -2.703125 11.0625 -2.78125 10.890625 -2.78125 C 10.75 -2.78125 10.578125 -2.703125 10.390625 -2.578125 C 10.1875 -2.453125 9.953125 -2.3125 9.671875 -2.171875 C 9.375 -2.015625 9.015625 -1.875 8.625 -1.75 C 8.234375 -1.625 7.75 -1.5625 7.203125 -1.5625 C 6.609375 -1.5625 6.0625 -1.640625 5.59375 -1.84375 C 5.109375 -2.046875 4.703125 -2.328125 4.34375 -2.71875 C 4 -3.125 3.734375 -3.609375 3.53125 -4.203125 C 3.328125 -4.78125 3.234375 -5.484375 3.203125 -6.265625 L 11.59375 -6.265625 C 11.796875 -6.265625 11.9375 -6.3125 12.015625 -6.4375 C 12.09375 -6.546875 12.125 -6.796875 12.125 -7.140625 C 12.125 -8.03125 12 -8.828125 11.734375 -9.515625 C 11.46875 -10.203125 11.109375 -10.796875 10.625 -11.28125 C 10.15625 -11.75 9.609375 -12.125 8.96875 -12.359375 C 8.328125 -12.609375 7.625 -12.75 6.890625 -12.75 C 5.96875 -12.75 5.15625 -12.59375 4.4375 -12.265625 C 3.703125 -11.9375 3.078125 -11.515625 2.59375 -10.953125 C 2.078125 -10.390625 1.703125 -9.734375 1.421875 -8.984375 C 1.15625 -8.21875 1.03125 -7.390625 1.03125 -6.53125 C 1.03125 -5.4375 1.171875 -4.484375 1.46875 -3.65625 C 1.765625 -2.8125 2.1875 -2.125 2.71875 -1.546875 C 3.25 -0.984375 3.875 -0.5625 4.609375 -0.265625 C 5.34375 0.03125 6.140625 0.171875 7.015625 0.171875 C 7.453125 0.171875 7.921875 0.140625 8.390625 0.0625 C 8.84375 -0.015625 9.296875 -0.140625 9.734375 -0.296875 C 10.15625 -0.453125 10.5625 -0.640625 10.953125 -0.890625 C 11.328125 -1.140625 11.65625 -1.421875 11.9375 -1.765625 Z M 11.9375 -1.765625 "/>
|
||||
</symbol>
|
||||
</g>
|
||||
<clipPath id="clip1">
|
||||
<path d="M 0 6 L 21 6 L 21 34.183594 L 0 34.183594 Z M 0 6 "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="surface1">
|
||||
<g style="fill:rgb(67.059326%,70.196533%,72.941589%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-1" x="3.32" y="24.072"/>
|
||||
</g>
|
||||
<g style="fill:rgb(67.059326%,70.196533%,72.941589%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-2" x="22.096228" y="24.072"/>
|
||||
<use xlink:href="#glyph0-3" x="34.873978" y="24.072"/>
|
||||
<use xlink:href="#glyph0-4" x="48.70518" y="24.072"/>
|
||||
<use xlink:href="#glyph0-5" x="61.024369" y="24.072"/>
|
||||
</g>
|
||||
<g style="fill:rgb(67.059326%,70.196533%,72.941589%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-6" x="69.551131" y="24.072"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(49.412537%,80.784607%,99.215698%);stroke-opacity:1;stroke-miterlimit:10;" d="M -13.322906 -17.010156 C -13.322906 -17.010156 0.782563 14.802344 5.384125 15.591406 C 9.985688 16.376563 16.891938 -8.35 19.841156 -11.338281 C 22.794281 -14.326562 24.798188 -6.029687 26.645844 -5.951562 C 28.4935 -5.873437 31.434906 -10.455469 33.165375 -10.771875 C 34.895844 -11.088281 37.505219 -8.299219 39.1185 -8.221094 C 40.731781 -8.142969 43.216156 -10.127344 44.786469 -10.205469 C 46.360687 -10.283594 48.884125 -8.865625 50.458344 -8.7875 C 52.028656 -8.709375 54.552094 -9.6 56.126312 -9.639062 C 57.700531 -9.678125 60.302094 -9.111719 61.794281 -9.072656 C 63.290375 -9.033594 66.89975 -9.353906 66.89975 -9.353906 " transform="matrix(1,0,0,-1,15.194,16.775)"/>
|
||||
<g style="fill:rgb(12.940979%,52.157593%,77.253723%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-1" x="3.888" y="23.505"/>
|
||||
</g>
|
||||
<g style="fill:rgb(12.940979%,52.157593%,77.253723%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-2" x="22.664228" y="23.505"/>
|
||||
<use xlink:href="#glyph0-3" x="35.441978" y="23.505"/>
|
||||
<use xlink:href="#glyph0-4" x="49.27318" y="23.505"/>
|
||||
<use xlink:href="#glyph0-5" x="61.592369" y="23.505"/>
|
||||
</g>
|
||||
<g style="fill:rgb(12.940979%,52.157593%,77.253723%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-6" x="70.094344" y="23.505"/>
|
||||
</g>
|
||||
<g clip-path="url(#clip1)" clip-rule="nonzero">
|
||||
<path style="fill:none;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(49.412537%,80.784607%,99.215698%);stroke-opacity:1;stroke-miterlimit:10;" d="M -9.127594 -7.935937 C -9.127594 -7.935937 -5.752594 -1.135156 -5.752594 -1.135156 " transform="matrix(1,0,0,-1,15.194,16.775)"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 13 KiB |
|
@ -0,0 +1 @@
|
|||
/usr/share/javascript/mathjax/
|
Binary file not shown.
After Width: | Height: | Size: 87 KiB |
|
@ -0,0 +1,57 @@
|
|||
{% if theme_logo %}
|
||||
<p class="logo">
|
||||
<a href="{{ pathto(master_doc) }}">
|
||||
<img class="logo" src="{{ pathto('_static/' ~ theme_logo, 1) }}" alt="Logo" width=143/>
|
||||
{% if theme_logo_name|lower == 'true' %}
|
||||
<h1 class="logo logo-name">{{ project }}</h1>
|
||||
{% endif %}
|
||||
</a>
|
||||
</p>
|
||||
{% else %}
|
||||
<h1 class="logo"><a href="{{ pathto(master_doc) }}">{{ project }}</a></h1>
|
||||
{% endif %}
|
||||
|
||||
{% if theme_description %}
|
||||
<p class="blurb">{{ theme_description }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if theme_github_user and theme_github_repo %}
|
||||
{% if theme_github_button|lower == 'true' %}
|
||||
<p>
|
||||
<iframe src="https://ghbtns.com/github-btn.html?user={{ theme_github_user }}&repo={{ theme_github_repo }}&type={{ theme_github_type }}&count={{ theme_github_count }}&size=large&v=2"
|
||||
allowtransparency="true" frameborder="0" scrolling="0" width="200px" height="35px"></iframe>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if theme_travis_button|lower != 'false' %}
|
||||
{% if theme_travis_button|lower == 'true' %}
|
||||
{% set path = theme_github_user + '/' + theme_github_repo %}
|
||||
{% else %}
|
||||
{% set path = theme_travis_button %}
|
||||
{% endif %}
|
||||
<p>
|
||||
<a class="badge" href="https://travis-ci.org/{{ path }}">
|
||||
<img
|
||||
alt="https://secure.travis-ci.org/{{ path }}.svg?branch={{ theme_badge_branch }}"
|
||||
src="https://secure.travis-ci.org/{{ path }}.svg?branch={{ theme_badge_branch }}"
|
||||
/>
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if theme_codecov_button|lower != 'false' %}
|
||||
{% if theme_codecov_button|lower == 'true' %}
|
||||
{% set path = theme_github_user + '/' + theme_github_repo %}
|
||||
{% else %}
|
||||
{% set path = theme_codecov_button %}
|
||||
{% endif %}
|
||||
<p>
|
||||
<a class="badge" href="https://codecov.io/github/{{ path }}">
|
||||
<img
|
||||
alt="https://codecov.io/github/{{ path }}/coverage.svg?branch={{ theme_badge_branch }}"
|
||||
src="https://codecov.io/github/{{ path }}/coverage.svg?branch={{ theme_badge_branch }}"
|
||||
/>
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
|
@ -0,0 +1,11 @@
|
|||
<br style="line-height:16px">
|
||||
<h3>{{ _('Navigation') }}</h3>
|
||||
{{ toctree(includehidden=theme_sidebar_includehidden, collapse=theme_sidebar_collapse) }}
|
||||
{% if theme_extra_nav_links %}
|
||||
<hr />
|
||||
<ul>
|
||||
{% for text, uri in theme_extra_nav_links.items() %}
|
||||
<li class="toctree-l1"><a href="{{ uri }}">{{ text }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
|
@ -0,0 +1,73 @@
|
|||
.. default-domain:: dynare
|
||||
|
||||
############
|
||||
Bibliography
|
||||
############
|
||||
|
||||
* Abramowitz, Milton and Irene A. Stegun (1964): “Handbook of Mathematical Functions”, Courier Dover Publications.
|
||||
* Adjemian, Stéphane, Matthieu Darracq Parriès and Stéphane Moyen (2008): “Towards a monetary policy evaluation framework”, *European Central Bank Working Paper*, 942.
|
||||
* Aguiar, Mark and Gopinath, Gita (2004): “Emerging Market Business Cycles: The Cycle is the Trend,” *NBER* Working Paper, 10734.
|
||||
* Amisano, Gianni and Tristani, Oreste (2010): “Euro area inflation persistence in an estimated nonlinear DSGE model”, *Journal of Economic Dynamics and Control*, 34(10), 1837–1858.
|
||||
* Andreasen, Martin M., Jesús Fernández-Villaverde, and Juan Rubio-Ramírez (2018): “The Pruned State-Space System for Non-Linear DSGE Models: Theory and Empirical Applications,” *Review of Economic Studies*, 85(1), pp. 1-49.
|
||||
* Andrews, Donald W.K (1991): “Heteroskedasticity and autocorrelation consistent covariance matrix estimation”, *Econometrica*, 59(3), 817–858.
|
||||
* Backus, David K., Patrick J. Kehoe, and Finn E. Kydland (1992): “International Real Business Cycles,” *Journal of Political Economy*, 100(4), 745–775.
|
||||
* Baxter, Marianne and Robert G. King (1999): “Measuring Business Cycles: Approximate Band-pass Filters for Economic Time Series,” *Review of Economics and Statistics*, 81(4), 575–593.
|
||||
* Boucekkine, Raouf (1995): “An alternative methodology for solving nonlinear forward-looking models,” *Journal of Economic Dynamics and Control*, 19, 711–734.
|
||||
* Brooks, Stephen P., and Andrew Gelman (1998): “General methods for monitoring convergence of iterative simulations,” *Journal of Computational and Graphical Statistics*, 7, pp. 434–455.
|
||||
* Cardoso, Margarida F., R. L. Salcedo and S. Feyo de Azevedo (1996): “The simplex simulated annealing approach to continuous non-linear optimization,” *Computers & Chemical Engineering*, 20(9), 1065-1080.
|
||||
* Chib, Siddhartha and Srikanth Ramamurthy (2010): “Tailored randomized block MCMC methods with application to DSGE models,” *Journal of Econometrics*, 155, 19–38.
|
||||
* Christiano, Lawrence J., Mathias Trabandt and Karl Walentin (2011): “Introducing financial frictions and unemployment into a small open economy model,” *Journal of Economic Dynamics and Control*, 35(12), 1999–2041.
|
||||
* Christoffel, Kai, Günter Coenen and Anders Warne (2010): “Forecasting with DSGE models,” *ECB Working Paper Series*, 1185.
|
||||
* Collard, Fabrice (2001): “Stochastic simulations with Dynare: A practical guide”.
|
||||
* Collard, Fabrice and Michel Juillard (2001a): “Accuracy of stochastic perturbation methods: The case of asset pricing models,” *Journal of Economic Dynamics and Control*, 25, 979–999.
|
||||
* Collard, Fabrice and Michel Juillard (2001b): “A Higher-Order Taylor Expansion Approach to Simulation of Stochastic Forward-Looking Models with an Application to a Non-Linear Phillips Curve,” *Computational Economics*, 17, 125–139.
|
||||
* Corona, Angelo, M. Marchesi, Claudio Martini, and Sandro Ridella (1987): “Minimizing multimodal functions of continuous variables with the “simulated annealing” algorithm”, *ACM Transactions on Mathematical Software*, 13(3), 262–280.
|
||||
* Del Negro, Marco and Franck Schorfheide (2004): “Priors from General Equilibrium Models for VARs”, *International Economic Review*, 45(2), 643–673.
|
||||
* Dennis, Richard (2007): “Optimal Policy In Rational Expectations Models: New Solution Algorithms”, *Macroeconomic Dynamics*, 11(1), 31–55.
|
||||
* Durbin, J. and S. J. Koopman (2012), *Time Series Analysis by State Space Methods*, Second Revised Edition, Oxford University Press.
|
||||
* Fair, Ray and John Taylor (1983): “Solution and Maximum Likelihood Estimation of Dynamic Nonlinear Rational Expectation Models,” *Econometrica*, 51, 1169–1185.
|
||||
* Fernández-Villaverde, Jesús and Juan Rubio-Ramírez (2004): “Comparing Dynamic Equilibrium Economies to Data: A Bayesian Approach,” *Journal of Econometrics*, 123, 153–187.
|
||||
* Fernández-Villaverde, Jesús and Juan Rubio-Ramírez (2005): “Estimating Dynamic Equilibrium Economies: Linear versus Nonlinear Likelihood,” *Journal of Applied Econometrics*, 20, 891–910.
|
||||
* Fernández-Villaverde, Jesús (2010): “The econometrics of DSGE models,” *SERIEs*, 1, 3–49.
|
||||
* Ferris, Michael C. and Todd S. Munson (1999): “Interfaces to PATH 3.0: Design, Implementation and Usage”, *Computational Optimization and Applications*, 12(1), 207–227.
|
||||
* Geweke, John (1992): “Evaluating the accuracy of sampling-based approaches to the calculation of posterior moments,” in J.O. Berger, J.M. Bernardo, A.P. Dawid, and A.F.M. Smith (eds.) Proceedings of the Fourth Valencia International Meeting on Bayesian Statistics, pp. 169–194, Oxford University Press.
|
||||
* Geweke, John (1999): “Using simulation methods for Bayesian econometric models: Inference, development and communication,” *Econometric Reviews*, 18(1), 1–73.
|
||||
* Giordani, Paolo, Michael Pitt, and Robert Kohn (2011): “Bayesian Inference for Time Series State Space Models” in: *The Oxford Handbook of Bayesian Econometrics*, ed. by John Geweke, Gary Koop, and Herman van Dijk, Oxford University Press, 61–124.
|
||||
* Goffe, William L., Gary D. Ferrier, and John Rogers (1994): “Global Optimization of Statistical Functions with Simulated Annealing,” *Journal of Econometrics*, 60(1/2), 65–100.
|
||||
* Hansen, Nikolaus and Stefan Kern (2004): “Evaluating the CMA Evolution Strategy on Multimodal Test Functions”. In: *Eighth International Conference on Parallel Problem Solving from Nature PPSN VIII*, Proceedings, Berlin: Springer, 282–291.
|
||||
* Harvey, Andrew C. and Garry D.A. Phillips (1979): “Maximum likelihood estimation of regression models with autoregressive-moving average disturbances,” *Biometrika*, 66(1), 49–58.
|
||||
* Herbst, Edward (2015): “Using the “Chandrasekhar Recursions” for Likelihood Evaluation of DSGE Models,” *Computational Economics*, 45(4), 693–705.
|
||||
* Ireland, Peter (2004): “A Method for Taking Models to the Data,” *Journal of Economic Dynamics and Control*, 28, 1205–26.
|
||||
* Iskrev, Nikolay (2010): “Local identification in DSGE models,” *Journal of Monetary Economics*, 57(2), 189–202.
|
||||
* Judd, Kenneth (1996): “Approximation, Perturbation, and Projection Methods in Economic Analysis”, in *Handbook of Computational Economics*, ed. by Hans Amman, David Kendrick, and John Rust, North Holland Press, 511–585.
|
||||
* Juillard, Michel (1996): “Dynare: A program for the resolution and simulation of dynamic models with forward variables through the use of a relaxation algorithm,” CEPREMAP, *Couverture Orange*, 9602.
|
||||
* Kim, Jinill and Sunghyun Kim (2003): “Spurious welfare reversals in international business cycle models,” *Journal of International Economics*, 60, 471–500.
|
||||
* Kanzow, Christian and Stefania Petra (2004): “On a semismooth least squares formulation of complementarity problems with gap reduction,” *Optimization Methods and Software*, 19, 507–525.
|
||||
* Kim, Jinill, Sunghyun Kim, Ernst Schaumburg, and Christopher A. Sims (2008): “Calculating and using second-order accurate solutions of discrete time dynamic equilibrium models,” *Journal of Economic Dynamics and Control*, 32(11), 3397–3414.
|
||||
* Koop, Gary (2003), *Bayesian Econometrics*, John Wiley & Sons.
|
||||
* Koopman, S. J. and J. Durbin (2000): “Fast Filtering and Smoothing for Multivariate State Space Models,” *Journal of Time Series Analysis*, 21(3), 281–296.
|
||||
* Koopman, S. J. and J. Durbin (2003): “Filtering and Smoothing of State Vector for Diffuse State Space Models,” *Journal of Time Series Analysis*, 24(1), 85–98.
|
||||
* Kuntsevich, Alexei V. and Franz Kappel (1997): “SolvOpt - The solver for local nonlinear optimization problems (version 1.1, Matlab, C, FORTRAN)”, University of Graz, Graz, Austria.
|
||||
* Laffargue, Jean-Pierre (1990): “Résolution d’un modèle macroéconomique avec anticipations rationnelles”, *Annales d’Économie et Statistique*, 17, 97–119.
|
||||
* Liu, Jane and Mike West (2001): “Combined parameter and state estimation in simulation-based filtering”, in *Sequential Monte Carlo Methods in Practice*, Eds. Doucet, Freitas and Gordon, Springer Verlag.
|
||||
* Lubik, Thomas and Frank Schorfheide (2007): “Do Central Banks Respond to Exchange Rate Movements? A Structural Investigation,” *Journal of Monetary Economics*, 54(4), 1069–1087.
|
||||
* Murray, Lawrence M., Emlyn M. Jones and John Parslow (2013): “On Disturbance State-Space Models and the Particle Marginal Metropolis-Hastings Sampler”, *SIAM/ASA Journal on Uncertainty Quantification*, 1, 494–521.
|
||||
* Pearlman, Joseph, David Currie, and Paul Levine (1986): “Rational expectations models with partial information,” *Economic Modelling*, 3(2), 90–105.
|
||||
* Planas, Christophe, Marco Ratto and Alessandro Rossi (2015): “Slice sampling in Bayesian estimation of DSGE models”.
|
||||
* Pfeifer, Johannes (2013): “A Guide to Specifying Observation Equations for the Estimation of DSGE Models”.
|
||||
* Pfeifer, Johannes (2014): “An Introduction to Graphs in Dynare”.
|
||||
* Rabanal, Pau and Juan Rubio-Ramirez (2003): “Comparing New Keynesian Models of the Business Cycle: A Bayesian Approach,” Federal Reserve of Atlanta, *Working Paper Series*, 2003-30.
|
||||
* Raftery, Adrian E. and Steven Lewis (1992): “How many iterations in the Gibbs sampler?,” in *Bayesian Statistics, Vol. 4*, ed. J.O. Berger, J.M. Bernardo, A.P. * Dawid, and A.F.M. Smith, Clarendon Press: Oxford, pp. 763-773.
|
||||
* Ratto, Marco (2008): “Analysing DSGE models with global sensitivity analysis”, *Computational Economics*, 31, 115–139.
|
||||
* Schorfheide, Frank (2000): “Loss Function-based evaluation of DSGE models,” *Journal of Applied Econometrics*, 15(6), 645–670.
|
||||
* Schmitt-Grohé, Stephanie and Martin Uríbe (2004): “Solving Dynamic General Equilibrium Models Using a Second-Order Approximation to the Policy Function,” *Journal of Economic Dynamics and Control*, 28(4), 755–775.
|
||||
* Schnabel, Robert B. and Elizabeth Eskow (1990): “A new modified Cholesky algorithm,” *SIAM Journal of Scientific and Statistical Computing*, 11, 1136–1158.
|
||||
* Sims, Christopher A., Daniel F. Waggoner and Tao Zha (2008): “Methods for inference in large multiple-equation Markov-switching models,” *Journal of Econometrics*, 146, 255–274.
|
||||
* Skoeld, Martin and Gareth O. Roberts (2003): “Density Estimation for the Metropolis-Hastings Algorithm,” *Scandinavian Journal of Statistics*, 30, 699–718.
|
||||
* Smets, Frank and Rafael Wouters (2003): “An Estimated Dynamic Stochastic General Equilibrium Model of the Euro Area,” *Journal of the European Economic Association*, 1(5), 1123–1175.
|
||||
* Stock, James H. and Mark W. Watson (1999). “Forecasting Inflation,”, *Journal of Monetary Economics*, 44(2), 293–335.
|
||||
* Uhlig, Harald (2001): “A Toolkit for Analysing Nonlinear Dynamic Stochastic Models Easily,” in *Computational Methods for the Study of Dynamic Economies*, Eds. Ramon Marimon and Andrew Scott, Oxford University Press, 30–61.
|
||||
* Villemot, Sébastien (2011): “Solving rational expectations models at first order: what Dynare does,” *Dynare Working Papers*, 2, CEPREMAP.
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2018-2019 Dynare Team
|
||||
#
|
||||
# This file is part of Dynare.
|
||||
#
|
||||
# Dynare is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Dynare is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath('../utils'))
|
||||
|
||||
extensions = ['sphinx.ext.autodoc',
|
||||
'sphinx.ext.mathjax']
|
||||
|
||||
source_suffix = '.rst'
|
||||
|
||||
templates_path = ['_templates']
|
||||
|
||||
html_static_path = ['_static']
|
||||
|
||||
mathjax_path = 'mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML'
|
||||
|
||||
master_doc = 'index'
|
||||
|
||||
project = u'Dynare'
|
||||
copyright = u'2019, Dynare Team'
|
||||
author = u'Dynare Team'
|
||||
|
||||
add_function_parentheses = False
|
||||
|
||||
# See ../utils/version.py, which is generated by autoconf
|
||||
from version import version
|
||||
from version import release
|
||||
|
||||
language = 'en'
|
||||
|
||||
exclude_patterns = []
|
||||
|
||||
highlight_language = 'dynare'
|
||||
|
||||
todo_include_todos = False
|
||||
|
||||
html_theme = 'alabaster'
|
||||
|
||||
html_sidebars = {
|
||||
"**": [
|
||||
"about.html",
|
||||
"searchbox.html",
|
||||
"navigation.html",
|
||||
]
|
||||
}
|
||||
|
||||
html_theme_options = {
|
||||
'logo': 'dlogo.svg',
|
||||
'logo_name': False,
|
||||
'fixed_sidebar': True,
|
||||
'page_width': '100%',
|
||||
}
|
||||
|
||||
htmlhelp_basename = 'Dynaremanual'
|
||||
|
||||
latex_elements = {
|
||||
'sphinxsetup': 'VerbatimBorderColor={rgb}{1,1,1},VerbatimColor={RGB}{240,240,240}, \
|
||||
warningBorderColor={RGB}{255,50,50},OuterLinkColor={RGB}{34,139,34}, \
|
||||
InnerLinkColor={RGB}{51,51,255},TitleColor={RGB}{51,51,255}',
|
||||
'papersize': 'a4paper',
|
||||
}
|
||||
|
||||
latex_documents = [
|
||||
(master_doc, 'dynare-manual.tex', u'Dynare Reference Manual',
|
||||
u'Dynare team', 'manual'),
|
||||
]
|
||||
|
||||
man_pages = [
|
||||
(master_doc, 'dynare', u'Dynare Reference Manual',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
def setup(app):
|
||||
from dynare_dom import DynareDomain
|
||||
from dynare_lex import DynareLexer
|
||||
app.add_lexer("dynare", DynareLexer())
|
||||
app.add_domain(DynareDomain)
|
|
@ -0,0 +1,220 @@
|
|||
.. default-domain:: dynare
|
||||
|
||||
.. |br| raw:: html
|
||||
|
||||
<br>
|
||||
|
||||
####################
|
||||
Dynare misc commands
|
||||
####################
|
||||
|
||||
.. command:: prior_function(OPTIONS);
|
||||
|
||||
|br| Executes a user-defined function on parameter draws from the prior
|
||||
distribution. Dynare returns the results of the computations for
|
||||
all draws in an $ndraws$ by $n$ cell array named
|
||||
``oo_.prior_function_results``.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: function = FUNCTION_NAME
|
||||
|
||||
The function must have the following header ``output_cell =
|
||||
FILENAME(xparam1,M_,options_,oo_,estim_params_,bayestopt_,dataset_,dataset_info)``,
|
||||
providing read-only access to all Dynare structures. The only
|
||||
output argument allowed is a :math:`1 \times n` cell array,
|
||||
which allows for storing any type of output/computations. This
|
||||
option is required.
|
||||
|
||||
.. option:: sampling_draws = INTEGER
|
||||
|
||||
Number of draws used for sampling. Default: 500.
|
||||
|
||||
.. command:: posterior_function(OPTIONS);
|
||||
|
||||
|br| Same as the :comm:`prior_function` command but for the
|
||||
posterior distribution. Results returned in
|
||||
``oo_.posterior_function_results``.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: function = FUNCTION_NAME
|
||||
|
||||
See :opt:`prior_function_function <function = FUNCTION_NAME>`.
|
||||
|
||||
.. option:: sampling_draws = INTEGER
|
||||
|
||||
See :opt:`prior_function_sampling_draws <sampling_draws = INTEGER>`.
|
||||
|
||||
.. command:: generate_trace_plots(CHAIN_NUMBER);
|
||||
|
||||
|br| Generates trace plots of the MCMC draws for all estimated
|
||||
parameters and the posterior density in the specified Markov Chain
|
||||
``CHAIN_NUMBER``.
|
||||
|
||||
.. matcomm:: internals FLAG ROUTINENAME[.m]|MODFILENAME
|
||||
|
||||
|br| Depending on the value of ``FLAG``, the ``internals`` command
|
||||
can be used to run unitary tests specific to a Matlab/Octave
|
||||
routine (if available), to display documentation about a
|
||||
Matlab/Octave routine, or to extract some informations about the
|
||||
state of Dynare.
|
||||
|
||||
*Flags*
|
||||
|
||||
``--test``
|
||||
|
||||
Performs the unitary test associated to ROUTINENAME (if this
|
||||
routine exists and if the matlab/octave ``.m`` file has
|
||||
unitary test sections).
|
||||
|
||||
*Example*
|
||||
|
||||
::
|
||||
|
||||
>> internals --test ROUTINENAME
|
||||
|
||||
if ``routine.m`` is not in the current directory, the full
|
||||
path has to be given::
|
||||
|
||||
>> internals --test ../matlab/fr/ROUTINENAME
|
||||
|
||||
``--info``
|
||||
|
||||
Prints on screen the internal documentation of ROUTINENAME (if
|
||||
this routine exists and if this routine has a texinfo internal
|
||||
documentation header). The path to ``ROUTINENAME`` has to be
|
||||
provided, if the routine is not in the current directory.
|
||||
|
||||
*Example*
|
||||
|
||||
::
|
||||
|
||||
>> internals --doc ../matlab/fr/ROUTINENAME
|
||||
|
||||
At this time, will work properly for only a small number
|
||||
of routines. At the top of the (available) Matlab/Octave
|
||||
routines a commented block for the internal documentation
|
||||
is written in the GNU texinfo documentation format. This
|
||||
block is processed by calling texinfo from
|
||||
MATLAB. Consequently, texinfo has to be installed on your
|
||||
machine.
|
||||
|
||||
``--display-mh-history``
|
||||
|
||||
Displays information about the previously saved MCMC draws
|
||||
generated by a ``.mod`` file named MODFILENAME. This file must
|
||||
be in the current directory.
|
||||
|
||||
*Example*
|
||||
|
||||
::
|
||||
|
||||
>> internals --display-mh-history MODFILENAME
|
||||
|
||||
``--load-mh-history``
|
||||
|
||||
|br| Loads into the Matlab/Octave’s workspace informations
|
||||
about the previously saved MCMC draws generated by a ``.mod``
|
||||
file named MODFILENAME.
|
||||
|
||||
*Example*
|
||||
|
||||
::
|
||||
|
||||
>> internals --load-mh-history MODFILENAME
|
||||
|
||||
This will create a structure called ``mcmc_informations``
|
||||
(in the workspace) with the following fields:
|
||||
|
||||
``Nblck``
|
||||
|
||||
The number of MCMC chains.
|
||||
|
||||
``InitialParameters``
|
||||
|
||||
A ``Nblck*n``, where ``n`` is the number of estimated
|
||||
parameters, array of doubles. Initial state of
|
||||
the MCMC.
|
||||
|
||||
``LastParameters``
|
||||
|
||||
A ``Nblck*n``, where ``n`` is the number of estimated
|
||||
parameters, array of doubles. Current state of
|
||||
the MCMC.
|
||||
|
||||
``InitialLogPost``
|
||||
|
||||
A ``Nblck*1`` array of doubles. Initial value of the
|
||||
posterior kernel.
|
||||
|
||||
``LastLogPost``
|
||||
|
||||
A ``Nblck*1`` array of doubles. Current value of the
|
||||
posterior kernel.
|
||||
|
||||
``InitialSeeds``
|
||||
|
||||
A ``1*Nblck`` structure array. Initial state of the random
|
||||
number generator.
|
||||
|
||||
``LastSeeds``
|
||||
|
||||
A ``1*Nblck`` structure array. Current state of the random
|
||||
number generator.
|
||||
|
||||
``AcceptanceRatio``
|
||||
|
||||
A ``1*Nblck`` array of doubles. Current acceptance ratios.
|
||||
|
||||
.. matcomm:: prior [options[, ...]];
|
||||
|
||||
Prints various informations about the prior distribution depending
|
||||
on the options. If no options are provided, the command returns
|
||||
the list of available options. Following options are available:
|
||||
|
||||
``table``
|
||||
|
||||
Prints a table describing the marginal prior distributions
|
||||
(mean, mode, std., lower and upper bounds, HPD interval).
|
||||
|
||||
``moments``
|
||||
|
||||
Computes and displays first and second order moments of the
|
||||
endogenous variables at the prior mode (considering the
|
||||
linearized version of the model).
|
||||
|
||||
``moments(distribution)``
|
||||
|
||||
Computes and displays the prior mean and prior standard
|
||||
deviation of the first and second moments of the endogenous
|
||||
variables (considering the linearized version of the model) by
|
||||
randomly sampling from the prior. The results will also be
|
||||
stored in the ``prior`` subfolder in a
|
||||
``_endogenous_variables_prior_draws.mat`` file.
|
||||
|
||||
``optimize``
|
||||
|
||||
Optimizes the prior density (starting from a random initial
|
||||
guess). The parameters such that the steady state does not
|
||||
exist or does not satisfy the Blanchard and Kahn conditions
|
||||
are penalized, as they would be when maximizing the posterior
|
||||
density. If a significant proportion of the prior mass is
|
||||
defined over such regions, the optimization algorithm may fail
|
||||
to converge to the true solution (the prior mode).
|
||||
|
||||
``simulate``
|
||||
|
||||
Computes the effective prior mass using a Monte-Carlo. Ideally
|
||||
the effective prior mass should be equal to 1, otherwise
|
||||
problems may arise when maximising the posterior density and
|
||||
model comparison based on marginal densities may be
|
||||
unfair. When comparing models, say :math:`A` and :math:`B`,
|
||||
the marginal densities, :math:`m_A` and :math:`m_B`, should be
|
||||
corrected for the estimated effective prior mass
|
||||
:math:`p_A\neq p_B \leq 1` so that the prior mass of the
|
||||
compared models are identical.
|
||||
|
||||
``plot``
|
||||
|
||||
Plots the marginal prior density.
|
|
@ -0,0 +1,58 @@
|
|||
.. default-domain:: dynare
|
||||
|
||||
########
|
||||
Examples
|
||||
########
|
||||
|
||||
Dynare comes with a database of example ``.mod`` files, which are
|
||||
designed to show a broad range of Dynare features, and are taken from
|
||||
academic papers for most of them. You should have these files in the
|
||||
``examples`` subdirectory of your distribution.
|
||||
|
||||
Here is a short list of the examples included. For a more complete
|
||||
description, please refer to the comments inside the files themselves.
|
||||
|
||||
``ramst.mod``
|
||||
|
||||
An elementary real business cycle (RBC) model, simulated in a
|
||||
deterministic setup.
|
||||
|
||||
``example1.mod``
|
||||
``example2.mod``
|
||||
|
||||
Two examples of a small RBC model in a stochastic setup, presented
|
||||
in *Collard (2001)* (see the file ``guide.pdf`` which comes with
|
||||
Dynare).
|
||||
|
||||
``example3.mod``
|
||||
|
||||
A small RBC model in a stochastic setup, presented in *Collard
|
||||
(2001)*. The steady state is solved analytically using the
|
||||
``steady_state_model`` block (see :bck:`steady_state_model`).
|
||||
|
||||
``fs2000.mod``
|
||||
|
||||
A cash in advance model, estimated by *Schorfheide (2000)*. The
|
||||
file shows how to use Dynare for estimation.
|
||||
|
||||
``fs2000_nonstationary.mod``
|
||||
|
||||
The same model than ``fs2000.mod``, but written in non-stationary
|
||||
form. Detrending of the equations is done by Dynare.
|
||||
|
||||
``bkk.mod``
|
||||
|
||||
Multi-country RBC model with time to build, presented in *Backus,
|
||||
Kehoe and Kydland (1992)*. The file shows how to use Dynare’s
|
||||
macro processor.
|
||||
|
||||
``agtrend.mod``
|
||||
|
||||
Small open economy RBC model with shocks to the growth trend,
|
||||
presented in *Aguiar and Gopinath (2004)*.
|
||||
|
||||
``NK_baseline.mod``
|
||||
|
||||
Baseline New Keynesian Model estimated in *Fernández-Villaverde
|
||||
(2010)*. It demonstrates how to use an explicit steady state file
|
||||
to update parameters and call a numerical solver.
|
|
@ -0,0 +1,43 @@
|
|||
The Dynare Reference Manual, version 4.6-unstable.
|
||||
==================================================
|
||||
|
||||
Currently the development team of Dynare is composed of:
|
||||
|
||||
* Stéphane Adjemian
|
||||
* Houtan Bastani
|
||||
* Michel Juillard
|
||||
* Frédéric Karamé
|
||||
* Junior Maih
|
||||
* Ferhat Mihoubi
|
||||
* Willi Mutschler
|
||||
* Johannes Pfeifer
|
||||
* Marco Ratto
|
||||
* Sébastien Villemot
|
||||
|
||||
Copyright © 1996-2019, Dynare Team.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
|
||||
|
||||
A copy of the license can be found at `http://www.gnu.org/licenses/fdl.txt <http://www.gnu.org/licenses/fdl.txt>`__.
|
||||
|
||||
.. toctree::
|
||||
:numbered:
|
||||
:maxdepth: 4
|
||||
|
||||
introduction
|
||||
installation-and-configuration
|
||||
running-dynare
|
||||
the-model-file
|
||||
the-configuration-file
|
||||
time-series
|
||||
reporting
|
||||
examples
|
||||
dynare-misc-commands
|
||||
bibliography
|
||||
|
||||
.. only:: builder_html
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
|
@ -0,0 +1,238 @@
|
|||
.. default-domain:: dynare
|
||||
|
||||
##############################
|
||||
Installation and configuration
|
||||
##############################
|
||||
|
||||
Software requirements
|
||||
=====================
|
||||
|
||||
Packaged versions of Dynare are available for Windows 7/8/10,
|
||||
`Debian GNU/Linux <http://www.debian.org/>`__, `Ubuntu`_ and macOS 10.8
|
||||
or later. Dynare should work on other systems, but some compilation
|
||||
steps are necessary in that case.
|
||||
|
||||
In order to run Dynare, you need one of the following:
|
||||
|
||||
* MATLAB version 7.9 (R2009b) or above;
|
||||
* GNU Octave version 4.2.1 or above, with the statistics package from `Octave-Forge`_.
|
||||
|
||||
The following optional extensions are also useful to benefit from
|
||||
extra features, but are in no way required:
|
||||
|
||||
* If under MATLAB: the Optimization Toolbox, the Statistics Toolbox,
|
||||
the Control System Toolbox;
|
||||
|
||||
* If under GNU Octave, the following `Octave-Forge`_ packages: ``optim, io,
|
||||
control``.
|
||||
|
||||
|
||||
Installation of Dynare
|
||||
======================
|
||||
|
||||
After installation, Dynare can be used in any directory on your
|
||||
computer. It is best practice to keep your model files in directories
|
||||
different from the one containing the Dynare toolbox. That way you can
|
||||
upgrade Dynare and discard the previous version without having to
|
||||
worry about your own files.
|
||||
|
||||
|
||||
On Windows
|
||||
----------
|
||||
|
||||
Execute the automated installer called ``dynare-4.x.y-win.exe`` (where
|
||||
``4.x.y`` is the version number), and follow the instructions. The
|
||||
default installation directory is ``c:\dynare\4.x.y``.
|
||||
|
||||
After installation, this directory will contain several
|
||||
sub-directories, among which are ``matlab``, ``mex`` and ``doc``.
|
||||
|
||||
The installer will also add an entry in your Start Menu with a
|
||||
shortcut to the documentation files and uninstaller.
|
||||
|
||||
Note that you can have several versions of Dynare coexisting (for
|
||||
example in ``c:\dynare``), as long as you correctly adjust your path
|
||||
settings (see see :ref:`words-warning`).
|
||||
|
||||
|
||||
On Debian GNU/Linux and Ubuntu
|
||||
------------------------------
|
||||
|
||||
Please refer to the `Dynare wiki`_ for detailed instructions.
|
||||
|
||||
Dynare will be installed under ``/usr/lib/dynare``. Documentation will
|
||||
be under ``/usr/share/doc/dynare-doc``.
|
||||
|
||||
|
||||
On macOS
|
||||
--------
|
||||
|
||||
To install Dynare for use with Matlab, execute the automated installer
|
||||
called ``dynare-4.x.y.pkg`` (where *4.x.y* is the version number), and
|
||||
follow the instructions. The default installation directory is
|
||||
``/Applications/Dynare/4.x.y`` (please refer to the `Dynare wiki`_ for
|
||||
detailed instructions).
|
||||
|
||||
After installation, this directory will contain several
|
||||
sub-directories, among which are ``matlab``, ``mex`` and ``doc``.
|
||||
|
||||
Note that several versions of Dynare can coexist (by default in
|
||||
``/Applications/Dynare``), as long as you correctly adjust your path
|
||||
settings (see :ref:`words-warning`).
|
||||
|
||||
To install Dynare for Octave, first install Homebrew following the
|
||||
instructions on their site: `https://brew.sh/
|
||||
<https://brew.sh/>`__. Then install Octave, issuing the command ``brew
|
||||
install octave`` at the Terminal prompt. You can then install the
|
||||
latest stable version of Dynare by typing ``brew install dynare`` at
|
||||
the Terminal prompt. You can also pass options to the installation
|
||||
command. These options can be viewed by typing ``brew info dynare`` at
|
||||
the Terminal prompt.
|
||||
|
||||
|
||||
For other systems
|
||||
-----------------
|
||||
|
||||
You need to download Dynare source code from the `Dynare website`_ and
|
||||
unpack it somewhere.
|
||||
|
||||
Then you will need to recompile the pre-processor and the dynamic
|
||||
loadable libraries. Please refer to `README.md
|
||||
<https://git.dynare.org/Dynare/dynare/blob/master/README.md>`__.
|
||||
|
||||
.. _compil-install:
|
||||
|
||||
Compiler installation
|
||||
=====================
|
||||
|
||||
Prerequisites on Windows
|
||||
------------------------
|
||||
|
||||
There is no prerequisites on Windows. Dynare now ships a compilation
|
||||
environment that can be used with the :opt:`use_dll` option.
|
||||
|
||||
|
||||
Prerequisites on Debian GNU/Linux and Ubuntu
|
||||
--------------------------------------------
|
||||
|
||||
Users of MATLAB under GNU/Linux need a working compilation
|
||||
environment installed. If not already present, it can be installed via
|
||||
``apt install build-essential``.
|
||||
|
||||
Users of Octave under GNU/Linux should install the package for MEX file
|
||||
compilation (under Debian or Ubuntu, it is called ``liboctave-dev``).
|
||||
|
||||
Prerequisites on macOS
|
||||
----------------------
|
||||
|
||||
[TO BE UPDATED]
|
||||
|
||||
If you are using MATLAB under macOS, you should install the latest
|
||||
version of XCode: `see instructions on the Dynare wiki
|
||||
<https://git.dynare.org/Dynare/dynare/wikis/Install-on-MacOS>`__.
|
||||
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
For MATLAB
|
||||
----------
|
||||
|
||||
.. highlight:: matlab
|
||||
|
||||
You need to add the ``matlab`` subdirectory of your Dynare
|
||||
installation to MATLAB path. You have two options for doing that:
|
||||
|
||||
|
||||
* Using the ``addpath`` command in the MATLAB command window:
|
||||
|
||||
Under Windows, assuming that you have installed Dynare in the
|
||||
standard location, and replacing ``4.x.y`` with the correct version
|
||||
number, type::
|
||||
|
||||
>> addpath c:/dynare/4.x.y/matlab
|
||||
|
||||
Under Debian GNU/Linux or Ubuntu, type::
|
||||
|
||||
>> addpath /usr/lib/dynare/matlab
|
||||
|
||||
Under macOS, assuming that you have installed Dynare in the standard
|
||||
location, and replacing ``4.x.y`` with the correct version number,
|
||||
type::
|
||||
|
||||
>> addpath /Applications/Dynare/4.x.y/matlab
|
||||
|
||||
MATLAB will not remember this setting next time you run it, and you
|
||||
will have to do it again.
|
||||
|
||||
* Via the menu entries:
|
||||
|
||||
Select the “Set Path” entry in the “File” menu, then click on “Add
|
||||
Folder…”, and select the ``matlab`` subdirectory of ‘your Dynare
|
||||
installation. Note that you *should not* use “Add with
|
||||
Subfolders…”. Apply the settings by clicking on “Save”. Note that
|
||||
MATLAB will remember this setting next time you run it.
|
||||
|
||||
|
||||
For GNU Octave
|
||||
--------------
|
||||
|
||||
You need to add the ``matlab`` subdirectory of your Dynare
|
||||
installation to Octave path, using the ``addpath`` at the Octave
|
||||
command prompt.
|
||||
|
||||
Under Windows, assuming that you have installed Dynare in the standard
|
||||
location, and replacing “*4.x.y*” with the correct version number,
|
||||
type::
|
||||
|
||||
octave:1> addpath c:/dynare/4.x.y/matlab
|
||||
|
||||
Under Debian GNU/Linux or Ubuntu, there is no need to use the
|
||||
``addpath`` command; the packaging does it for you.
|
||||
|
||||
Under macOS, assuming that you have installed Dynare and Octave via
|
||||
Homebrew, type::
|
||||
|
||||
octave:1> addpath /usr/local/opt/dynare/lib/dynare/matlab
|
||||
|
||||
If you don’t want to type this command every time you run Octave, you
|
||||
can put it in a file called ``.octaverc`` in your home directory
|
||||
(under Windows this will generally be ``c:\Users\USERNAME`` while under macOS it is
|
||||
``/Users/USERNAME/``). This file is run by Octave at every startup.
|
||||
|
||||
|
||||
.. _words-warning:
|
||||
|
||||
Some words of warning
|
||||
---------------------
|
||||
|
||||
You should be very careful about the content of your MATLAB or Octave
|
||||
path. You can display its content by simply typing ``path`` in the
|
||||
command window.
|
||||
|
||||
The path should normally contain system directories of MATLAB or
|
||||
Octave, and some subdirectories of your Dynare installation. You have
|
||||
to manually add the ``matlab`` subdirectory, and Dynare will
|
||||
automatically add a few other subdirectories at runtime (depending on
|
||||
your configuration). You must verify that there is no directory coming
|
||||
from another version of Dynare than the one you are planning to use.
|
||||
|
||||
You have to be aware that adding other directories (on top of the
|
||||
dynare folders) to your MATLAB or Octave path can potentially create
|
||||
problems if any of your M-files have the same name as a Dynare
|
||||
file. Your routine would then override the Dynare routine, making
|
||||
Dynare unusable.
|
||||
|
||||
|
||||
.. warning::
|
||||
|
||||
Never add all the subdirectories of the ``matlab`` folder to the
|
||||
MATLAB or Octave path. You must let Dynare decide which subdirectories
|
||||
have to be added to the MATLAB or Octave path. Otherwise, you may
|
||||
end up with a non optimal or un-usable installation of Dynare.
|
||||
|
||||
|
||||
.. _Ubuntu: http://www.ubuntu.com/
|
||||
.. _Dynare website: https://www.dynare.org/
|
||||
.. _Dynare wiki: https://git.dynare.org/Dynare/dynare/wikis
|
||||
.. _Octave-Forge: http://octave.sourceforge.io/
|
|
@ -0,0 +1,137 @@
|
|||
.. default-domain:: dynare
|
||||
|
||||
############
|
||||
Introduction
|
||||
############
|
||||
|
||||
What is Dynare?
|
||||
===============
|
||||
|
||||
Dynare is a software platform for handling a wide class of economic
|
||||
models, in particular dynamic stochastic general equilibrium (DSGE)
|
||||
and overlapping generations (OLG) models. The models solved by Dynare
|
||||
include those relying on the *rational expectations* hypothesis,
|
||||
wherein agents form their expectations about the future in a way
|
||||
consistent with the model. But Dynare is also able to handle models
|
||||
where expectations are formed differently: on one extreme, models
|
||||
where agents perfectly anticipate the future; on the other extreme,
|
||||
models where agents have limited rationality or imperfect knowledge of
|
||||
the state of the economy and, hence, form their expectations through a
|
||||
learning process. In terms of types of agents, models solved by Dynare
|
||||
can incorporate consumers, productive firms, governments, monetary
|
||||
authorities, investors and financial intermediaries. Some degree of
|
||||
heterogeneity can be achieved by including several distinct classes of
|
||||
agents in each of the aforementioned agent categories.
|
||||
|
||||
Dynare offers a user-friendly and intuitive way of describing these
|
||||
models. It is able to perform simulations of the model given a
|
||||
calibration of the model parameters and is also able to estimate these
|
||||
parameters given a dataset. In practice, the user will write a text
|
||||
file containing the list of model variables, the dynamic equations
|
||||
linking these variables together, the computing tasks to be performed
|
||||
and the desired graphical or numerical outputs.
|
||||
|
||||
A large panel of applied mathematics and computer science techniques
|
||||
are internally employed by Dynare: multivariate nonlinear solving and
|
||||
optimization, matrix factorizations, local functional approximation,
|
||||
Kalman filters and smoothers, MCMC techniques for Bayesian estimation,
|
||||
graph algorithms, optimal control, …
|
||||
|
||||
Various public bodies (central banks, ministries of economy and
|
||||
finance, international organisations) and some private financial
|
||||
institutions use Dynare for performing policy analysis exercises and
|
||||
as a support tool for forecasting exercises. In the academic world,
|
||||
Dynare is used for research and teaching purposes in postgraduate
|
||||
macroeconomics courses.
|
||||
|
||||
Dynare is a free software, which means that it can be downloaded free
|
||||
of charge, that its source code is freely available, and that it can
|
||||
be used for both non-profit and for-profit purposes. Most of the
|
||||
source files are covered by the GNU General Public Licence (GPL)
|
||||
version 3 or later (there are some exceptions to this, see the file
|
||||
license.txt in Dynare distribution). It is available for the Windows,
|
||||
macOS, and Linux platforms and is fully documented through a reference
|
||||
manual. Part of Dynare is programmed in C++, while the rest is written
|
||||
using the `MATLAB`_ programming language. The latter implies that
|
||||
commercially-available MATLAB software is required in order to run
|
||||
Dynare. However, as an alternative to MATLAB, Dynare is also able to
|
||||
run on top of `GNU Octave`_ (basically a free clone of MATLAB): this
|
||||
possibility is particularly interesting for students or institutions
|
||||
who cannot afford, or do not want to pay for, MATLAB and are willing
|
||||
to bear the concomitant performance loss.
|
||||
|
||||
The development of Dynare is mainly done at `CEPREMAP`_ by a core team
|
||||
of researchers who devote part of their time to software
|
||||
development. Currently the development team of Dynare is composed of
|
||||
Stéphane Adjemian (Université du Maine, Gains and Cepremap), Houtan
|
||||
Bastani (Cepremap), Michel Juillard (Banque de France), Frédéric
|
||||
Karamé (Université du Maine, Gains and Cepremap), Junior Maih (Norges
|
||||
Bank), Ferhat Mihoubi (Université Paris-Est Créteil, Érudite and
|
||||
Cepremap), Johannes Pfeifer (University of Cologne), Marco Ratto
|
||||
(European Commission, Joint Research Centre - JRC) and Sébastien
|
||||
Villemot (Cepremap). Increasingly, the developer base is expanding, as
|
||||
tools developed by researchers outside of Cepremap are integrated into
|
||||
Dynare. Financial support is provided by Cepremap, Banque de France
|
||||
and DSGE-net (an international research network for DSGE modeling).
|
||||
|
||||
Interaction between developers and users of Dynare is central to the
|
||||
project. A `web forum`_ is available for users who have questions
|
||||
about the usage of Dynare or who want to report bugs. Current known
|
||||
and fixed bugs are listed on the `Dynare wiki`_. Issues or whishes can
|
||||
be reported on our `Git repository`_. Training sessions are given
|
||||
through the Dynare Summer School, which is organized every year and is
|
||||
attended by about 40 people. Finally, priorities in terms of future
|
||||
developments and features to be added are decided in cooperation with
|
||||
the institutions providing financial support.
|
||||
|
||||
|
||||
Documentation sources
|
||||
=====================
|
||||
|
||||
The present document is the reference manual for Dynare. It documents
|
||||
all commands and features in a systematic fashion.
|
||||
|
||||
Other useful sources of information include the `Dynare wiki`_ and the
|
||||
`Dynare forums`_.
|
||||
|
||||
|
||||
Citing Dynare in your research
|
||||
==============================
|
||||
|
||||
You should cite Dynare if you use it in your research. The
|
||||
recommended way todo this is to cite the present manual, as:
|
||||
|
||||
Stéphane Adjemian, Houtan Bastani, Michel Juillard, Frédéric
|
||||
Karamé, Junior Maih, Ferhat Mihoubi, George Perendia, Johannes Pfeifer, Marco
|
||||
Ratto and Sébastien Villemot (2011), “Dynare: Reference Manual,
|
||||
Version 4,” *Dynare Working Papers*, 1, CEPREMAP
|
||||
|
||||
For convenience, you can copy and paste the following into your BibTeX file:
|
||||
|
||||
.. code-block:: bibtex
|
||||
|
||||
@TechReport{Adjemianetal2011,
|
||||
author = {Adjemian, St\'ephane and Bastani, Houtan and Juillard, Michel and
|
||||
Karam\'e, Fr\'ederic and Maih, Junior and Mihoubi, Ferhat and
|
||||
Perendia, George and Pfeifer, Johannes and Ratto, Marco and
|
||||
Villemot, S\'ebastien},
|
||||
title = {Dynare: Reference Manual Version 4},
|
||||
year = {2011},
|
||||
institution = {CEPREMAP},
|
||||
type = {Dynare Working Papers},
|
||||
number = {1},
|
||||
}
|
||||
|
||||
If you want to give a URL, use the address of the Dynare website:
|
||||
https://www.dynare.org.
|
||||
|
||||
|
||||
|
||||
.. _MATLAB: http://www.mathworks.com/products/matlab/
|
||||
.. _GNU Octave: http://www.octave.org/
|
||||
.. _CEPREMAP: http://www.cepremap.fr/
|
||||
.. _web forum: https://forum.dynare.org/
|
||||
.. _official Dynare website: http://www.dynare.org/
|
||||
.. _Dynare wiki: https://git.dynare.org/Dynare/dynare/wikis
|
||||
.. _Dynare forums: https://forum.dynare.org/
|
||||
.. _Git repository: https://git.dynare.org/Dynare/dynare
|
|
@ -0,0 +1,884 @@
|
|||
.. default-domain:: dynare
|
||||
|
||||
.. |br| raw:: html
|
||||
|
||||
<br>
|
||||
|
||||
.. highlight:: matlab
|
||||
|
||||
#########
|
||||
Reporting
|
||||
#########
|
||||
|
||||
Dynare provides a simple interface for creating :math:`\text{\LaTeX}`
|
||||
reports, comprised of :math:`\text{\LaTeX}` tables and ``PGFPLOTS/TikZ
|
||||
graphs``. You can use the report as created through Dynare or pick out
|
||||
the pieces (tables and graphs) you want for inclusion in your own
|
||||
paper. Though Dynare provides a subset of options available through
|
||||
``PGFPLOTS/TikZ``, you can easily modify the graphs created by Dynare
|
||||
using the options available in the ``PGFPLOTS/TikZ`` manual. You can
|
||||
either do this manually or by passing the options to
|
||||
:opt:`miscTikzAxisOptions <miscTikzAxisOptions, STRING>` or
|
||||
:opt:`graphMiscTikzAddPlotOptions <graphMiscTikzAddPlotOptions,
|
||||
STRING>`.
|
||||
|
||||
Reports are created and modified by calling methods on class
|
||||
objects. The objects are hierarchical, with the following order (from
|
||||
highest to lowest): ``Report``, ``Page``, ``Section``,
|
||||
``Graph/Table/Vspace``, ``Series``. For simplicity of syntax, we
|
||||
abstract away from these classes, allowing you to operate directly on
|
||||
a ``Report`` object, while maintaining the names of these classes in
|
||||
the ``Report`` class methods you will use.
|
||||
|
||||
The report is created sequentially, command by command, hence the
|
||||
order of the commands matters. When an object of a certain hierarchy
|
||||
is inserted, all methods will function on that object until an object
|
||||
of equal or greater hierarchy is added. Hence, once you add a ``Page``
|
||||
to the report, every time you add a ``Section`` object, it will be
|
||||
added to this ``Page`` until another ``Page`` is added to the report
|
||||
(via :repmeth:`addPage`). This will become more clear with the example
|
||||
at the end of the section.
|
||||
|
||||
Options to methods are passed differently than those to Dynare
|
||||
commands. They take the form of named options to Matlab functions
|
||||
where the arguments come in pairs
|
||||
(e.g. ``function_name(`option_1_name', `option_1_value',
|
||||
`option_2_name', `option_2_value', ...)``, where ``option_X_name`` is
|
||||
the name of the option while ``option_X_value`` is the value assigned
|
||||
to that option). The ordering of the option pairs matters only in the
|
||||
unusual case when an option is provided twice (probably
|
||||
erroneously). In this case, the last value passed is the one that is
|
||||
used.
|
||||
|
||||
Below, you will see a list of methods available for the Report class
|
||||
and a clarifying example.
|
||||
|
||||
.. construct:: report
|
||||
|
||||
|br| Instantiates a ``Report`` object.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: compiler, FILENAME
|
||||
|
||||
The full path to the :math:`\text{\LaTeX}` compiler on your
|
||||
system. If this option is not provided, Dynare will try to
|
||||
find the appropriate program to compile :math:`\text{\LaTeX}` on your
|
||||
system. Default is system dependent:
|
||||
|
||||
* Windows: the result of findtexmf ``--file-type=exe pdflatex``.
|
||||
* macOS and Linux: the result of ``which pdflatex``.
|
||||
|
||||
.. option:: directory, FILENAME
|
||||
|
||||
The path to the directory you want the report created in. Default:
|
||||
current directory.
|
||||
|
||||
.. option:: showDate, BOOLEAN
|
||||
|
||||
Display the date and time when the report was
|
||||
compiled. Default: ``true``.
|
||||
|
||||
.. option:: fileName, FILENAME
|
||||
|
||||
The file name to use when saving this report. Default: ``report.tex``.
|
||||
|
||||
.. option:: header, STRING
|
||||
|
||||
The valid :math:`\text{\LaTeX}` code to be included in the report before
|
||||
``\begin{document}``. Default: ``empty``.
|
||||
|
||||
.. option:: margin, DOUBLE
|
||||
|
||||
The margin size. Default: ``2.5``.
|
||||
|
||||
.. option:: marginUnit, `cm' | `in'
|
||||
|
||||
Units associated with the margin. Default: ```cm'``.
|
||||
|
||||
.. option:: orientation, `landscape' | `portrait'
|
||||
|
||||
Paper orientation: Default: ```portrait'``.
|
||||
|
||||
.. option:: paper, `a4' | `letter'
|
||||
|
||||
Paper size. Default: ```a4'``.
|
||||
|
||||
.. option:: showOutput, BOOLEAN
|
||||
|
||||
Print report creation progress to screen. Shows you the page
|
||||
number as it is created and as it is written. This is useful
|
||||
to see where a potential error occurs in report
|
||||
creation. Default: ``true``.
|
||||
|
||||
.. option:: title, STRING
|
||||
|
||||
Report Title. Default: ``none``.
|
||||
|
||||
|
||||
.. reportingmethod:: addPage
|
||||
|
||||
|br| Adds a Page to the Report.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: footnote, STRING
|
||||
|
||||
A footnote to be included at the bottom of this page. Default: ``none``.
|
||||
|
||||
.. option:: latex, STRING
|
||||
|
||||
The valid :math:`\text{\LaTeX}` code to be used for this
|
||||
page. Alows the user to create a page to be included in the
|
||||
report by passing :math:`\text{\LaTeX}` code directly. If this option is
|
||||
passed, the page itself will be saved in the :opt:`pageDirName
|
||||
<pageDirName, FILENAME>` directory in the form ``page_X.tex``
|
||||
where X refers to the page number. Default: ``empty``.
|
||||
|
||||
.. option:: orientation, `landscape' | `portrait'
|
||||
|
||||
See :opt:`orientation <orientation, `landscape' | `portrait'>`.
|
||||
|
||||
.. option:: pageDirName, FILENAME
|
||||
|
||||
The name of the folder in which to store this page. Directory given is
|
||||
relative to the `directory` option of the report class. Only used when
|
||||
the :opt:`latex <latex, STRING>` command is passed. Default:
|
||||
``tmpRepDir``.
|
||||
|
||||
.. option:: paper, `a4' | `letter'
|
||||
|
||||
See :opt:`paper <paper, `a4' | `letter'>`.
|
||||
|
||||
.. option:: title, STRING | CELL_ARRAY_STRINGS
|
||||
|
||||
With one entry (a STRING), the title of the page. With more
|
||||
than one entry (a CELL_ARRAY_STRINGS), the title and
|
||||
subtitle(s) of the page. Values passed must be valid
|
||||
:math:`\text{\LaTeX}` code (e.g., ``%`` must be
|
||||
``\%``). Default: ``none``.
|
||||
|
||||
.. option:: titleFormat, STRING | CELL_ARRAY_STRINGS
|
||||
|
||||
A string representing the valid :math:`\text{\LaTeX}` markup to use on
|
||||
``title``. The number of cell array entries must be equal to
|
||||
that of the ``title`` option if you do not want to use the
|
||||
default value for the title (and subtitles). Default:
|
||||
``\large\bfseries``.
|
||||
|
||||
.. option:: titleTruncate, INTEGER
|
||||
|
||||
Useful when automatically generating page titles that may
|
||||
become too long, ``titleTruncate`` can be used to truncate a
|
||||
title (and subsequent subtitles) when they pass the specified
|
||||
number of characters. Default: ``.off``.
|
||||
|
||||
|
||||
.. reportingmethod:: addSection
|
||||
|
||||
|br| Adds a ``Section`` to a ``Page``.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: cols, INTEGER
|
||||
|
||||
The number of columns in the section. Default: ``1``.
|
||||
|
||||
.. option:: height, STRING
|
||||
|
||||
A string to be used with the ``\sectionheight`` :math:`\text{\LaTeX}`
|
||||
command. Default: ``'!'``
|
||||
|
||||
|
||||
.. reportingmethod:: addGraph
|
||||
|
||||
|br| Adds a ``Graph`` to a ``Section``.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: data, dseries
|
||||
|
||||
The ``dseries`` that provides the data for the graph. Default: ``none``.
|
||||
|
||||
.. option:: axisShape, `box' | `L'
|
||||
|
||||
The shape the axis should have. ```box'`` means that there is
|
||||
an axis line to the left, right, bottom, and top of the
|
||||
graphed line(s). 'L'`` means that there is an axis to the left
|
||||
and bottom of the graphed line(s). Default: ```box'``.
|
||||
|
||||
.. option:: graphDirName, FILENAME
|
||||
|
||||
The name of the folder in which to store this figure. Directory given
|
||||
is relative to the `directory` option of the report class. Default:
|
||||
``tmpRepDir``.
|
||||
|
||||
.. option:: graphName, STRING
|
||||
|
||||
The name to use when saving this figure. Default: something of
|
||||
the form ``graph_pg1_sec2_row1_col3.tex``.
|
||||
|
||||
.. option:: height, DOUBLE
|
||||
|
||||
The height of the graph, in inches. Default: ``4.5``.
|
||||
|
||||
.. option:: showGrid, BOOLEAN
|
||||
|
||||
Whether or not to display the major grid on the
|
||||
graph. Default: ``true``.
|
||||
|
||||
.. option:: showLegend, BOOLEAN
|
||||
|
||||
Whether or not to display the legend.
|
||||
|
||||
Unless you use the :opt:`graphLegendName <graphLegendName,
|
||||
STRING>` option, the name displayed in the legend is the tex
|
||||
name associated with the ``dseries``. You can modify this tex
|
||||
name by using :dsermeth:`tex_rename <B =
|
||||
tex_rename>`. Default: ``false``.
|
||||
|
||||
.. option:: legendAt, NUMERICAL_VECTOR
|
||||
|
||||
The coordinates for the legend location. If this option is
|
||||
passed, it overrides the :opt:`legendLocation <legendLocation,
|
||||
OPTION>` option. Must be of size ``2``. Default: ``empty``.
|
||||
|
||||
.. option:: showLegendBox, BOOLEAN
|
||||
|
||||
Whether or not to display a box around the legend. Default: ``false``.
|
||||
|
||||
.. option:: legendLocation, OPTION
|
||||
|
||||
Where to place the legend in the graph. Possible values for OPTION are::
|
||||
|
||||
`south west' | `south east' | `north west' | `north east' | `outer north east'
|
||||
|
||||
Default: ```south east'``.
|
||||
|
||||
.. option:: legendOrientation, `vertical' | `horizontal'
|
||||
|
||||
Orientation of the legend. Default: ```horizontal'``.
|
||||
|
||||
.. option:: legendFontSize, OPTION
|
||||
|
||||
The font size for legend entries. Possible values for OPTION are::
|
||||
|
||||
`tiny' | `scriptsize' | `footnotesize' | `small' | `normalsize' |
|
||||
`large' | `Large' | `LARGE' | `huge' | `Huge'
|
||||
|
||||
Default: ``tiny``.
|
||||
|
||||
.. option:: miscTikzAxisOptions, STRING
|
||||
|
||||
If you are comfortable with ``PGFPLOTS/TikZ``, you can use
|
||||
this option to pass arguments directly to the
|
||||
``PGFPLOTS/TikZ`` axis environment command. Specifically to be
|
||||
used for desired ``PGFPLOTS/TikZ`` options that have not been
|
||||
incorporated into Dynare Reporting. Default: ``empty``.
|
||||
|
||||
.. option:: miscTikzPictureOptions, STRING
|
||||
|
||||
If you are comfortable with ``PGFPLOTS/TikZ``, you can use
|
||||
this option to pass arguments directly to the
|
||||
``PGFPLOTS/TikZ`` ``tikzpicture`` environment command. (e.g.,
|
||||
to scale the graph in the x and y dimensions, you can pass
|
||||
following to this option: 'xscale=2.5,
|
||||
yscale=0.5'``). Specifically to be used for desired
|
||||
``PGFPLOTS/TikZ`` options that have not been incorporated into
|
||||
Dynare Reporting. Default: ``empty``.
|
||||
|
||||
.. option:: seriesToUse, CELL_ARRAY_STRINGS
|
||||
|
||||
The names of the series contained in the ``dseries`` provided
|
||||
to the :opt:`data <data, dseries>` option. If empty, use all
|
||||
series provided to ``data`` option. Default: ``empty``.
|
||||
|
||||
.. option:: shade, dates
|
||||
|
||||
The date range showing the portion of the graph that should be
|
||||
shaded. Default: ``none``.
|
||||
|
||||
.. option:: shadeColor, STRING
|
||||
|
||||
The color to use in the shaded portion of the graph. All valid
|
||||
color strings defined for use by ``PGFPLOTS/TikZ`` are
|
||||
valid. A list of defined colors is::
|
||||
|
||||
'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'black', 'gray',
|
||||
'white','darkgray', 'lightgray', 'brown', 'lime', 'olive', 'orange',
|
||||
'pink', 'purple', 'teal', 'violet'.
|
||||
|
||||
Furthermore, You can use combinations of these colors. For
|
||||
example, if you wanted a color that is 20\% green and 80\%
|
||||
purple, you could pass the string ``'green!20!purple'``. You
|
||||
can also use RGB colors, following the syntax:
|
||||
```rgb,255:red,231;green,84;blue,121'`` which corresponds to
|
||||
the RGB color ``(231;84;121)``. More examples are available in
|
||||
the section 4.7.5 of the ``PGFPLOTS/TikZ`` manual, revision
|
||||
1.10. Default: ```green'``
|
||||
|
||||
.. option:: shadeOpacity, DOUBLE
|
||||
|
||||
The opacity of the shaded area, must be in ``[0,100]``. Default: ``20``.
|
||||
|
||||
.. option:: tickFontSize, OPTION
|
||||
|
||||
The font size for x- and y-axis tick labels. Possible values
|
||||
for OPTION are::
|
||||
|
||||
`tiny' | `scriptsize' | `footnotesize' | `small' | `normalsize' |
|
||||
`large' | `Large' | `LARGE' | `huge' | `Huge'
|
||||
|
||||
Default: ``normalsize``.
|
||||
|
||||
.. option:: title, STRING | CELL_ARRAY_STRINGS
|
||||
|
||||
Same as :opt:`title <title, STRING | CELL_ARRAY_STRINGS>`,
|
||||
just for graphs.
|
||||
|
||||
.. option:: titleFontSize, OPTION
|
||||
|
||||
The font size for title. Possible values for OPTION are::
|
||||
|
||||
`tiny' | `scriptsize' | `footnotesize' | `small' | `normalsize' |
|
||||
`large' | `Large' | `LARGE' | `huge' | `Huge'
|
||||
|
||||
Default: ``normalsize``.
|
||||
|
||||
.. option:: titleFormat, STRING
|
||||
|
||||
The format to use for the graph title. Unlike
|
||||
:opt:`titleFormat <titleFormat, STRING | CELL_ARRAY_STRINGS>`,
|
||||
due to a constraint of ``TikZ``, this format applies to the
|
||||
title and subtitles. Default: ``TikZ`` default.
|
||||
|
||||
.. option:: width, DOUBLE
|
||||
|
||||
The width of the graph, in inches. Default: ``6.0``.
|
||||
|
||||
.. option:: writeCSV, BOOLEAN
|
||||
|
||||
Whether or not to write a CSV file with only the plotted
|
||||
data. The file will be saved in the directory specified by
|
||||
:opt:`graphDirName <graphDirName, FILENAME>` with the same base
|
||||
name as specified by :opt:`graphName <graphName, STRING>` with
|
||||
the ending ``.csv``. Default: ``false``.
|
||||
|
||||
.. option:: xlabel, STRING
|
||||
|
||||
The x-axis label. Default: ``none``.
|
||||
|
||||
.. option:: ylabel, STRING
|
||||
|
||||
The y-axis label. Default: ``none``.
|
||||
|
||||
.. option:: xAxisTight, BOOLEAN
|
||||
|
||||
Use a tight x axis. If false, uses ``PGFPLOTS/TikZ`` ``enlarge
|
||||
x limits`` to choose appropriate axis size. Default: ``true``.
|
||||
|
||||
.. option:: xrange, dates
|
||||
|
||||
The boundary on the x-axis to display in the graph. Default: ``all``.
|
||||
|
||||
.. option:: xTicks, NUMERICAL_VECTOR
|
||||
|
||||
Used only in conjunction with :opt:`xTickLabels <xTickLabels,
|
||||
CELL_ARRAY_STRINGS | `ALL'>`, this option denotes the
|
||||
numerical position of the label along the x-axis. The
|
||||
positions begin at ``1``. Default: the indices associated with
|
||||
the first and last dates of the ``dseries`` and, if passed,
|
||||
the index associated with the first date of the :opt:`shade
|
||||
<shade, dates>` option.
|
||||
|
||||
.. option:: xTickLabels, CELL_ARRAY_STRINGS | `ALL'
|
||||
|
||||
The labels to be mapped to the ticks provided by
|
||||
``xTicks``. Default: the first and last dates of the
|
||||
``dseries`` and, if passed, the date first date of the
|
||||
:opt:`shade <shade, dates>` option.
|
||||
|
||||
.. option:: xTickLabelAnchor, STRING
|
||||
|
||||
Where to anchor the x tick label. Default: ```east'``.
|
||||
|
||||
.. option:: xTickLabelRotation, DOUBLE
|
||||
|
||||
The amount to rotate the x tick labels by. Default: ``0``.
|
||||
|
||||
.. option:: yAxisTight, BOOLEAN
|
||||
|
||||
Use a tight y axis. If false, uses ``PGFPLOTS/TikZ`` ``enlarge
|
||||
y limits`` to choose appropriate axis size. Default:
|
||||
``false``.
|
||||
|
||||
.. option:: yrange, NUMERICAL_VECTOR
|
||||
|
||||
The boundary on the y-axis to display in the graph,
|
||||
represented as a ``NUMERICAL_VECTOR`` of size ``2``, with the
|
||||
first entry less than the second entry. Default: ``all``.
|
||||
|
||||
.. option:: yTickLabelFixed, BOOLEAN
|
||||
|
||||
Round the y tick labels to a fixed number of decimal places,
|
||||
given by ``yTickLabelPrecision``. Default: ``true``.
|
||||
|
||||
.. option:: yTickLabelPrecision, INTEGER
|
||||
|
||||
The precision with which to report the ``yTickLabel``. Default: ``0``.
|
||||
|
||||
.. option:: yTickLabelScaled, BOOLEAN
|
||||
|
||||
Determines whether or not there is a common scaling factor for
|
||||
the y axis. Default: ``true``.
|
||||
|
||||
.. option:: yTickLabelZeroFill, BOOLEAN
|
||||
|
||||
Whether or not to fill missing precision spots with
|
||||
zeros. Default: ``true``.
|
||||
|
||||
.. option:: showZeroline, BOOLEAN
|
||||
|
||||
Display a solid black line at :math:`y = 0`. Default: ``false``.
|
||||
|
||||
.. option:: zeroLineColor, STRING
|
||||
|
||||
The color to use for the zero line. Only used if
|
||||
:opt:`showZeroLine <showZeroline, BOOLEAN>` is true. See the
|
||||
explanation in :opt:`shadeColor <shadeColor, STRING>` for how
|
||||
to use colors with reports. Default: ```black'``.
|
||||
|
||||
|
||||
.. reportingmethod:: addTable
|
||||
|
||||
|br| Adds a ``Table`` to a ``Section``.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: data, dseries
|
||||
|
||||
See :opt:`data <data, dseries>`.
|
||||
|
||||
.. option:: highlightRows, CELL_ARRAY_STRINGS
|
||||
|
||||
A cell array containing the colors to use for row
|
||||
highlighting. See :opt:`shadeColor <shadeColor, STRING>` for
|
||||
how to use colors with reports. Highlighting for a specific
|
||||
row can be overridden by using the :opt:`tableRowColor
|
||||
<tableRowColor, STRING>` option to
|
||||
:repmeth:`addSeries`. Default: ``empty``.
|
||||
|
||||
.. option:: showHlines, BOOLEAN
|
||||
|
||||
Whether or not to show horizontal lines separating the
|
||||
rows. Default: ``false``.
|
||||
|
||||
.. option:: precision, INTEGER
|
||||
|
||||
The number of decimal places to report in the table data
|
||||
(rounding done via the *round half away from zero*
|
||||
method). Default: ``1``.
|
||||
|
||||
.. option:: range, dates
|
||||
|
||||
The date range of the data to be displayed. Default: ``all``.
|
||||
|
||||
.. option:: seriesToUse, CELL_ARRAY_STRINGS
|
||||
|
||||
See :opt:`seriesToUse <seriesToUse, CELL_ARRAY_STRINGS>`.
|
||||
|
||||
.. option:: tableDirName, FILENAME
|
||||
|
||||
The name of the folder in which to store this table. Directory given is
|
||||
relative to the `directory` option of the report class. Default:
|
||||
``tmpRepDir``.
|
||||
|
||||
.. option:: tableName, STRING
|
||||
|
||||
The name to use when saving this table. Default: something of
|
||||
the form ``table_pg1_sec2_row1_col3.tex``.
|
||||
|
||||
.. option:: title, STRING
|
||||
|
||||
Same as :opt:`title <title, STRING>`, just for tables.
|
||||
|
||||
.. option:: titleFormat, STRING
|
||||
|
||||
Same as :opt:`titleFormat <titleFormat, STRING | CELL_ARRAY_STRINGS>`,
|
||||
just for tables. Default: ``\large``.
|
||||
|
||||
.. option:: vlineAfter, dates | CELL_ARRAY_DATES
|
||||
|
||||
Show a vertical line after the specified date (or dates if a
|
||||
cell array of dates is passed). Default: ``empty``.
|
||||
|
||||
.. option:: vlineAfterEndOfPeriod, BOOLEAN
|
||||
|
||||
Show a vertical line after the end of every period (i.e. after
|
||||
every year, after the fourth quarter, etc.). Default:
|
||||
``false``.
|
||||
|
||||
.. option:: showVlines, BOOLEAN
|
||||
|
||||
Whether or not to show vertical lines separating the
|
||||
columns. Default: ``false``.
|
||||
|
||||
.. option:: writeCSV, BOOLEAN
|
||||
|
||||
Whether or not to write a CSV file containing the data
|
||||
displayed in the table. The file will be saved in the
|
||||
directory specified by :opt:`tableDirName <tableDirName,
|
||||
FILENAME>` with the same base name as specified by
|
||||
:opt:`tableName <tableName, STRING>` with the ending
|
||||
``.csv``. Default: ``false``.
|
||||
|
||||
|
||||
.. reportingmethod:: addSeries
|
||||
|
||||
|br| Adds a ``Series`` to a ``Graph`` or a ``Table``.
|
||||
|
||||
Options specific to graphs begin with ```graph'`` while options
|
||||
specific to tables begin with ```table'``.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: data, dseries
|
||||
|
||||
See :opt:`data <data, dseries>`.
|
||||
|
||||
.. option:: graphBar, BOOLEAN
|
||||
|
||||
Whether or not to display this series as a bar graph as oppsed
|
||||
to the default of displaying it as a line graph. Default:
|
||||
``false``.
|
||||
|
||||
.. option:: graphFanShadeColor, STRING
|
||||
|
||||
The shading color to use between a series and the
|
||||
previously-added series in a graph. Useful for making fan
|
||||
charts. Default: ``empty``.
|
||||
|
||||
.. option:: graphFanShadeOpacity, INTEGER
|
||||
|
||||
The opacity of the color passed in :opt:`graphFanShadeColor
|
||||
<graphFanShadeColor, STRING>`. Default: ``50``.
|
||||
|
||||
.. option:: graphBarColor, STRING
|
||||
|
||||
The outline color of each bar in the bar graph. Only active if
|
||||
:opt:`graphBar <graphBar, BOOLEAN>` is passed. Default:
|
||||
```black'``.
|
||||
|
||||
.. option:: graphBarFillColor, STRING
|
||||
|
||||
The fill color of each bar in the bar graph. Only active if
|
||||
:opt:`graphBar <graphBar, BOOLEAN>` is passed. Default:
|
||||
```black'``.
|
||||
|
||||
.. option:: graphBarWidth, DOUBLE
|
||||
|
||||
The width of each bar in the bar graph. Only active if
|
||||
:opt:`graphBar <graphBar, BOOLEAN>` is passed. Default: ``2``.
|
||||
|
||||
.. option:: graphHline, DOUBLE
|
||||
|
||||
Use this option to draw a horizontal line at the given
|
||||
value. Default: ``empty``.
|
||||
|
||||
.. option:: graphLegendName, STRING
|
||||
|
||||
The name to display in the legend for this series, passed as
|
||||
valid :math:`\text{\LaTeX}` (e.g., ``GDP_{US}, $\alpha$,
|
||||
\color{red}GDP\color{black}``). Will be displayed only if the
|
||||
``data`` and :opt:`showLegend <showLegend, BOOLEAN>` options
|
||||
have been passed. Default: the tex name of the series.
|
||||
|
||||
.. option:: graphLineColor, STRING
|
||||
|
||||
Color to use for the series in a graph. See the explanation in
|
||||
:opt:`shadeColor <shadeColor, STRING>` for how to use colors
|
||||
with reports. Default: ```black'``
|
||||
|
||||
.. option:: graphLineStyle, OPTION
|
||||
|
||||
Line style for this series in a graph. Possible values for OPTION are::
|
||||
|
||||
`none' | `solid' | `dotted' | `densely dotted' | `loosely dotted' | `dashed' |
|
||||
`densely dashed' | `loosely dashed' | `dashdotted' | `densely dashdotted' |
|
||||
`loosely dashdotted' | `dashdotdotted' | `densely dashdotdotted' |
|
||||
`loosely dashdotdotted'
|
||||
|
||||
Default: ```solid'``.
|
||||
|
||||
.. option:: graphLineWidth DOUBLE
|
||||
|
||||
Line width for this series in a graph. Default: ``0.5``.
|
||||
|
||||
.. option:: graphMarker, OPTION
|
||||
|
||||
The Marker to use on this series in a graph. Possible values
|
||||
for OPTION are::
|
||||
|
||||
`x' | `+' | `-' | `|' | `o' | `asterisk' | `star' | `10-pointed star' |
|
||||
`oplus' | `oplus*' | `otimes' | `otimes*' | `square' | `square*' |
|
||||
`triangle' | `triangle*' | `diamond' | `diamond*' | `halfdiamond*' |
|
||||
`halfsquare*' | `halfsquare right*' | `halfsquare left*' | `Mercedes star' |
|
||||
`Mercedes star flipped' | `halfcircle' | `halfcircle*' | `pentagon' |
|
||||
`pentagon star'
|
||||
|
||||
Default: ``none``.
|
||||
|
||||
.. option:: graphMarkerEdgeColor, STRING
|
||||
|
||||
The edge color of the graph marker. See the explanation in
|
||||
:opt:`shadeColor <shadeColor, STRING>` for how to use colors
|
||||
with reports. Default: ``graphLineColor``.
|
||||
|
||||
.. option:: graphMarkerFaceColor, STRING
|
||||
|
||||
The face color of the graph marker. See the explanation in
|
||||
:opt:`shadeColor <shadeColor, STRING>` for how to use colors
|
||||
with reports. Default: ``graphLineColor``.
|
||||
|
||||
.. option:: graphMarkerSize, DOUBLE
|
||||
|
||||
The size of the graph marker. Default: ``1``.
|
||||
|
||||
.. option:: graphMiscTikzAddPlotOptions, STRING
|
||||
|
||||
If you are comfortable with ``PGFPLOTS/TikZ``, you can use
|
||||
this option to pass arguments directly to the
|
||||
``PGFPLOTS/TikZ`` ``addPlots`` command. (e.g., Instead of
|
||||
passing the marker options above, you can pass a string such
|
||||
as the following to this option: ```mark=halfcircle*,mark
|
||||
options={rotate=90,scale=3}'``). Specifically to be used for
|
||||
desired ``PGFPLOTS/TikZ`` options that have not been
|
||||
incorporated into Dynare Reproting. Default: ``empty``.
|
||||
|
||||
.. option:: graphShowInLegend, BOOLEAN
|
||||
|
||||
Whether or not to show this series in the legend, given that
|
||||
the :opt:`showLegend <showLegend, BOOLEAN>` option was passed
|
||||
to :repmeth:`addGraph`. Default: ``true``.
|
||||
|
||||
.. option:: graphVline, dates
|
||||
|
||||
Use this option to draw a vertical line at a given
|
||||
date. Default: ``empty``.
|
||||
|
||||
.. option:: tableDataRhs, dseries
|
||||
|
||||
A series to be added to the right of the current
|
||||
series. Usefull for displaying aggregate data for a
|
||||
series. e.g if the series is quarterly ``tableDataRhs`` could
|
||||
point to the yearly averages of the quarterly series. This
|
||||
would cause quarterly data to be displayed followed by annual
|
||||
data. Default: ``empty``.
|
||||
|
||||
.. option:: tableRowColor, STRING
|
||||
|
||||
The color that you want the row to be. Predefined values
|
||||
include ``LightCyan`` and ``Gray``. Default: ``white``.
|
||||
|
||||
.. option:: tableRowIndent, INTEGER
|
||||
|
||||
The number of times to indent the name of the series in the
|
||||
table. Used to create subgroups of series. Default: ``0``.
|
||||
|
||||
.. option:: tableShowMarkers, BOOLEAN
|
||||
|
||||
In a Table, if ``true``, surround each cell with brackets and
|
||||
color it according to :opt:`tableNegColor <tableNegColor,
|
||||
LATEX_COLOR>` and :opt:`tablePosColor <tablePosColor,
|
||||
LATEX_COLOR>`. No effect for graphs. Default: ``false``.
|
||||
|
||||
.. option:: tableAlignRight, BOOLEAN
|
||||
|
||||
Whether or not to align the series name to the right of the
|
||||
cell. Default: ``false``.
|
||||
|
||||
.. option:: tableMarkerLimit, DOUBLE
|
||||
|
||||
For values less than :math:`-1*\texttt{tableMarkerLimit}`,
|
||||
mark the cell with the color denoted by tableNegColor. For
|
||||
those greater than ``tableMarkerLimit``, mark the cell with
|
||||
the color denoted by tablePosColor. Default: ``1e-4``.
|
||||
|
||||
.. option:: tableNaNSymb, STRING
|
||||
|
||||
Replace ``NaN`` values with the text in this option. Default: ``NaN``.
|
||||
|
||||
.. option:: tableNegColor, LATEX_COLOR
|
||||
|
||||
The color to use when marking Table data that is less than
|
||||
zero. Default: ```red'``
|
||||
|
||||
.. option:: tablePrecision, INTEGER
|
||||
|
||||
The number of decimal places to report in the table
|
||||
data. Default: the value set by :opt:`precision <precision,
|
||||
INTEGER>`.
|
||||
|
||||
.. option:: tablePosColor, LATEX_COLOR
|
||||
|
||||
The color to use when marking Table data that is greater than
|
||||
zero. Default: ```blue'``
|
||||
|
||||
.. option:: tableSubSectionHeader, STRING
|
||||
|
||||
A header for a subsection of the table. No data will be
|
||||
associated with it. It is equivalent to adding an empty series
|
||||
with a name. Default: ``''``
|
||||
|
||||
.. option:: zeroTol, DOUBLE
|
||||
|
||||
The zero tolerance. Anything smaller than ``zeroTol`` and
|
||||
larger than ``-zeroTol`` will be set to zero before being
|
||||
graphed or written to the table. Default: ``1e-6``.
|
||||
|
||||
|
||||
.. reportingmethod:: addParagraph
|
||||
|
||||
|br| Adds a ``Paragraph`` to a ``Section``.
|
||||
|
||||
The ``Section`` can only be comprised of ``Paragraphs`` and must
|
||||
only have 1 column.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: balancedCols, BOOLEAN
|
||||
|
||||
Determines whether the text is spread out evenly across the
|
||||
columns when the ``Paragraph`` has more than one
|
||||
column. Default: ``true``.
|
||||
|
||||
.. option:: cols, INTEGER
|
||||
|
||||
The number of columns for the ``Paragraph``. Default: ``1``.
|
||||
|
||||
.. option:: heading, STRING
|
||||
|
||||
The heading for the ``Paragraph`` (like a section
|
||||
heading). The string must be valid :math:`\text{\LaTeX}` code. Default:
|
||||
``empty``.
|
||||
|
||||
.. option:: indent, BOOLEAN
|
||||
|
||||
Whether or not to indent the paragraph. Default: ``true``.
|
||||
|
||||
.. option:: text, STRING
|
||||
|
||||
The paragraph itself. The string must be valid :math:`\text{\LaTeX}`
|
||||
code. Default: ``empty``.
|
||||
|
||||
|
||||
.. reportingmethod:: addVspace
|
||||
|
||||
|br| Adds a ``Vspace`` (vertical space) to a ``Section``.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: hline, INTEGER
|
||||
|
||||
The number of horizontal lines to be inserted. Default: ``0``.
|
||||
|
||||
.. option:: number, INTEGER
|
||||
|
||||
The number of new lines to be inserted. Default: ``1``.
|
||||
|
||||
|
||||
.. reportingmethod:: write
|
||||
|
||||
|br| Writes the :math:`\text{\LaTeX}` representation of this
|
||||
``Report``, saving it to the file specified by :opt:`filename
|
||||
<fileName, FILENAME>`.
|
||||
|
||||
|
||||
.. reportingmethod:: compile
|
||||
|
||||
|br| Compiles the report written by ``write`` into a ``pdf``
|
||||
file. If the report has not already been written (determined by
|
||||
the existence of the file specified by :opt:`filename <fileName,
|
||||
FILENAME>`, ``write`` is called.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: compiler, FILENAME
|
||||
|
||||
Like :opt:`compiler <compiler, FILENAME>`, except will not
|
||||
overwrite the value of ``compiler`` contained in the report
|
||||
object. Hence, passing the value here is useful for using
|
||||
different :math:`\text{\LaTeX}` compilers or just for passing
|
||||
the value at the last minute.
|
||||
|
||||
.. option:: showOutput, BOOLEAN
|
||||
|
||||
Print the compiler output to the screen. Useful for debugging
|
||||
your code as the :math:`\text{\LaTeX}` compiler hangs if there is a
|
||||
problem. Default: the value of :opt:`showOutput <showOutput,
|
||||
BOOLEAN>`.
|
||||
|
||||
.. option:: showReport, BOOLEAN
|
||||
|
||||
Open the compiled report (works on Windows and macOS on
|
||||
Matlab). Default: ``true``.
|
||||
|
||||
|
||||
*Example*
|
||||
|
||||
The following code creates a one page report. The first part of the
|
||||
page contains two graphs displayed across two columns and one row. The
|
||||
bottom of the page displays a centered table::
|
||||
|
||||
%% Create dseries
|
||||
dsq = dseries(`quarterly.csv');
|
||||
dsa = dseries(`annual.csv');
|
||||
dsca = dseries(`annual_control.csv');
|
||||
|
||||
%% Report
|
||||
rep = report();
|
||||
|
||||
%% Page 1
|
||||
rep.addPage('title', {'My Page Title', 'My Page Subtitle'}, ...
|
||||
'titleFormat', {'\large\bfseries', '\large'});
|
||||
|
||||
% Section 1
|
||||
rep.addSection('cols', 2);
|
||||
|
||||
rep.addGraph('title', 'Graph Column 1', 'showLegend', true, ...
|
||||
'xrange', dates('2007q1'):dates('2013q4'), ...
|
||||
'shade', dates('2012q2'):dates('2013q4'));
|
||||
rep.addSeries('data', dsq{'GROWTH_US'}, 'graphLineColor', 'blue', ...
|
||||
'graphLineStyle', 'loosely dashed', 'graphLineWidth', 1);
|
||||
rep.addSeries('data', dsq{'GROWTH_EU'}, 'graphLineColor', 'green', ...
|
||||
'graphLineWidth', 1.5);
|
||||
|
||||
rep.addGraph('title', 'Graph Column 2', 'showLegend', true, ...
|
||||
'xrange', dates('2007q1'):dates('2013q4'), ...
|
||||
'shade', dates('2012q2'):dates('2013q4'));
|
||||
rep.addSeries('data', dsq{'GROWTH_JA'}, 'graphLineColor', 'blue', ...
|
||||
'graphLineWidth', 1);
|
||||
rep.addSeries('data', dsq{'GROWTH_RC6'}, 'graphLineColor', 'green', ...
|
||||
'graphLineStyle', 'dashdotdotted', 'graphLineWidth', 1.5);
|
||||
|
||||
% Section 2
|
||||
rep.addVspace('number', 15);
|
||||
rep.addSection();
|
||||
rep.addTable('title', 'Table 1', 'range', dates('2012Y'):dates('2014Y'));
|
||||
shortNames = {'US', 'EU'};
|
||||
longNames = {'United States', 'Euro Area'};
|
||||
for i=1:length(shortNames)
|
||||
rep.addSeries('data', dsa{['GROWTH_' shortNames{i}]});
|
||||
delta = dsa{['GROWTH_' shortNames{i}]}-dsca{['GROWTH_' shortNames{i}]};
|
||||
delta.tex_rename_('$\Delta$');
|
||||
rep.addSeries('data', delta, ...
|
||||
'tableShowMarkers', true, 'tableAlignRight', true);
|
||||
end
|
||||
|
||||
%% Write & Compile Report
|
||||
rep.write();
|
||||
rep.compile();
|
||||
|
||||
Once compiled, the report looks like:
|
||||
|
||||
.. image:: _static/report.png
|
|
@ -0,0 +1,511 @@
|
|||
.. default-domain:: dynare
|
||||
|
||||
##############
|
||||
Running Dynare
|
||||
##############
|
||||
|
||||
In order to give instructions to Dynare, the user has to write a
|
||||
*model file* whose filename extension must be ``.mod`` or
|
||||
``.dyn``. This file contains the description of the model and the
|
||||
computing tasks required by the user. Its contents are described in
|
||||
:ref:`model-file`.
|
||||
|
||||
.. _dyn-invoc:
|
||||
|
||||
Dynare invocation
|
||||
=================
|
||||
|
||||
Once the model file is written, Dynare is invoked using the ``dynare``
|
||||
command at the MATLAB or Octave prompt (with the filename of the
|
||||
``.mod`` given as argument).
|
||||
|
||||
In practice, the handling of the model file is done in two steps: in
|
||||
the first one, the model and the processing instructions written by
|
||||
the user in a *model file* are interpreted and the proper MATLAB or
|
||||
GNU Octave instructions are generated; in the second step, the program
|
||||
actually runs the computations. Both steps are triggered automatically
|
||||
by the ``dynare`` command.
|
||||
|
||||
.. matcomm:: dynare FILENAME[.mod] [OPTIONS…]
|
||||
|
||||
This command launches Dynare and executes the instructions
|
||||
included in ``FILENAME.mod``. This user-supplied file contains the
|
||||
model and the processing instructions, as described in
|
||||
:ref:`model-file`. The options, listed below, can be passed on the
|
||||
command line, following the name of the ``.mod`` file or in the
|
||||
first line of the ``.mod`` file itself (see below).
|
||||
|
||||
dynare begins by launching the preprocessor on the ``.mod
|
||||
file``. By default (unless ``use_dll`` option has been given to
|
||||
``model``), the preprocessor creates three intermediary files:
|
||||
|
||||
- ``+FILENAME/driver.m``
|
||||
|
||||
Contains variable declarations, and computing tasks.
|
||||
|
||||
- ``+FILENAME/dynamic.m``
|
||||
|
||||
Contains the dynamic model equations. Note that Dynare might
|
||||
introduce auxiliary equations and variables (see
|
||||
:ref:`aux-variables`). Outputs are the residuals of the
|
||||
dynamic model equations in the order the equations were
|
||||
declared and the Jacobian of the dynamic model equations. For
|
||||
higher order approximations also the Hessian and the
|
||||
third-order derivatives are provided. When computing the
|
||||
Jacobian of the dynamic model, the order of the endogenous
|
||||
variables in the columns is stored in
|
||||
``M_.lead_lag_incidence``. The rows of this matrix represent
|
||||
time periods: the first row denotes a lagged (time t-1)
|
||||
variable, the second row a contemporaneous (time t) variable,
|
||||
and the third row a leaded (time t+1) variable. The columns of
|
||||
the matrix represent the endogenous variables in their order
|
||||
of declaration. A zero in the matrix means that this
|
||||
endogenous does not appear in the model in this time
|
||||
period. The value in the ``M_.lead_lag_incidence`` matrix
|
||||
corresponds to the column of that variable in the Jacobian of
|
||||
the dynamic model. Example: Let the second declared variable
|
||||
be ``c`` and the ``(3,2)`` entry of ``M_.lead_lag_incidence``
|
||||
be 15. Then the 15th column of the Jacobian is the derivative
|
||||
with respect to ``c(+1)``.
|
||||
|
||||
- ``+FILENAME/static.m``
|
||||
|
||||
Contains the long run static model equations. Note that Dynare
|
||||
might introduce auxiliary equations and variables (see
|
||||
:ref:`aux-variables`). Outputs are the residuals of the static
|
||||
model equations in the order the equations were declared and
|
||||
the Jacobian of the static equations. Entry ``(i,j)`` of the
|
||||
Jacobian represents the derivative of the ith static model
|
||||
equation with respect to the jth model variable in declaration
|
||||
order.
|
||||
|
||||
|
||||
These files may be looked at to understand errors reported at the
|
||||
simulation stage.
|
||||
|
||||
``dynare`` will then run the computing tasks by executing
|
||||
``+FILENAME/driver.m``. If a user needs to rerun the computing
|
||||
tasks without calling the preprocessor (or without calling the
|
||||
:mcomm:`dynare` command), for
|
||||
instance because he has modified the script, he just have to type
|
||||
the following on the command line:
|
||||
|
||||
.. code-block:: matlab
|
||||
|
||||
>> FILENAME.driver
|
||||
|
||||
A few words of warning are warranted here: under Octave the
|
||||
filename of the ``.mod`` file should be chosen in such a way that
|
||||
the generated ``.m`` files described above do not conflict with
|
||||
``.m`` files provided by Octave or by Dynare. Not
|
||||
respecting this rule could cause crashes or unexpected
|
||||
behaviour. In particular, it means that the ``.mod`` file cannot
|
||||
be given the name of an Octave or Dynare command. For instance, under
|
||||
Octave, it also means that the ``.mod`` file cannot be named
|
||||
``test.mod`` or ``example.mod``.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: noclearall
|
||||
|
||||
By default, ``dynare`` will issue a ``clear all`` command to
|
||||
MATLAB (<R2015b) or Octave, thereby deleting all workspace
|
||||
variables and functions; this option instructs ``dynare`` not
|
||||
to clear the workspace. Note that starting with Matlab 2015b
|
||||
``dynare`` only deletes the global variables and the functions
|
||||
using persistent variables, in order to benefit from the JIT
|
||||
(Just In Time) compilation. In this case the option instructs
|
||||
``dynare`` not to clear the globals and functions.
|
||||
|
||||
.. option:: onlyclearglobals
|
||||
|
||||
By default, ``dynare`` will issue a ``clear all`` command to
|
||||
MATLAB versions before 2015b and to Octave, thereby deleting
|
||||
all workspace variables; this option instructs ``dynare`` to
|
||||
clear only the global variables (i.e. ``M_, options_, oo_,
|
||||
estim_params_, bayestopt_``, and ``dataset_``), leaving the
|
||||
other variables in the workspace.
|
||||
|
||||
.. option:: debug
|
||||
|
||||
Instructs the preprocessor to write some debugging information
|
||||
about the scanning and parsing of the ``.mod`` file.
|
||||
|
||||
.. option:: notmpterms
|
||||
|
||||
Instructs the preprocessor to omit temporary terms in the
|
||||
static and dynamic files; this generally decreases
|
||||
performance, but is used for debugging purposes since it makes
|
||||
the static and dynamic files more readable.
|
||||
|
||||
.. option:: savemacro[=FILENAME]
|
||||
|
||||
Instructs ``dynare`` to save the intermediary file which is
|
||||
obtained after macro processing (see :ref:`macro-proc-lang`);
|
||||
the saved output will go in the file specified, or if no file
|
||||
is specified in ``FILENAME-macroexp.mod``
|
||||
|
||||
.. option:: onlymacro
|
||||
|
||||
Instructs the preprocessor to only perform the
|
||||
macro processing step, and stop just after. Useful for
|
||||
debugging purposes or for using the macro processor
|
||||
independently of the rest of Dynare toolbox.
|
||||
|
||||
.. option:: nolinemacro
|
||||
|
||||
Instructs the macro preprocessor to omit line numbering
|
||||
information in the intermediary ``.mod`` file created after
|
||||
the macro processing step. Useful in conjunction with
|
||||
:opt:`savemacro <savemacro[=FILENAME]>` when one wants that to reuse the intermediary
|
||||
``.mod`` file, without having it cluttered by line numbering
|
||||
directives.
|
||||
|
||||
.. option:: noemptylinemacro
|
||||
|
||||
Passing this option removes all empty from the macro expanded
|
||||
mod file created when the :opt:`savemacro <savemacro[=FILENAME]>` option is used.
|
||||
|
||||
.. option:: onlymodel
|
||||
|
||||
Instructs the preprocessor to print only information about the
|
||||
model in the driver file; no Dynare commands (other than the
|
||||
shocks statement and parameter initializations) are printed
|
||||
and hence no computational tasks performed. The same
|
||||
ancillary files are created as would otherwise be created
|
||||
(dynamic, static files, etc.).
|
||||
|
||||
.. option:: nolog
|
||||
|
||||
Instructs Dynare to no create a logfile of this run in
|
||||
``FILENAME.log.`` The default is to create the logfile.
|
||||
|
||||
.. option:: params_derivs_order=0|1|2
|
||||
|
||||
When :comm:`identification`, :comm:`dynare_sensitivity` (with
|
||||
identification), or :ref:`estimation_cmd <estim-comm>` are
|
||||
present, this option is used to limit the order of the
|
||||
derivatives with respect to the parameters that are calculated
|
||||
by the preprocessor. 0 means no derivatives, 1 means first
|
||||
derivatives, and 2 means second derivatives. Default: 2
|
||||
|
||||
.. option:: nowarn
|
||||
|
||||
Suppresses all warnings.
|
||||
|
||||
.. option:: json = parse|check|transform|compute
|
||||
|
||||
Causes the preprocessor to output a version of the ``.mod`` file in
|
||||
JSON format. When the JSON output is created depends on the value
|
||||
passed. These values represent various steps of processing in the
|
||||
preprocessor.
|
||||
|
||||
If ``parse`` is passed, the output will be written after the parsing of
|
||||
the ``.mod`` file to a file called ``FILENAME.json`` but before file
|
||||
has been checked (e.g. if there are unused exogenous in the model
|
||||
block, the JSON output will be created before the preprocessor exits).
|
||||
|
||||
If ``check`` is passed, the output will be written to a file called
|
||||
``FILENAME.json`` after the model has been checked.
|
||||
|
||||
If ``transform`` is passed, the JSON output of the transformed
|
||||
model (maximum lead of 1, minimum lag of -1, expectation
|
||||
operators substituted, etc.) will be written to a file called
|
||||
``FILENAME.json`` and the original, untransformed model will
|
||||
be written in ``FILENAME_original.json``.
|
||||
|
||||
And if ``compute`` is passed, the output is written after the
|
||||
computing pass. In this case, the transformed model is written
|
||||
to ``FILENAME.json``, the original model is written to
|
||||
``FILENAME_original.json``, and the dynamic and static files
|
||||
are written to ``FILENAME_dynamic.json`` and
|
||||
``FILENAME_static.json``.
|
||||
|
||||
.. option:: jsonstdout
|
||||
|
||||
Instead of writing output requested by ``json`` to files,
|
||||
write to standard out.
|
||||
|
||||
.. option:: onlyjson
|
||||
|
||||
Quit processing once the output requested by ``json`` has been
|
||||
written.
|
||||
|
||||
.. option:: jsonderivsimple
|
||||
|
||||
Print a simplified version (excluding variable name(s) and lag
|
||||
information) of the static and dynamic files in
|
||||
``FILENAME_static.json`` and ``FILENAME_dynamic.``.
|
||||
|
||||
.. option:: warn_uninit
|
||||
|
||||
Display a warning for each variable or parameter which is not
|
||||
initialized. See :ref:`param-init`, or
|
||||
:comm:`load_params_and_steady_state
|
||||
<load_params_and_steady_state>` for initialization of
|
||||
parameters. See :ref:`init-term-cond`, or
|
||||
:comm:`load_params_and_steady_state
|
||||
<load_params_and_steady_state>` for initialization of
|
||||
endogenous and exogenous variables.
|
||||
|
||||
.. option:: console
|
||||
|
||||
Activate console mode. In addition to the behavior of
|
||||
``nodisplay``, Dynare will not use graphical waitbars for long
|
||||
computations.
|
||||
|
||||
.. option:: nograph
|
||||
|
||||
Activate the ``nograph`` option (see :opt:`nograph`), so that
|
||||
Dynare will not produce any graph.
|
||||
|
||||
.. option:: nointeractive
|
||||
|
||||
Instructs Dynare to not request user input.
|
||||
|
||||
.. option:: nopathchange
|
||||
|
||||
By default Dynare will change Matlab/Octave’s path if
|
||||
``dynare/matlab`` directory is not on top and if Dynare’s
|
||||
routines are overriden by routines provided in other
|
||||
toolboxes. If one wishes to override Dynare’s routines, the
|
||||
``nopathchange`` options can be used. Alternatively, the path
|
||||
can be temporarly modified by the user at the top of the
|
||||
``.mod`` file (using Matlab/Octave’s ``addpath`` command).
|
||||
|
||||
.. option:: nopreprocessoroutput
|
||||
|
||||
Prevent Dynare from printing the output of the steps leading up to the
|
||||
preprocessor as well as the preprocessor output itself.
|
||||
|
||||
.. option:: mexext=mex|mexw32|mexw64|mexmaci64|mexa64
|
||||
|
||||
The mex extension associated with your platform to be used
|
||||
when compiling output associated with :opt:`use_dll`.
|
||||
Dynare is able to set this automatically, so you should not
|
||||
need to set it yourself.
|
||||
|
||||
.. option:: matlabroot=<<path>>
|
||||
|
||||
The path to the Matlab installation for use with
|
||||
:opt:`use_dll`. Dynare is able to set this automatically,
|
||||
so you should not need to set it yourself.
|
||||
|
||||
.. option:: parallel[=CLUSTER_NAME]
|
||||
|
||||
Tells Dynare to perform computations in parallel. If
|
||||
CLUSTER_NAME is passed, Dynare will use the specified cluster
|
||||
to perform parallel computations. Otherwise, Dynare will use
|
||||
the first cluster specified in the configuration file. See
|
||||
:ref:`conf-file`, for more information about the configuration
|
||||
file.
|
||||
|
||||
.. option:: conffile=FILENAME
|
||||
|
||||
Specifies the location of the configuration file if it differs
|
||||
from the default. See :ref:`conf-file`, for more information
|
||||
about the configuration file and its default location.
|
||||
|
||||
.. option:: parallel_slave_open_mode
|
||||
|
||||
Instructs Dynare to leave the connection to the slave node
|
||||
open after computation is complete, closing this connection
|
||||
only when Dynare finishes processing.
|
||||
|
||||
.. option:: parallel_test
|
||||
|
||||
Tests the parallel setup specified in the configuration file
|
||||
without executing the ``.mod`` file. See :ref:`conf-file`, for
|
||||
more information about the configuration file.
|
||||
|
||||
.. option:: -DMACRO_VARIABLE=MACRO_EXPRESSION
|
||||
|
||||
Defines a macro-variable from the command line (the same
|
||||
effect as using the Macro directive ``@#define`` in a model
|
||||
file, see :ref:`macro-proc-lang`).
|
||||
|
||||
.. option:: -I<<path>>
|
||||
|
||||
Defines a path to search for files to be included by the
|
||||
macro processor (using the ``@#include`` command). Multiple
|
||||
``-I`` flags can be passed on the command line. The paths will
|
||||
be searched in the order that the ``-I`` flags are passed and
|
||||
the first matching file will be used. The flags passed here
|
||||
take priority over those passed to ``@#includepath``.
|
||||
|
||||
.. option:: nostrict
|
||||
|
||||
Allows Dynare to issue a warning and continue processing when
|
||||
|
||||
1. there are more endogenous variables than equations.
|
||||
2. an undeclared symbol is assigned in ``initval`` or ``endval``.
|
||||
3. an undeclared symbol is found in the ``model`` block in
|
||||
this case, it is automatically declared exogenous.
|
||||
4. exogenous variables were declared but not used in the
|
||||
``model`` block.
|
||||
|
||||
.. option:: fast
|
||||
|
||||
Only useful with model option ``use_dll``. Don’t recompile the
|
||||
MEX files when running again the same model file and the lists
|
||||
of variables and the equations haven’t changed. We use a 32
|
||||
bit checksum, stored in ``<model filename>/checksum``. There
|
||||
is a very small probability that the preprocessor misses a
|
||||
change in the model. In case of doubt, re-run without the fast
|
||||
option.
|
||||
|
||||
.. option:: minimal_workspace
|
||||
|
||||
Instructs Dynare not to write parameter assignments to
|
||||
parameter names in the .m file produced by the
|
||||
preprocessor. This is potentially useful when running
|
||||
``dynare`` on a large ``.mod`` file that runs into workspace
|
||||
size limitations imposed by MATLAB.
|
||||
|
||||
.. option:: compute_xrefs
|
||||
|
||||
Tells Dynare to compute the equation cross references, writing
|
||||
them to the output ``.m`` file.
|
||||
|
||||
.. option:: stochastic
|
||||
|
||||
Tells Dynare that the model to be solved is stochastic. If no
|
||||
Dynare commands related to stochastic models (``stoch_simul``,
|
||||
``estimation``, ...) are present in the ``.mod`` file, Dynare
|
||||
understands by default that the model to be solved is
|
||||
deterministic.
|
||||
|
||||
These options can be passed to the preprocessor by listing them
|
||||
after the name of the ``.mod`` file. They can alternatively be
|
||||
defined in the first line of the ``.mod`` file, this avoids typing
|
||||
them on the command line each time a ``.mod`` file is to be
|
||||
run. This line must be a Dynare comment (ie must begin with //)
|
||||
and the options must be comma separated between ``--+`` options:
|
||||
and ``+--``. Note that any text after the ``+--`` will be
|
||||
discarded. As in the command line, if an option admits a value the
|
||||
equal symbol must not be surrounded by spaces. For instance ``json
|
||||
= compute`` is not correct, and should be written
|
||||
``json=compute``.
|
||||
|
||||
*Output*
|
||||
|
||||
Depending on the computing tasks requested in the ``.mod`` file,
|
||||
executing the ``dynare`` command will leave variables containing
|
||||
results in the workspace available for further processing. More
|
||||
details are given under the relevant computing tasks. The
|
||||
``M_``,``oo_``, and ``options_`` structures are saved in a file
|
||||
called ``FILENAME_results.mat``. If they exist, ``estim_params_``,
|
||||
``bayestopt_``, ``dataset_``, ``oo_recursive_`` and
|
||||
``estimation_info`` are saved in the same file.
|
||||
|
||||
.. matvar:: M_
|
||||
|
||||
Structure containing various information about the model.
|
||||
|
||||
.. matvar:: options_
|
||||
|
||||
Structure contains the values of the various options used by
|
||||
Dynare during the computation.
|
||||
|
||||
.. matvar:: oo_
|
||||
|
||||
Structure containing the various results of the computations.
|
||||
|
||||
.. matvar:: dataset_
|
||||
|
||||
A ``dseries`` object containing the data used for estimation.
|
||||
|
||||
.. matvar:: oo_recursive_
|
||||
|
||||
Cell array containing the ``oo_`` structures obtained when
|
||||
estimating the model for the different samples when performing
|
||||
recursive estimation and forecasting. The ``oo_`` structure
|
||||
obtained for the sample ranging to the `i` -th observation is
|
||||
saved in the `i` -th field. The fields for non-estimated
|
||||
endpoints are empty.
|
||||
|
||||
*Example*
|
||||
|
||||
Call dynare from the MATLAB or Octave prompt, without or with options:
|
||||
|
||||
.. code-block:: matlab
|
||||
|
||||
>> dynare ramst
|
||||
>> dynare ramst.mod savemacro
|
||||
|
||||
Alternatively the options can be passed in the first line of
|
||||
``ramst.mod``:
|
||||
|
||||
.. code-block:: dynare
|
||||
|
||||
// --+ options: savemacro, json=compute +--
|
||||
|
||||
and then dynare called without passing options on the command line:
|
||||
|
||||
.. code-block:: matlab
|
||||
|
||||
>> dynare ramst
|
||||
|
||||
|
||||
|
||||
|
||||
Dynare hooks
|
||||
============
|
||||
|
||||
It is possible to call pre and post Dynare preprocessor hooks written
|
||||
as MATLAB scripts. The script ``MODFILENAME/hooks/priorprocessing.m``
|
||||
is executed before the call to Dynare’s preprocessor, and can be used
|
||||
to programmatically transform the mod file that will be read by the
|
||||
preprocessor. The script ``MODFILENAME/hooks/postprocessing.m`` is
|
||||
gexecuted just after the call to Dynare’s preprocessor, and can be used
|
||||
to programmatically transform the files generated by Dynare’s
|
||||
preprocessor before actual computations start. The pre and/or post
|
||||
dynare preprocessor hooks are executed if and only if the
|
||||
aforementioned scripts are detected in the same folder as the the
|
||||
model file, ``FILENAME.mod``.
|
||||
|
||||
|
||||
Understanding Preprocessor Error Messages
|
||||
=========================================
|
||||
|
||||
If the preprocessor runs into an error while processing your ``.mod``
|
||||
file, it will issue an error. Due to the way that a parser works,
|
||||
sometimes these errors can be misleading. Here, we aim to demystify
|
||||
these error messages.
|
||||
|
||||
The preprocessor issues error messages of the form:
|
||||
|
||||
#. ``ERROR: <<file.mod>>: line A, col B: <<error message>>``
|
||||
#. ``ERROR: <<file.mod>>: line A, cols B-C: <<error message>>``
|
||||
#. ``ERROR: <<file.mod>>: line A, col B - line C, col D: <<error message>>``
|
||||
|
||||
The first two errors occur on a single line, with error two spanning
|
||||
multiple columns. Error three spans multiple rows.
|
||||
|
||||
Often, the line and column numbers are precise, leading you directly
|
||||
to the offending syntax. Infrequently however, because of the way the
|
||||
parser works, this is not the case. The most common example of
|
||||
misleading line and column numbers (and error message for that matter)
|
||||
is the case of a missing semicolon, as seen in the following example::
|
||||
|
||||
varexo a, b
|
||||
parameters c, ...;
|
||||
|
||||
In this case, the parser doesn’t know a semicolon is missing at the
|
||||
end of the ``varexo`` command until it begins parsing the second line
|
||||
and bumps into the ``parameters`` command. This is because we allow
|
||||
commands to span multiple lines and, hence, the parser cannot know
|
||||
that the second line will not have a semicolon on it until it gets
|
||||
there. Once the parser begins parsing the second line, it realizes
|
||||
that it has encountered a keyword, ``parameters``, which it did not
|
||||
expect. Hence, it throws an error of the form: ``ERROR: <<file.mod>>:
|
||||
line 2, cols 0-9: syntax error, unexpected PARAMETERS``. In this case,
|
||||
you would simply place a semicolon at the end of line one and the
|
||||
parser would continue processing.
|
||||
|
||||
It is also helpful to keep in mind that any piece of code that does not violate
|
||||
Dynare syntax, but at the same time is not recognized by the parser, is interpreted
|
||||
as native Matlab code. This code will be directly passed to the ``driver`` script.
|
||||
Investigating ``driver.m`` file then helps with debugging. Such problems most often
|
||||
occur when defined variable or parameter names have been misspelled so that Dynare's
|
||||
parser is unable to recognize them.
|
|
@ -0,0 +1,389 @@
|
|||
.. default-domain:: dynare
|
||||
|
||||
.. |br| raw:: html
|
||||
|
||||
<br>
|
||||
|
||||
.. _conf-file:
|
||||
|
||||
######################
|
||||
The configuration file
|
||||
######################
|
||||
|
||||
The configuration file is used to provide Dynare with information not
|
||||
related to the model (and hence not placed in the model file). At the
|
||||
moment, it is only used when using Dynare to run parallel
|
||||
computations.
|
||||
|
||||
On Linux and macOS, the default location of the configuration file is
|
||||
``$HOME/.dynare``, while on Windows it is ``%APPDATA%\dynare.ini``
|
||||
(typically ``c:\Users\USERNAME\AppData\dynare.ini``). You
|
||||
can specify a non standard location using the ``conffile`` option of
|
||||
the ``dynare`` command (see :ref:`dyn-invoc`).
|
||||
|
||||
The parsing of the configuration file is case-sensitive and it should
|
||||
take the following form, with each option/choice pair placed on a
|
||||
newline::
|
||||
|
||||
[command0]
|
||||
option0 = choice0
|
||||
option1 = choice1
|
||||
|
||||
[command1]
|
||||
option0 = choice0
|
||||
option1 = choice1
|
||||
|
||||
The configuration file follows a few conventions (self-explanatory
|
||||
conventions such as ``USER_NAME`` have been excluded for concision):
|
||||
|
||||
``COMPUTER_NAME``
|
||||
|
||||
Indicates the valid name of a server (e.g. ``localhost``,
|
||||
``server.cepremap.org``) or an IP address.
|
||||
|
||||
``DRIVE_NAME``
|
||||
|
||||
Indicates a valid drive name in Windows, without the trailing
|
||||
colon (e.g. ``C``).
|
||||
|
||||
``PATH``
|
||||
|
||||
Indicates a valid path in the underlying operating system
|
||||
(e.g. ``/home/user/dynare/matlab/``).
|
||||
|
||||
``PATH_AND_FILE``
|
||||
|
||||
Indicates a valid path to a file in the underlying operating
|
||||
system (e.g. ``/usr/local/MATLAB/R2010b/bin/matlab``).
|
||||
|
||||
``BOOLEAN``
|
||||
|
||||
Is ``true`` or ``false``.
|
||||
|
||||
|
||||
Dynare Configuration
|
||||
====================
|
||||
|
||||
This section explains how to configure Dynare for general
|
||||
processing. Currently, there is only one option available.
|
||||
|
||||
.. confblock:: [hooks]
|
||||
|
||||
|br| This block can be used to specify configuration options that will
|
||||
be used when running Dynare.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: GlobalInitFile = PATH_AND_FILE
|
||||
|
||||
The location of the global initialization file to be run at
|
||||
the end of ``global_initialization.m``.
|
||||
|
||||
*Example*
|
||||
|
||||
::
|
||||
|
||||
[hooks]
|
||||
GlobalInitFile = /home/usern/dynare/myInitFile.m
|
||||
|
||||
|
||||
.. confblock:: [paths]
|
||||
|
||||
|br| This block can be used to specify paths that will be used
|
||||
when running dynare.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: Include = PATH
|
||||
|
||||
A colon-separated path to use when searching for files to
|
||||
include via ``@#include``. Paths specified via :opt:`-I
|
||||
<-I\<\<path\>\>>` take priority over paths specified here,
|
||||
while these paths take priority over those specified by
|
||||
``@#includepath``.
|
||||
|
||||
*Example*
|
||||
|
||||
::
|
||||
|
||||
[paths]
|
||||
Include = /path/to/folder/containing/modfiles:/path/to/another/folder
|
||||
|
||||
.. _paral-conf:
|
||||
|
||||
Parallel Configuration
|
||||
======================
|
||||
|
||||
This section explains how to configure Dynare for parallelizing some
|
||||
tasks which require very little inter-process communication.
|
||||
|
||||
The parallelization is done by running several MATLAB or Octave
|
||||
processes, either on local or on remote machines. Communication
|
||||
between master and slave processes are done through SMB on Windows and
|
||||
SSH on UNIX. Input and output data, and also some short status
|
||||
messages, are exchanged through network filesystems. Currently the
|
||||
system works only with homogenous grids: only Windows or only Unix
|
||||
machines.
|
||||
|
||||
The following routines are currently parallelized:
|
||||
|
||||
* the posterior sampling algorithms when using multiple chains;
|
||||
* the Metropolis-Hastings diagnostics;
|
||||
* the posterior IRFs;
|
||||
* the prior and posterior statistics;
|
||||
* some plotting routines.
|
||||
|
||||
Note that creating the configuration file is not enough in order to
|
||||
trigger parallelization of the computations: you also need to specify
|
||||
the ``parallel`` option to the ``dynare`` command. For more details,
|
||||
and for other options related to the parallelization engine, see
|
||||
:ref:`dyn-invoc`.
|
||||
|
||||
You also need to verify that the following requirements are met by
|
||||
your cluster (which is composed of a master and of one or more
|
||||
slaves):
|
||||
|
||||
For a Windows grid:
|
||||
|
||||
* a standard Windows network (SMB) must be in place;
|
||||
* the `PsTools`_ suite must be installed in the path of the
|
||||
master Windows machine;
|
||||
* the Windows user on the master machine has to be user of any
|
||||
other slave machine in the cluster, and that user will be
|
||||
used for the remote computations.
|
||||
* detailed step-by-step setup instructions can be found in
|
||||
:ref:`win-ssg`.
|
||||
|
||||
For a UNIX grid:
|
||||
|
||||
* SSH must be installed on the master and on the slave machines;
|
||||
* SSH keys must be installed so that the SSH connection from
|
||||
the master to the slaves can be done without passwords, or
|
||||
using an SSH agent.
|
||||
|
||||
We now turn to the description of the configuration directives. Note
|
||||
that comments in the configuration file can be provided by separate
|
||||
lines starting with a hashtag (#).
|
||||
|
||||
.. confblock:: [cluster]
|
||||
|
||||
|br| When working in parallel, ``[cluster]`` is required to specify the
|
||||
group of computers that will be used. It is required even if you
|
||||
are only invoking multiple processes on one computer.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: Name = CLUSTER_NAME
|
||||
|
||||
The reference name of this cluster.
|
||||
|
||||
.. option:: Members = NODE_NAME[(WEIGHT)] NODE_NAME[(WEIGHT)] ...
|
||||
|
||||
A list of nodes that comprise the cluster with an optional
|
||||
computing weight specified for that node. The computing weight
|
||||
indicates how much more powerful one node is with respect to
|
||||
the others (e.g. ``n1(2) n2(1) n3(3)`` means that ``n1`` is
|
||||
two times more powerful than ``n2`` whereas ``n3`` is three
|
||||
times more powerful than ``n2``). Each node is separated by at
|
||||
least one space and the weights are in parenthesis with no
|
||||
spaces separating them from their node.
|
||||
|
||||
*Example*
|
||||
|
||||
::
|
||||
|
||||
[cluster]
|
||||
Name = c1
|
||||
Members = n1 n2 n3
|
||||
|
||||
[cluster]
|
||||
Name = c2
|
||||
Members = n1(4) n2 n3
|
||||
|
||||
|
||||
.. confblock:: [node]
|
||||
|
||||
|br| When working in parallel, ``[node]`` is required for every
|
||||
computer that will be used. The options that are required differ,
|
||||
depending on the underlying operating system and whether you are
|
||||
working locally or remotely.
|
||||
|
||||
*Options*
|
||||
|
||||
.. option:: Name = NODE_NAME
|
||||
|
||||
The reference name of this node.
|
||||
|
||||
.. option:: CPUnbr = INTEGER | [INTEGER:INTEGER]
|
||||
|
||||
If just one integer is passed, the number of processors to
|
||||
use. If a range of integers is passed, the specific processors
|
||||
to use (processor counting is defined to begin at one as
|
||||
opposed to zero). Note that using specific processors is only
|
||||
possible under Windows; under Linux and macOS, if a range is
|
||||
passed the same number of processors will be used but the
|
||||
range will be adjusted to begin at one.
|
||||
|
||||
.. option:: ComputerName = COMPUTER_NAME
|
||||
|
||||
The name or IP address of the node. If you want to run
|
||||
locally, use ``localhost`` (case-sensitive).
|
||||
|
||||
.. option:: Port = INTEGER
|
||||
|
||||
The port number to connect to on the node. The default is
|
||||
empty, meaning that the connection will be made to the default
|
||||
SSH port (22).
|
||||
|
||||
.. option:: UserName = USER_NAME
|
||||
|
||||
The username used to log into a remote system. Required for
|
||||
remote runs on all platforms.
|
||||
|
||||
.. option:: Password = PASSWORD
|
||||
|
||||
The password used to log into the remote system. Required for
|
||||
remote runs originating from Windows.
|
||||
|
||||
.. option:: RemoteDrive = DRIVE_NAME
|
||||
|
||||
The drive to be used for remote computation. Required for
|
||||
remote runs originating from Windows.
|
||||
|
||||
.. option:: RemoteDirectory = PATH
|
||||
|
||||
The directory to be used for remote computation. Required for
|
||||
remote runs on all platforms.
|
||||
|
||||
.. option:: DynarePath = PATH
|
||||
|
||||
The path to the matlab subdirectory within the Dynare
|
||||
installation directory. The default is the empty string.
|
||||
|
||||
.. option:: MatlabOctavePath = PATH_AND_FILE
|
||||
|
||||
The path to the MATLAB or Octave executable. The default value
|
||||
is ``matlab``.
|
||||
|
||||
.. option:: NumberOfThreadsPerJob = INTEGER
|
||||
|
||||
For Windows nodes, sets the number of threads assigned to each
|
||||
remote MATLAB/Octave run. The default value is 1.
|
||||
|
||||
.. option:: SingleCompThread = BOOLEAN
|
||||
|
||||
Whether or not to disable MATLAB’s native multithreading. The
|
||||
default value is ``false``. Option meaningless under Octave.
|
||||
|
||||
.. option:: OperatingSystem = OPERATING_SYSTEM
|
||||
|
||||
The operating system associated with a node. Only necessary
|
||||
when creating a cluster with nodes from different operating
|
||||
systems. Possible values are ``unix`` or ``windows``. There is
|
||||
no default value.
|
||||
|
||||
*Example*
|
||||
|
||||
::
|
||||
|
||||
[node]
|
||||
Name = n1
|
||||
ComputerName = localhost
|
||||
CPUnbr = 1
|
||||
|
||||
[node]
|
||||
Name = n2
|
||||
ComputerName = dynserv.cepremap.org
|
||||
CPUnbr = 5
|
||||
UserName = usern
|
||||
RemoteDirectory = /home/usern/Remote
|
||||
DynarePath = /home/usern/dynare/matlab
|
||||
MatlabOctavePath = matlab
|
||||
|
||||
[node]
|
||||
Name = n3
|
||||
ComputerName = dynserv.dynare.org
|
||||
Port = 3333
|
||||
CPUnbr = [2:4]
|
||||
UserName = usern
|
||||
RemoteDirectory = /home/usern/Remote
|
||||
DynarePath = /home/usern/dynare/matlab
|
||||
MatlabOctavePath = matlab
|
||||
|
||||
.. _win-ssg:
|
||||
|
||||
Windows Step-by-Step Guide
|
||||
==========================
|
||||
|
||||
This section outlines the steps necessary on most Windows systems to
|
||||
set up Dynare for parallel execution.
|
||||
|
||||
1. Write a configuration file containing the options you want. A
|
||||
mimimum working example setting up a cluster consisting of two
|
||||
local CPU cores that allows for e.g. running two Monte Carlo
|
||||
Markov Chains in parallel is shown below.
|
||||
2. Save the configuration file somwhere. The name and file ending
|
||||
do not matter if you are providing it with the ``conffile``
|
||||
command line option. The only restrictions are that the path
|
||||
must be a valid filename, not contain non-alpha-numeric
|
||||
characters, and not contain any whitespaces. For the
|
||||
configuration file to be accessible without providing an
|
||||
explicit path at the command line, you must save it under the
|
||||
name ``dynare.ini`` into your user account’s ``Application
|
||||
Data`` folder.
|
||||
3. Install `PSTools`_ to your system, e.g. into ``C:\PSTools.``
|
||||
4. Set the Windows System Path to the ``PSTools`` folder
|
||||
(e.g. using something along the line of pressing Windows
|
||||
Key+Pause to open the System Configuration, then go to Advanced
|
||||
-> Environment Variables -> Path).
|
||||
5. Restart your computer to make the path change effective.
|
||||
6. Open Matlab and type into the command window::
|
||||
|
||||
!psexec
|
||||
|
||||
This executes the ``psexec.exe`` from PSTools on your system
|
||||
and shows whether Dynare will be able to locate it. If Matlab
|
||||
complains at this stage, you did not correctly set your Windows
|
||||
system path for the ``PSTools`` folder.
|
||||
7. If ``psexec.exe`` was located in the previous step, a popup
|
||||
will show up, asking for confirmation of the license
|
||||
agreement. Confirm this copyright notice of ``psexec`` (this
|
||||
needs to be done only once). After this, Dynare should be ready
|
||||
for parallel execution.
|
||||
8. Call Dynare on your mod-file invoking the ``parallel`` option
|
||||
and providing the path to your configuration file with the
|
||||
``conffile`` option (if you did not save it as
|
||||
``%APPDATA%\dynare.ini`` in step 2 where it should be detected
|
||||
automatically)::
|
||||
|
||||
dynare ls2003 parallel conffile='C:\Users\Dynare~1\parallel\conf_file.ini'
|
||||
|
||||
Please keep in mind that no white spaces or names longer than 8
|
||||
characters are allowed in the ``conffile`` path. The 8-character
|
||||
restriction can be circumvented by using the tilde Windows path
|
||||
notation as in the above example.
|
||||
|
||||
*Example*::
|
||||
|
||||
#cluster needs to always be defined first
|
||||
[cluster]
|
||||
#Provide a name for the cluster
|
||||
Name=Local
|
||||
#declare the nodes being member of the cluster
|
||||
Members=n1
|
||||
|
||||
#declare nodes (they need not all be part of a cluster)
|
||||
[node]
|
||||
#name of the node
|
||||
Name=n1
|
||||
#name of the computer (localhost for the current machine)
|
||||
ComputerName=localhost
|
||||
#cores to be included from this node
|
||||
CPUnbr=[1:2]
|
||||
#path to matlab.exe; on Windows, theMatlab bin folder is in the system path
|
||||
#so we only need to provide the name of the exe file
|
||||
MatlabOctavePath=matlab
|
||||
#Dynare path you are using
|
||||
DynarePath=C:/dynare/2016-05-10/matlab
|
||||
|
||||
.. _PsTools: https://technet.microsoft.com/sysinternals/pstools.aspx
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,376 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2018-2019 Dynare Team
|
||||
#
|
||||
# This file is part of Dynare.
|
||||
#
|
||||
# Dynare is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Dynare is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
sphinx.domains.dynare
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The Dynare domain.
|
||||
|
||||
Loosely based on the JavaScript domain from the Sphinx team and the CoffeScript domain
|
||||
by Stephen Sugden (available at sphinx-contrib)
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import Directive, directives
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.domains import Domain, ObjType
|
||||
from sphinx.locale import l_, _
|
||||
from sphinx.directives import ObjectDescription
|
||||
from sphinx.roles import XRefRole
|
||||
from sphinx.util.nodes import make_refnode
|
||||
from sphinx.util.docfields import Field, GroupedField, TypedField
|
||||
|
||||
############### Dynare Object types #######################
|
||||
|
||||
class DynObject(ObjectDescription):
|
||||
has_arguments = True
|
||||
display_prefix = None
|
||||
allow_nesting = False
|
||||
|
||||
def handle_signature(self, sig, signode):
|
||||
sig = sig.strip()
|
||||
|
||||
# Some variable/parameter declarations combine spaces and parenthesis
|
||||
# in a strange way, so they are treated separately
|
||||
if sig.startswith(('var V','varexo V','varexo_det V','parameters P','model_comparison F')):
|
||||
member = sig[:sig.index(' ')]
|
||||
arglist = sig[sig.index(' '):]
|
||||
# General cases
|
||||
elif '(' in sig:
|
||||
member = sig[:sig.index('(')]
|
||||
arglist = sig[sig.index('('):]
|
||||
arglist = arglist.strip()
|
||||
elif ' ' in sig:
|
||||
member = sig[:sig.index(' ')]
|
||||
arglist = sig[sig.index(' '):]
|
||||
else:
|
||||
member = sig
|
||||
arglist = None
|
||||
|
||||
prefix = self.env.ref_context.get('dynare:object', None)
|
||||
name = member.strip()
|
||||
fullname = name
|
||||
|
||||
signode['object'] = prefix
|
||||
signode['fullname'] = fullname
|
||||
|
||||
if self.display_prefix:
|
||||
signode += addnodes.desc_annotation(self.display_prefix, self.display_prefix)
|
||||
|
||||
signode += addnodes.desc_name(name, name)
|
||||
|
||||
if self.has_arguments:
|
||||
if not arglist:
|
||||
signode += addnodes.desc_parameterlist()
|
||||
else:
|
||||
signode += addnodes.desc_addname(arglist,arglist)
|
||||
return fullname, prefix
|
||||
|
||||
def add_target_and_index(self, name_obj, sig, signode):
|
||||
fullname = name_obj[0]
|
||||
if fullname not in self.state.document.ids:
|
||||
signode['names'].append(fullname)
|
||||
signode['ids'].append(fullname)
|
||||
signode['first'] = not self.names
|
||||
self.state.document.note_explicit_target(signode)
|
||||
objects = self.env.domaindata['dynare']['objects']
|
||||
|
||||
if fullname in objects:
|
||||
self.state_machine.reporter.warning(
|
||||
'duplicate object description of %s, ' % fullname +
|
||||
'other instance in ' +
|
||||
self.env.doc2path(objects[fullname][0]),line=self.lineno)
|
||||
objects[fullname] = (self.env.docname, self.objtype)
|
||||
|
||||
indextext = self.get_index_text(fullname,name_obj)
|
||||
if indextext:
|
||||
self.indexnode['entries'].append(('single', indextext, fullname,'', None))
|
||||
|
||||
def get_index_text(self, objectname, name_obj):
|
||||
name, obj = name_obj
|
||||
|
||||
regexp = re.compile(r'\s*=\s*')
|
||||
if bool(regexp.search(name)):
|
||||
aux, name = re.compile(r'\s*=\s*').split(name)
|
||||
|
||||
if self.objtype == 'function':
|
||||
return _('%s (function)') % name
|
||||
elif self.objtype == 'class':
|
||||
return _('%s (class)') % name
|
||||
elif self.objtype == 'datesmethod':
|
||||
return _('%s (dates method)') % name
|
||||
elif self.objtype == 'dseriesmethod':
|
||||
return _('%s (dseries method)') % name
|
||||
elif self.objtype == 'reportingmethod':
|
||||
return _('%s (reporting method)') % name
|
||||
elif self.objtype == 'matcomm':
|
||||
return _('%s (MATLAB command)') % name
|
||||
elif self.objtype == 'command':
|
||||
return _('%s (command)') % name
|
||||
elif self.objtype == 'block':
|
||||
return _('%s (block)') % name
|
||||
elif self.objtype == 'confblock':
|
||||
name = name[1:-1]
|
||||
return _('%s (config block)') % name
|
||||
elif self.objtype == 'macrodir':
|
||||
name = name[2:]
|
||||
return _('%s (macro directive)') % name
|
||||
|
||||
class DynCallable(DynObject):
|
||||
has_arguments = True
|
||||
|
||||
doc_field_types = [
|
||||
TypedField('arguments', label=l_('Arguments'),
|
||||
names=('argument', 'arg', 'parameter', 'param'),
|
||||
typerolename='func', typenames=('paramtype', 'type')),
|
||||
Field('returnvalue', label=l_('Returns'), has_arg=False,
|
||||
names=('returns', 'return')),
|
||||
Field('returntype', label=l_('Return type'), has_arg=False,
|
||||
names=('rtype',)),
|
||||
Field('example', label=l_('Example'), has_arg=False,
|
||||
names=('ex',)),
|
||||
]
|
||||
|
||||
class DynClass(DynObject):
|
||||
has_arguments = False
|
||||
display_prefix = 'Dynare class: '
|
||||
allow_nesting = True
|
||||
|
||||
doc_field_types = [
|
||||
TypedField('members', label=l_('Members'),
|
||||
names=('argument', 'arg', ),
|
||||
typerolename='func', typenames=('type', )),
|
||||
Field('example', label=l_('Example'), has_arg=False,
|
||||
names=('ex',)),
|
||||
]
|
||||
|
||||
class DynFunction(DynCallable):
|
||||
display_prefix = 'Function: '
|
||||
allow_nesting = True
|
||||
|
||||
class DatesMethod(DynCallable):
|
||||
display_prefix = 'Method: '
|
||||
allow_nesting = True
|
||||
|
||||
class DseriesMethod(DynCallable):
|
||||
display_prefix = 'Method: '
|
||||
allow_nesting = True
|
||||
|
||||
class ReportingMethod(DynCallable):
|
||||
display_prefix = 'Method: '
|
||||
allow_nesting = True
|
||||
|
||||
class MatComm(DynCallable):
|
||||
display_prefix = 'MATLAB/Octave command: '
|
||||
allow_nesting = False
|
||||
|
||||
class DynComm(DynCallable):
|
||||
display_prefix = 'Command: '
|
||||
allow_nesting = False
|
||||
|
||||
class DynBlock(DynCallable):
|
||||
display_prefix = 'Block: '
|
||||
allow_nesting = False
|
||||
|
||||
class DynConfBlock(DynCallable):
|
||||
display_prefix = 'Configuration block: '
|
||||
has_arguments = False
|
||||
allow_nesting = False
|
||||
|
||||
class DynMacroDir(DynCallable):
|
||||
display_prefix = 'Macro directive: '
|
||||
allow_nesting = False
|
||||
|
||||
class Constructor(DynCallable):
|
||||
display_prefix = 'Constructor: '
|
||||
allow_nesting = False
|
||||
|
||||
class DynSimpleObject(ObjectDescription):
|
||||
has_arguments = False
|
||||
allow_nesting = False
|
||||
|
||||
def handle_signature(self, sig, signode):
|
||||
sig = sig.strip()
|
||||
member = sig
|
||||
arglist = None
|
||||
prefix = self.env.ref_context.get('dynare:object', None)
|
||||
name = member
|
||||
fullname = name
|
||||
|
||||
signode['object'] = prefix
|
||||
signode['fullname'] = fullname
|
||||
|
||||
if self.display_prefix:
|
||||
signode += addnodes.desc_annotation(self.display_prefix, self.display_prefix)
|
||||
|
||||
signode += addnodes.desc_name(name, name)
|
||||
return fullname, prefix
|
||||
|
||||
def add_target_and_index(self, name_obj, sig, signode):
|
||||
fullname = name_obj[0]
|
||||
if fullname not in self.state.document.ids:
|
||||
signode['names'].append(fullname)
|
||||
signode['ids'].append(fullname)
|
||||
signode['first'] = not self.names
|
||||
self.state.document.note_explicit_target(signode)
|
||||
objects = self.env.domaindata['dynare']['objects']
|
||||
if fullname in objects:
|
||||
self.state_machine.reporter.warning(
|
||||
'duplicate object description of %s, ' % fullname +
|
||||
'other instance in ' +
|
||||
self.env.doc2path(objects[fullname][0]), line=self.lineno)
|
||||
objects[fullname] = self.env.docname, self.objtype
|
||||
|
||||
indextext = self.get_index_text(fullname,name_obj)
|
||||
if indextext:
|
||||
self.indexnode['entries'].append(('single', indextext, fullname,'', None))
|
||||
|
||||
def get_index_text(self, objectname, name_obj):
|
||||
name, obj = name_obj
|
||||
|
||||
if self.objtype == 'construct':
|
||||
name, rest = name.split(' ',1)
|
||||
return _('%s (constructor)') % name
|
||||
elif self.objtype == 'matvar':
|
||||
return _('%s (MATLAB variable)') % name
|
||||
elif self.objtype == 'specvar':
|
||||
return _('%s (special variable)') % name
|
||||
elif self.objtype == 'operator':
|
||||
endsig = name.find(' ')
|
||||
name = name[0:endsig]
|
||||
return _('%s (operator)') % name
|
||||
elif self.objtype == 'constant':
|
||||
return _('%s (constant)') % name
|
||||
|
||||
class MatlabVar(DynSimpleObject):
|
||||
display_prefix = 'MATLAB/Octave variable: '
|
||||
allow_nesting = False
|
||||
|
||||
class SpecialVar(MatlabVar):
|
||||
display_prefix = 'Special variable: '
|
||||
|
||||
class Operator(MatlabVar):
|
||||
display_prefix = 'Operator: '
|
||||
|
||||
class Constant(MatlabVar):
|
||||
display_prefix = 'Constant: '
|
||||
|
||||
class Option(MatlabVar):
|
||||
display_prefix = None
|
||||
|
||||
############## Cross-referencing ####################
|
||||
|
||||
class DynareXRefRole(XRefRole):
|
||||
def process_link(self, env, refnode, has_explicit_title, title, target):
|
||||
refnode['dynare:object'] = env.ref_context.get('dynare:object')
|
||||
return title, target
|
||||
|
||||
############### Dynare domain #######################
|
||||
|
||||
class DynareDomain(Domain):
|
||||
name = 'dynare'
|
||||
label = 'Dynare'
|
||||
object_types = {
|
||||
'function': ObjType(l_('function'), 'func'),
|
||||
'datesmethod': ObjType(l_('method'), 'datmeth'),
|
||||
'dseriesmethod': ObjType(l_('method'), 'dsermeth'),
|
||||
'reportingmethod': ObjType(l_('method'), 'repmeth'),
|
||||
'matcomm': ObjType(l_('matlab command'), 'mcomm'),
|
||||
'command': ObjType(l_('command'), 'comm'),
|
||||
'class': ObjType(l_('class'), 'class'),
|
||||
'block': ObjType(l_('block'), 'bck'),
|
||||
'confblock': ObjType(l_('config block'), 'cbck'),
|
||||
'macrodir': ObjType(l_('macro directive'), 'mdir'),
|
||||
'construct': ObjType(l_('constructor'), 'cstr'),
|
||||
'matvar': ObjType(l_('matlab variable'), 'mvar'),
|
||||
'specvar': ObjType(l_('special variable'), 'svar'),
|
||||
'operator': ObjType(l_('operator'), 'op'),
|
||||
'constant': ObjType(l_('constant'), 'const'),
|
||||
'option': ObjType(l_('option'), 'opt'),
|
||||
}
|
||||
directives = {
|
||||
'function': DynFunction,
|
||||
'datesmethod': DatesMethod,
|
||||
'dseriesmethod': DseriesMethod,
|
||||
'reportingmethod': ReportingMethod,
|
||||
'matcomm': MatComm,
|
||||
'command': DynComm,
|
||||
'class': DynClass,
|
||||
'block': DynBlock,
|
||||
'confblock': DynConfBlock,
|
||||
'macrodir': DynMacroDir,
|
||||
'construct': Constructor,
|
||||
'matvar': MatlabVar,
|
||||
'specvar': SpecialVar,
|
||||
'operator': Operator,
|
||||
'constant': Constant,
|
||||
'option': Option,
|
||||
}
|
||||
roles = {
|
||||
'func': DynareXRefRole(),
|
||||
'datmeth': DynareXRefRole(),
|
||||
'dsermeth': DynareXRefRole(),
|
||||
'repmeth': DynareXRefRole(),
|
||||
'mcomm': DynareXRefRole(),
|
||||
'comm': DynareXRefRole(),
|
||||
'class': DynareXRefRole(),
|
||||
'bck': DynareXRefRole(),
|
||||
'cbck': DynareXRefRole(),
|
||||
'mdir': DynareXRefRole(),
|
||||
'cstr': DynareXRefRole(),
|
||||
'mvar': DynareXRefRole(),
|
||||
'svar': DynareXRefRole(),
|
||||
'op': DynareXRefRole(),
|
||||
'const': DynareXRefRole(),
|
||||
'opt': DynareXRefRole(),
|
||||
}
|
||||
initial_data = {
|
||||
'objects': {},
|
||||
}
|
||||
|
||||
def clear_doc(self, docname):
|
||||
for fullname, (fn, _l) in list(self.data['objects'].items()):
|
||||
if fn == docname:
|
||||
del self.data['objects'][fullname]
|
||||
|
||||
def find_obj(self, env, obj, name, typ, searchorder=0):
|
||||
objects = self.data['objects']
|
||||
newname = name # None
|
||||
return newname, objects.get(newname)
|
||||
|
||||
def merge_domaindata(self, docnames, otherdata):
|
||||
for fullname, (fn, objtype) in otherdata['objects'].items():
|
||||
if fn in docnames:
|
||||
self.data['objects'][fullname] = (fn, objtype)
|
||||
|
||||
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
|
||||
objectname = node.get('dynare:object')
|
||||
searchorder = node.hasattr('refspecific') and 1 or 0
|
||||
name, obj = self.find_obj(env, objectname, target, typ, searchorder)
|
||||
if not obj:
|
||||
return None
|
||||
return make_refnode(builder, fromdocname, obj[0], name, contnode, name)
|
||||
|
||||
def get_objects(self):
|
||||
for refname, (docname, type) in list(self.data['objects'].items()):
|
||||
yield refname, refname, type, docname, refname, 1
|
|
@ -0,0 +1,111 @@
|
|||
# Copyright (C) 2018-2019 Dynare Team
|
||||
#
|
||||
# This file is part of Dynare.
|
||||
#
|
||||
# Dynare is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Dynare is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import re
|
||||
|
||||
from pygments.lexer import Lexer, RegexLexer, bygroups, do_insertions, words
|
||||
from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
|
||||
Number, Punctuation, Generic, Whitespace
|
||||
|
||||
# Configuration block :BOLD
|
||||
#conf_blocks = ('hooks','paths','cluster','node')
|
||||
|
||||
__all__ = ['DynareLexer']
|
||||
|
||||
class DynareLexer(RegexLexer):
|
||||
|
||||
name = 'Dynare'
|
||||
aliases = ['dynare']
|
||||
filenames = ['*.mod']
|
||||
|
||||
commands = (
|
||||
"dynare","var","varexo","varexo_det","parameters","change_type","model_local_variable",
|
||||
"predetermined_variables","trend_var","log_trend_var","external_function",
|
||||
"write_latex_original_model","write_latex_dynamic_model",
|
||||
"write_latex_static_model","resid","initval_file","histval_file","dsample",
|
||||
"periods","values","corr","steady","check","model_diagnostics","model_info",
|
||||
"print_bytecode_dynamic_model"," print_bytecode_static_model",
|
||||
"perfect_foresight_setup","perfect_foresight_solver","simul","stoch_simul",
|
||||
"extended_path","varobs","estimation","unit_root_vars","bvar_density",
|
||||
"model_comparison","shock_decomposition","realtime_shock_decomposition",
|
||||
"plot_shock_decomposition","calib_smoother","forecast",
|
||||
"conditional_forecast","plot_conditional_forecast","bvar_forecast",
|
||||
"smoother2histval","osr","osr_params","ramsey_model","ramsey_policy",
|
||||
"discretionary_policy","planner_objective","dynare_sensitivity",
|
||||
"markov_switching","svar","sbvar","ms_estimation","ms_simulation",
|
||||
"ms_compute_mdd","ms_compute_probabilities","ms_irf","ms_forecast",
|
||||
"ms_variance_decomposition","rplot","dynatype","dynasave","set_dynare_seed",
|
||||
"save_params_and_steady_state","load_params_and_steady_state",
|
||||
"dynare_version","write_latex_definitions","write_latex_parameter_table",
|
||||
"write_latex_prior_table","collect_latex_files","prior_function",
|
||||
"posterior_function","generate_trace_plots")
|
||||
|
||||
report_commands = ("report","addPage","addSection","addGraph","addTable",
|
||||
"addSeries","addParagraph","addVspace","write","compile")
|
||||
|
||||
operators = (
|
||||
"STEADY_STATE","EXPECTATION")
|
||||
|
||||
macro_dirs = (
|
||||
"@#includepath", "@#include", "@#define", "@#if",
|
||||
"@#ifdef", "@#ifndef", "@#else","@#endif",
|
||||
"@#for", "@#endfor", "@#echo", "@#error")
|
||||
|
||||
builtin_constants = (
|
||||
"inf", "nan")
|
||||
|
||||
tokens = {
|
||||
'root': [
|
||||
(r'\s*(%|//).*$', Comment),
|
||||
|
||||
(words((
|
||||
'model','steady_state_model','initval','endval','histval',
|
||||
'shocks','mshocks','homotopy_setup','observation_trends',
|
||||
'estimated_params','estimated_params_init','estimated_params_bounds',
|
||||
'shock_groups','conditional_forecast_paths','optim_weights',
|
||||
'osr_params_bounds','ramsey_constraints','irf_calibration',
|
||||
'moment_calibration','identification','svar_identification',
|
||||
'verbatim','end','node','cluster','paths','hooks'), prefix=r'\b', suffix=r'\s*\b'),Keyword.Reserved),
|
||||
|
||||
(words(commands + report_commands,
|
||||
prefix=r'\b', suffix=r'\s*\b'), Name.Entity),
|
||||
|
||||
(words(operators), Operator.Word),
|
||||
|
||||
(words(macro_dirs,suffix=r'\s*'), Name.Function),
|
||||
|
||||
(words(builtin_constants), Name.Constant),
|
||||
|
||||
(r'\s*[a-zA-Z_]\s*', Name),
|
||||
|
||||
|
||||
(r'\s*(\d+\.\d+|\d*\.\d+)([eEf][+-]?[0-9]+)?\s*', Number.Float),
|
||||
(r'\s*\d+[eEf][+-]?[0-9]+\s*', Number.Float),
|
||||
(r'\s*\d+\s*', Number.Integer),
|
||||
|
||||
(r'"[^"]*"', String),
|
||||
(r"`[^`]*'", String),
|
||||
(r"'[^']*'", String),
|
||||
|
||||
(r'\s*(-|\+|\*|\/|\^)\s*', Operator),
|
||||
(r'\s*(==|<=|>=|~=|<|>|&&|!)\s*', Operator),
|
||||
|
||||
(r'\s*[\[\](){}:@.,\|]\s*', Punctuation),
|
||||
(r'\s*(=|:|;|>>|#|\$)\s*', Punctuation),
|
||||
]
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
version = u'@PACKAGE_VERSION@'
|
||||
release = u'@PACKAGE_VERSION@'
|
|
@ -1,3 +1 @@
|
|||
SUBDIRS = sylv parser/cc tl doc utils/cc integ kord src
|
||||
|
||||
EXTRA_DIST = change_log.html c++lib.w tests extern
|
||||
SUBDIRS = utils/cc sylv parser/cc tl doc integ kord src tests
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
@q This file defines standard C++ namespaces and classes @>
|
||||
@q Please send corrections to saroj-tamasa@@worldnet.att.net @>
|
||||
@s std int
|
||||
@s rel_ops int
|
||||
@s bitset int
|
||||
@s char_traits int
|
||||
@s deque int
|
||||
@s list int
|
||||
@s map int
|
||||
@s multimap int
|
||||
@s multiset int
|
||||
@s pair int
|
||||
@s set int
|
||||
@s stack int
|
||||
@s exception int
|
||||
@s logic_error int
|
||||
@s runtime_error int
|
||||
@s domain_error int
|
||||
@s invalid_argument int
|
||||
@s length_error int
|
||||
@s out_of_range int
|
||||
@s range_error int
|
||||
@s overflow_error int
|
||||
@s underflow_error int
|
||||
@s back_insert_iterator int
|
||||
@s front_insert_iterator int
|
||||
@s insert_iterator int
|
||||
@s reverse_iterator int
|
||||
@s istream_iterator int
|
||||
@s ostream_iterator int
|
||||
@s istreambuf_iterator int
|
||||
@s ostreambuf_iterator int
|
||||
@s iterator_traits int
|
||||
@s queue int
|
||||
@s vector int
|
||||
@s basic_string int
|
||||
@s string int
|
||||
@s auto_ptr int
|
||||
@s valarray int
|
||||
@s ios_base int
|
||||
@s basic_ios int
|
||||
@s basic_streambuf int
|
||||
@s basic_istream int
|
||||
@s basic_ostream int
|
||||
@s basic_iostream int
|
||||
@s basic_stringbuf int
|
||||
@s basic_istringstream int
|
||||
@s basic_ostringstream int
|
||||
@s basic_stringstream int
|
||||
@s basic_filebuf int
|
||||
@s basic_ifstream int
|
||||
@s basic_ofstream int
|
||||
@s basic_fstream int
|
||||
@s ctype int
|
||||
@s collate int
|
||||
@s collate_byname int
|
||||
@s streambuf int
|
||||
@s istream int
|
||||
@s ostream int
|
||||
@s iostream int
|
||||
@s stringbuf int
|
||||
@s istringstream int
|
||||
@s ostringstream int
|
||||
@s stringstream int
|
||||
@s filebuf int
|
||||
@s ifstream int
|
||||
@s ofstream int
|
||||
@s fstream int
|
||||
@s wstreambuf int
|
||||
@s wistream int
|
||||
@s wostream int
|
||||
@s wiostram int
|
||||
@s wstringbuf int
|
||||
@s wistringstream int
|
||||
@s wostringstream int
|
||||
@s wstringstream int
|
||||
@s wfilebuf int
|
||||
@s wifstream int
|
||||
@s wofstream int
|
||||
@s wfstream int
|
||||
@s streamoff int
|
||||
@s streamsize int
|
||||
@s fpos int
|
||||
@s streampos int
|
||||
@s wstreampos int
|
|
@ -1,7 +1,13 @@
|
|||
EXTRA_DIST = dynare++-ramsey.tex dynare++-tutorial.tex
|
||||
EXTRA_DIST = \
|
||||
dynare++-ramsey.tex \
|
||||
dynare++-tutorial.tex \
|
||||
sylvester.tex \
|
||||
tl.tex \
|
||||
changelog-old.html \
|
||||
changelog-sylv-old.html
|
||||
|
||||
if HAVE_PDFLATEX
|
||||
pdf-local: dynare++-ramsey.pdf dynare++-tutorial.pdf
|
||||
pdf-local: dynare++-ramsey.pdf dynare++-tutorial.pdf sylvester.pdf tl.pdf
|
||||
endif
|
||||
|
||||
%.pdf: %.tex
|
||||
|
|
|
@ -1033,12 +1033,8 @@ default.
|
|||
threads. Complex evaluations of Faa Di Bruno formulas, simulations and
|
||||
numerical integration can be parallelized, Dynare++ exploits this
|
||||
advantage. You have to have a hardware support for this, otherwise
|
||||
there is no gain from the parallelization. As a rule of thumb, set the
|
||||
number of threads to the number of processors. An exception is a
|
||||
machine with Pentium 4 with Hyper Threading (abbreviated by HT). This
|
||||
processor can run two threads concurrently. The same applies to
|
||||
Dual-Core processors. Since these processors are present in most new
|
||||
PC desktops/laptops, the default is 2.
|
||||
there is no gain from the parallelization. The default value is the number of
|
||||
logical processors present on the machine, divided by 2.
|
||||
|
||||
\item[\desc{\tt --ss-tol \it float}] This sets the tolerance of the
|
||||
non-linear solver of deterministic steady state to {\it float}. It is
|
||||
|
|
|
@ -1,20 +1,27 @@
|
|||
\input amstex
|
||||
\documentstyle{amsppt}
|
||||
\def\vec{\mathop{\hbox{vec}}}
|
||||
\def\otimesi{\mathop{\overset{\ssize i}\to{\otimes}}}
|
||||
\def\iF{\,^i\!F}
|
||||
\def\imF{\,^{i-1}\!F}
|
||||
\def\solvi{\bold{solv1}}
|
||||
\def\solvii{\bold{solv2}}
|
||||
\def\solviip{\bold{solv2p}}
|
||||
\documentclass[11pt,a4paper]{article}
|
||||
|
||||
\topmatter
|
||||
\title Solution of Specialized Sylvester Equation\endtitle
|
||||
\author Ondra Kamenik\endauthor
|
||||
\email ondrej.kamenik@cnb.cz\endemail
|
||||
\endtopmatter
|
||||
\usepackage{amssymb}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amsthm}
|
||||
|
||||
\usepackage{fullpage}
|
||||
|
||||
\begin{document}
|
||||
\title{Solution of Specialized Sylvester Equation}
|
||||
\author{Ondra Kamenik}
|
||||
\date{2004}
|
||||
\maketitle
|
||||
|
||||
\renewcommand{\vec}{\mathop{\hbox{vec}}}
|
||||
\newcommand{\otimesi}{\mathop{\overset{i}{\otimes}}}
|
||||
\newcommand{\iF}{\,^i\!F}
|
||||
\newcommand{\imF}{\,^{i-1}\!F}
|
||||
\newcommand{\solvi}{\mathbf{solv1}}
|
||||
\newcommand{\solvii}{\mathbf{solv2}}
|
||||
\newcommand{\solviip}{\mathbf{solv2p}}
|
||||
|
||||
\newtheorem{lemma}{Lemma}
|
||||
|
||||
\document
|
||||
Given the following matrix equation
|
||||
$$AX+BX\left(\otimesi C\right)=D,$$ where $A$ is regular $n\times n$
|
||||
matrix, $X$ is $n\times m^i$ matrix of unknowns, $B$ is singular
|
||||
|
@ -36,173 +43,168 @@ and vectorized
|
|||
$$\left(I+\otimesi F^T\otimes K\right)\vec(Y)=\vec(\widehat{D})$$
|
||||
Let $\iF$ denote $\otimesi F^T$ for the rest of the text.
|
||||
|
||||
\proclaim{Lemma 1}
|
||||
\section{Preliminary results}
|
||||
|
||||
\begin{lemma}
|
||||
\label{sylv:first-lemma}
|
||||
For any $n\times n$ matrix $A$ and $\beta_1\beta_2>0$, if there is
|
||||
exactly one solution of
|
||||
$$\left(I_2\otimes I_n +
|
||||
\pmatrix\alpha&\beta_1\cr-\beta_2&\alpha\endpmatrix
|
||||
\otimes A\right)\pmatrix x_1\cr x_2\endpmatrix =
|
||||
\pmatrix d_1\cr d_2\endpmatrix,$$
|
||||
\begin{pmatrix}\alpha&\beta_1\cr-\beta_2&\alpha\end{pmatrix}
|
||||
\otimes A\right)\begin{pmatrix} x_1\cr x_2\end{pmatrix} =
|
||||
\begin{pmatrix} d_1\cr d_2\end{pmatrix},$$
|
||||
then it can be obtained as solution of
|
||||
$$\align
|
||||
\begin{align*}
|
||||
\left(I_n + 2\alpha A+(\alpha^2+\beta^2)A^2\right)x_1 & =
|
||||
\widehat{d_1}\\
|
||||
\left(I_n + 2\alpha A+(\alpha^2+\beta^2)A^2\right)x_2 & =
|
||||
\widehat{d_2}
|
||||
\endalign$$
|
||||
\end{align*}
|
||||
where $\beta=\sqrt{\beta1\beta2}$, and
|
||||
$$
|
||||
\pmatrix \widehat{d_1}\cr\widehat{d_2}\endpmatrix =
|
||||
\begin{pmatrix} \widehat{d_1}\cr\widehat{d_2}\end{pmatrix} =
|
||||
\left(I_2\otimes I_n +
|
||||
\pmatrix\alpha&-\beta_1\cr\beta_2&\alpha\endpmatrix
|
||||
\otimes A\right)\pmatrix d_1\cr d_2\endpmatrix$$
|
||||
\endproclaim
|
||||
\begin{pmatrix}\alpha&-\beta_1\cr\beta_2&\alpha\end{pmatrix}
|
||||
\otimes A\right)\begin{pmatrix} d_1\cr d_2\end{pmatrix}$$
|
||||
\end{lemma}
|
||||
|
||||
\demo{Proof} Since
|
||||
\begin{proof} Since
|
||||
$$
|
||||
\pmatrix \alpha&\beta_1\cr-\beta_2&\alpha\endpmatrix
|
||||
\pmatrix \alpha&-\beta_1\cr\beta_2&\alpha\endpmatrix
|
||||
\begin{pmatrix} \alpha&\beta_1\cr-\beta_2&\alpha\end{pmatrix}
|
||||
\begin{pmatrix} \alpha&-\beta_1\cr\beta_2&\alpha\end{pmatrix}
|
||||
=
|
||||
\pmatrix \alpha&-\beta_1\cr\beta_2&\alpha\endpmatrix
|
||||
\pmatrix \alpha&\beta_1\cr-\beta_2&\alpha\endpmatrix
|
||||
\begin{pmatrix} \alpha&-\beta_1\cr\beta_2&\alpha\end{pmatrix}
|
||||
\begin{pmatrix} \alpha&\beta_1\cr-\beta_2&\alpha\end{pmatrix}
|
||||
=
|
||||
\pmatrix \alpha^2+\beta^2&0\cr 0&\alpha^2+\beta^2\endpmatrix,
|
||||
\begin{pmatrix} \alpha^2+\beta^2&0\cr 0&\alpha^2+\beta^2\end{pmatrix},
|
||||
$$
|
||||
it is easy to see that if the equation is multiplied by
|
||||
$$I_2\otimes I_n +
|
||||
\pmatrix\alpha&-\beta_1\cr\beta_2&\alpha\endpmatrix
|
||||
\begin{pmatrix}\alpha&-\beta_1\cr\beta_2&\alpha\end{pmatrix}
|
||||
\otimes A$$
|
||||
we obtain the result. We only need to prove that the matrix is
|
||||
regular. But this is clear because matrix
|
||||
$$\pmatrix \alpha&-\beta_1\cr\beta_2&\alpha\endpmatrix$$
|
||||
$$\begin{pmatrix} \alpha&-\beta_1\cr\beta_2&\alpha\end{pmatrix}$$
|
||||
collapses an eigenvalue of $A$ to $-1$ iff the matrix
|
||||
$$\pmatrix \alpha&\beta_1\cr-\beta_2&\alpha\endpmatrix$$
|
||||
does.\qed
|
||||
\enddemo
|
||||
$$\begin{pmatrix} \alpha&\beta_1\cr-\beta_2&\alpha\end{pmatrix}$$
|
||||
does.
|
||||
\end{proof}
|
||||
|
||||
\proclaim{Lemma 2}
|
||||
\begin{lemma}
|
||||
\label{sylv:second-lemma}
|
||||
For any $n\times n$ matrix $A$ and $\delta_1\delta_2>0$, if there is
|
||||
exactly one solution of
|
||||
$$\left(I_2\otimes I_n +
|
||||
2\alpha\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix\otimes A
|
||||
2\alpha\begin{pmatrix}\gamma&\delta_1\cr-\delta_2&\gamma\end{pmatrix}\otimes A
|
||||
+(\alpha^2+\beta^2)
|
||||
\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix^2\otimes A^2\right)
|
||||
\pmatrix x_1\cr x_2\endpmatrix=
|
||||
\pmatrix d_1\cr d_2\endpmatrix
|
||||
\begin{pmatrix}\gamma&\delta_1\cr-\delta_2&\gamma\end{pmatrix}^2\otimes A^2\right)
|
||||
\begin{pmatrix} x_1\cr x_2\end{pmatrix}=
|
||||
\begin{pmatrix} d_1\cr d_2\end{pmatrix}
|
||||
$$
|
||||
it can be obtained as
|
||||
$$
|
||||
\align
|
||||
\begin{align*}
|
||||
\left(I_n+2a_1A+(a_1^2+b_1^2)A^2\right)\left(I_n+2a_2A+(a_2^2+b_2^2)A^2\right)
|
||||
x_1 & =\widehat{d_1}\\
|
||||
\left(I_n+2a_1A+(a_1^2+b_1^2)A^2\right)\left(I_n+2a_2A+(a_2^2+b_2^2)A^2\right)
|
||||
x_2 & =\widehat{d_2}
|
||||
\endalign$$
|
||||
\end{align*}
|
||||
where
|
||||
$$
|
||||
\pmatrix \widehat{d_1}\cr\widehat{d_2}\endpmatrix =
|
||||
\begin{pmatrix} \widehat{d_1}\cr\widehat{d_2}\end{pmatrix} =
|
||||
\left(I_2\otimes I_n +
|
||||
2\alpha\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix\otimes A
|
||||
2\alpha\begin{pmatrix}\gamma&-\delta_1\cr\delta_2&\gamma\end{pmatrix}\otimes A
|
||||
+(\alpha^2+\beta^2)
|
||||
\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix^2\otimes A^2\right)
|
||||
\pmatrix d_1\cr d_2\endpmatrix
|
||||
\begin{pmatrix}\gamma&-\delta_1\cr\delta_2&\gamma\end{pmatrix}^2\otimes A^2\right)
|
||||
\begin{pmatrix} d_1\cr d_2\end{pmatrix}
|
||||
$$
|
||||
and
|
||||
$$
|
||||
\align
|
||||
\begin{align*}
|
||||
a_1 & = \alpha\gamma - \beta\delta\\
|
||||
b_1 & = \alpha\delta + \gamma\beta\\
|
||||
a_2 & = \alpha\gamma + \beta\delta\\
|
||||
b_2 & = \alpha\delta - \gamma\beta\\
|
||||
\delta & = \sqrt{\delta_1\delta_2}
|
||||
\endalign$$
|
||||
\endproclaim
|
||||
\end{align*}
|
||||
|
||||
\demo{Proof}
|
||||
\end{lemma}
|
||||
|
||||
\begin{proof}
|
||||
The matrix can be written as
|
||||
$$\left(I_2\otimes I_n+(\alpha+\roman i\beta)
|
||||
\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix\otimes A\right)
|
||||
\left(I_2\otimes I_n +(\alpha-\roman i\beta)
|
||||
\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix\otimes A\right).
|
||||
$$\left(I_2\otimes I_n+(\alpha+\mathrm i\beta)
|
||||
\begin{pmatrix}\gamma&\delta_1\cr-\delta_2&\gamma\end{pmatrix}\otimes A\right)
|
||||
\left(I_2\otimes I_n +(\alpha-\mathrm i\beta)
|
||||
\begin{pmatrix}\gamma&\delta_1\cr-\delta_2&\gamma\end{pmatrix}\otimes A\right).
|
||||
$$
|
||||
Note that the both matrices are regular since their product is
|
||||
regular. For the same reason as in the previous proof, the following
|
||||
matrix is also regular
|
||||
$$\left(I_2\otimes I_n+(\alpha+\roman i\beta)
|
||||
\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix\otimes A\right)
|
||||
\left(I_2\otimes I_n +(\alpha-\roman i\beta)
|
||||
\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix\otimes A\right),
|
||||
$$\left(I_2\otimes I_n+(\alpha+\mathrm i\beta)
|
||||
\begin{pmatrix}\gamma&-\delta_1\cr\delta_2&\gamma\end{pmatrix}\otimes A\right)
|
||||
\left(I_2\otimes I_n +(\alpha-\mathrm i\beta)
|
||||
\begin{pmatrix}\gamma&-\delta_1\cr\delta_2&\gamma\end{pmatrix}\otimes A\right),
|
||||
$$
|
||||
and we may multiply the equation by this matrix obtaining
|
||||
$\widehat{d_1}$ and $\widehat{d_2}$. Note that the four matrices
|
||||
commute, that is why we can write the whole product as
|
||||
$$
|
||||
\align
|
||||
\left(I_2\otimes I_n + (\alpha+\roman i\beta)
|
||||
\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix\otimes A\right)\cdot
|
||||
\left(I_2\otimes I_n + (\alpha+\roman i\beta)
|
||||
\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix\otimes A\right)&\cdot\\
|
||||
\left(I_2\otimes I_n + (\alpha-\roman i\beta)
|
||||
\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix\otimes A\right)\cdot
|
||||
\left(I_2\otimes I_n + (\alpha-\roman i\beta)
|
||||
\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix\otimes A\right)&=\\
|
||||
\left(I_2\otimes I_n + 2(\alpha + \roman i\beta)
|
||||
\pmatrix\gamma&0\cr 0&\gamma\endpmatrix\otimes A +
|
||||
(\alpha + \roman i\beta)^2
|
||||
\pmatrix\gamma^2+\delta^2&0\cr 0&\gamma^2+\delta^2\endpmatrix\otimes A^2
|
||||
\begin{align*}
|
||||
\left(I_2\otimes I_n + (\alpha+\mathrm i\beta)
|
||||
\begin{pmatrix}\gamma&\delta_1\cr-\delta_2&\gamma\end{pmatrix}\otimes A\right)\cdot
|
||||
\left(I_2\otimes I_n + (\alpha+\mathrm i\beta)
|
||||
\begin{pmatrix}\gamma&-\delta_1\cr\delta_2&\gamma\end{pmatrix}\otimes A\right)&\cdot\\
|
||||
\left(I_2\otimes I_n + (\alpha-\mathrm i\beta)
|
||||
\begin{pmatrix}\gamma&\delta_1\cr-\delta_2&\gamma\end{pmatrix}\otimes A\right)\cdot
|
||||
\left(I_2\otimes I_n + (\alpha-\mathrm i\beta)
|
||||
\begin{pmatrix}\gamma&-\delta_1\cr\delta_2&\gamma\end{pmatrix}\otimes A\right)&=\\
|
||||
\left(I_2\otimes I_n + 2(\alpha + \mathrm i\beta)
|
||||
\begin{pmatrix}\gamma&0\cr 0&\gamma\end{pmatrix}\otimes A +
|
||||
(\alpha + \mathrm i\beta)^2
|
||||
\begin{pmatrix}\gamma^2+\delta^2&0\cr 0&\gamma^2+\delta^2\end{pmatrix}\otimes A^2
|
||||
\right)&\cdot\\
|
||||
\left(I_2\otimes I_n + 2(\alpha - \roman i\beta)
|
||||
\pmatrix\gamma&0\cr 0&\gamma\endpmatrix\otimes A +
|
||||
(\alpha - \roman i\beta)^2
|
||||
\pmatrix\gamma^2+\delta^2&0\cr 0&\gamma^2+\delta^2\endpmatrix\otimes A^2
|
||||
\left(I_2\otimes I_n + 2(\alpha - \mathrm i\beta)
|
||||
\begin{pmatrix}\gamma&0\cr 0&\gamma\end{pmatrix}\otimes A +
|
||||
(\alpha - \mathrm i\beta)^2
|
||||
\begin{pmatrix}\gamma^2+\delta^2&0\cr 0&\gamma^2+\delta^2\end{pmatrix}\otimes A^2
|
||||
\right)&
|
||||
\endalign
|
||||
$$
|
||||
\end{align*}
|
||||
|
||||
The product is a diagonal consiting of two $n\times n$ blocks, which are the
|
||||
same. The block can be rewritten as product:
|
||||
$$
|
||||
\align
|
||||
(I_n+(\alpha+\roman i\beta)(\gamma+\roman i\delta)A)\cdot
|
||||
(I_n+(\alpha+\roman i\beta)(\gamma-\roman i\delta)A)&\cdot\\
|
||||
(I_n+(\alpha-\roman i\beta)(\gamma+\roman i\delta)A)\cdot
|
||||
(I_n+(\alpha-\roman i\beta)(\gamma-\roman i\delta)A)&
|
||||
\endalign
|
||||
$$
|
||||
\begin{align*}
|
||||
(I_n+(\alpha+\mathrm i\beta)(\gamma+\mathrm i\delta)A)\cdot
|
||||
(I_n+(\alpha+\mathrm i\beta)(\gamma-\mathrm i\delta)A)&\cdot\\
|
||||
(I_n+(\alpha-\mathrm i\beta)(\gamma+\mathrm i\delta)A)\cdot
|
||||
(I_n+(\alpha-\mathrm i\beta)(\gamma-\mathrm i\delta)A)&
|
||||
\end{align*}
|
||||
and after reordering
|
||||
$$
|
||||
\align
|
||||
(I_n+(\alpha+\roman i\beta)(\gamma+\roman i\delta)A)\cdot
|
||||
(I_n+(\alpha-\roman i\beta)(\gamma-\roman i\delta)A)&\cdot\\
|
||||
(I_n+(\alpha+\roman i\beta)(\gamma-\roman i\delta)A)\cdot
|
||||
(I_n+(\alpha-\roman i\beta)(\gamma+\roman i\delta)A)&=\\
|
||||
\begin{align*}
|
||||
(I_n+(\alpha+\mathrm i\beta)(\gamma+\mathrm i\delta)A)\cdot
|
||||
(I_n+(\alpha-\mathrm i\beta)(\gamma-\mathrm i\delta)A)&\cdot\\
|
||||
(I_n+(\alpha+\mathrm i\beta)(\gamma-\mathrm i\delta)A)\cdot
|
||||
(I_n+(\alpha-\mathrm i\beta)(\gamma+\mathrm i\delta)A)&=\\
|
||||
(I_n+2(\alpha\gamma-\beta\delta)A+
|
||||
(\alpha^2+\beta^2)(\gamma^2+\delta^2)A^2)&\cdot\\
|
||||
(I_n+2(\alpha\gamma+\beta\delta)A+
|
||||
(\alpha^2+\beta^2)(\gamma^2+\delta^2)A^2)&
|
||||
\endalign
|
||||
$$
|
||||
\end{align*}
|
||||
Now it suffices to compare $a_1=\alpha\gamma-\beta\delta$ and verify
|
||||
that
|
||||
$$
|
||||
\align
|
||||
\begin{align*}
|
||||
b_1^2 & = (\alpha^2+\beta^2)(\gamma^2+\delta^2)-a_1^2 =\cr
|
||||
& = \alpha^2\gamma^2+\beta^2\gamma^2+\alpha^2\beta^2+\beta^2\delta^2-
|
||||
(\alpha\gamma)^2+2\alpha\beta\gamma\delta-(\beta\delta)^2=\cr
|
||||
& = (\beta\gamma)^2 + (\alpha\beta)^2 + 2\alpha\beta\gamma\delta=\cr
|
||||
& = (\beta\gamma +\alpha\beta)^2
|
||||
\endalign
|
||||
$$
|
||||
\end{align*}
|
||||
For $b_2$ it is done in the same way.
|
||||
\qed
|
||||
\enddemo
|
||||
\end{proof}
|
||||
|
||||
\head The Algorithm\endhead
|
||||
\section{The Algorithm}
|
||||
|
||||
Below we define three functions of which
|
||||
$\vec(Y)=\solvi(1,\vec(\widehat{D}),i)$ provides the solution $Y$. $X$
|
||||
is then obtained as $X=U^TY\left(\otimesi V\right)$.
|
||||
|
||||
\subhead Synopsis\endsubhead
|
||||
\subsection{Synopsis}
|
||||
|
||||
$F^T$ is $m\times m$ lower quasi-triangular matrix. Let $m_r$ be a
|
||||
number of real eigenvalues, $m_c$ number of complex pairs. Thus
|
||||
|
@ -215,7 +217,7 @@ vectors of appropriate dimensions, and $x_{\bar j}$ is $\bar j$-th
|
|||
partition of $x$, and $x_j=(x_{\bar j}\quad x_{\bar j+1})^T$ if $j$-th
|
||||
eigenvalue is complex, and $x_j=x_{\bar j}$ if $j$-th eigenvalue is real.
|
||||
|
||||
\subhead Function $\solvi$\endsubhead
|
||||
\subsection{Function $\solvi$}
|
||||
|
||||
The function $x=\solvi(r,d,i)$ solves equation
|
||||
$$\left(I_{m^i}\otimes I_n+r\iF\otimes K\right)x = d.$$
|
||||
|
@ -226,7 +228,7 @@ quasi-triangular matrix, so this is easy.
|
|||
|
||||
If $i>0$, then we go through diagonal blocks $F_j$ for
|
||||
$j=1,\ldots, m_r+m_c$ and perform:
|
||||
\roster
|
||||
\begin{enumerate}
|
||||
\item if $F_j=(f_{\bar j\bar j}) = (f)$, then we return
|
||||
$x_j=\solvi(rf,d_{\bar j}, i-1)$. Then precalculate $y=d_j-x_j$, and
|
||||
eliminate guys below $F_j$. This is, for each $k=\bar j+1,\ldots, m$, we
|
||||
|
@ -234,46 +236,45 @@ put
|
|||
$$d_k = d_k-rf_{\bar jk}\left(\imF\otimes K\right)x_{\bar j}=
|
||||
d_k - \frac{f_{\bar jk}}{f}y$$
|
||||
|
||||
\item if $F_j=\pmatrix\alpha&\beta_1\cr -\beta_2&\alpha\endpmatrix$,
|
||||
\item if $F_j=\begin{pmatrix}\alpha&\beta_1\cr -\beta_2&\alpha\end{pmatrix}$,
|
||||
we return $x_j=\solvii(r\alpha, r\beta_1, r\beta_2, d_j, i-1)$. Then
|
||||
we precalculate
|
||||
$$y=\left(\pmatrix\alpha&-\beta_1\cr \beta_2&\alpha\endpmatrix
|
||||
$$y=\left(\begin{pmatrix}\alpha&-\beta_1\cr \beta_2&\alpha\end{pmatrix}
|
||||
\otimes I_{m^{i-1}}\otimes I_n\right)
|
||||
\pmatrix d_{\bar j} - x_{\bar j}\cr
|
||||
\begin{pmatrix} d_{\bar j} - x_{\bar j}\cr
|
||||
d_{\bar j+1} - x_{\bar j+1}
|
||||
\endpmatrix$$
|
||||
\end{pmatrix}$$
|
||||
and eliminate guys below $F_j$. This is, for each $k=\bar j+2,\ldots, n$
|
||||
we put
|
||||
$$
|
||||
\align
|
||||
\begin{align*}
|
||||
d_k &= d_k - r(f_{{\bar j}k}\quad f_{{\bar j}+1 k})
|
||||
\otimes\left(\imF\otimes K\right)x_j\\
|
||||
&= d_k - \frac{1}{\alpha^2+\beta_1\beta_2}
|
||||
\left((f_{{\bar j}k}\quad f_{{\bar j}+1 k})
|
||||
\otimes I_{m^{i-1}}\otimes I_n\right)y
|
||||
\endalign
|
||||
$$
|
||||
\endroster
|
||||
\end{align*}
|
||||
|
||||
\subhead Function $\solvii$\endsubhead
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Function $\solvii$}
|
||||
|
||||
The function $x=\solvii(\alpha, \beta_1, \beta_2, d, i)$ solves
|
||||
equation
|
||||
$$
|
||||
\left(I_2\otimes I_{m^i}\otimes I_n +
|
||||
\pmatrix\alpha&\beta_1\cr-\beta_2&\alpha\endpmatrix
|
||||
\begin{pmatrix}\alpha&\beta_1\cr-\beta_2&\alpha\end{pmatrix}
|
||||
\otimes\iF\otimes K\right)x=d
|
||||
$$
|
||||
|
||||
According to {\bf Lemma 1} the function returns
|
||||
According to Lemma \ref{sylv:first-lemma} the function returns
|
||||
$$
|
||||
x=\pmatrix\solviip(\alpha,\beta_1\beta_2,\widehat{d_1},i)\cr
|
||||
\solviip(\alpha,\beta_1\beta_2,\widehat{d_2},i)\endpmatrix,
|
||||
x=\begin{pmatrix}\solviip(\alpha,\beta_1\beta_2,\widehat{d_1},i)\cr
|
||||
\solviip(\alpha,\beta_1\beta_2,\widehat{d_2},i)\end{pmatrix},
|
||||
$$
|
||||
where $\widehat{d_1}$, and $\widehat{d_2}$ are partitions of
|
||||
$\widehat{d}$ from the lemma.
|
||||
|
||||
\subhead Function $\solviip$\endsubhead
|
||||
\subsection{Function $\solviip$}
|
||||
|
||||
The function $x=\solviip(\alpha,\beta^2,d,i)$ solves equation
|
||||
$$
|
||||
|
@ -291,7 +292,7 @@ then it is lower triangular.
|
|||
|
||||
If $i>0$, then we go through diagonal blocks $F_j$ for $j=1,\ldots, m_r+m_c$
|
||||
and perform:
|
||||
\roster
|
||||
\begin{enumerate}
|
||||
\item if $F_j=(f_{\bar j\bar j})=(f)$ then $j$-th diagonal block of
|
||||
$$
|
||||
I_{m^i}\otimes I_n + 2\alpha\iF\otimes K +
|
||||
|
@ -311,16 +312,14 @@ $$y_1 = 2\alpha f(\imF\otimes K)x_j = d_j-x_j-y_2.$$
|
|||
Let $g_{pq}$ denote element of $F^{2T}$ at position $(q,p)$.
|
||||
The elimination is done by going through $k=\bar j+1,\ldots, m$ and
|
||||
putting
|
||||
$$
|
||||
\align
|
||||
\begin{align*}
|
||||
d_k &= d_k - \left(2\alpha f_{\bar j k}\imF\otimes K +
|
||||
(\alpha^2+\beta^2)g_{\bar j k}\imF^2\otimes K^2\right)x_j\\
|
||||
&= d_k - \frac{f_{\bar j k}}{f}y_1 -
|
||||
\frac{g_{\bar j k}}{f^2}y_2
|
||||
\endalign
|
||||
$$
|
||||
\end{align*}
|
||||
|
||||
\item if $F_j=\pmatrix\gamma&\delta_1\cr -\delta_2&\gamma\endpmatrix$,
|
||||
\item if $F_j=\begin{pmatrix}\gamma&\delta_1\cr -\delta_2&\gamma\end{pmatrix}$,
|
||||
then $j$-th diagonal block of
|
||||
$$
|
||||
I_{m^i}\otimes I_n + 2\alpha\iF\otimes K +
|
||||
|
@ -329,26 +328,24 @@ $$
|
|||
takes the form
|
||||
$$
|
||||
I_{m^{i-1}}\otimes I_n +2\alpha
|
||||
\pmatrix\gamma&\delta_1\cr -\delta_2&\gamma\endpmatrix\imF\otimes K
|
||||
\begin{pmatrix}\gamma&\delta_1\cr -\delta_2&\gamma\end{pmatrix}\imF\otimes K
|
||||
+(\alpha^2+\beta^2)
|
||||
\pmatrix\gamma&\delta_1\cr -\delta_2&\gamma\endpmatrix^2\imF^2\otimes K^2
|
||||
\begin{pmatrix}\gamma&\delta_1\cr -\delta_2&\gamma\end{pmatrix}^2\imF^2\otimes K^2
|
||||
$$
|
||||
According to {\bf Lemma 2}, we need to calculate
|
||||
According to Lemma \ref{sylv:second-lemma}, we need to calculate
|
||||
$\widehat{d}_{\bar j}$, and $\widehat{d}_{\bar j+1}$, and $a_1$,
|
||||
$b_1$, $a_2$, $b_2$. Then we obtain
|
||||
$$
|
||||
\align
|
||||
\begin{align*}
|
||||
x_{\bar j}&=
|
||||
\solviip(a_1,b_1^2,\solviip(a_2,b_2^2,\widehat{d}_{\bar j},i-1),i-1)\\
|
||||
x_{\bar j+1}&=
|
||||
\solviip(a_1,b_1^2,\solviip(a_2,b_2^2,\widehat{d}_{\bar j+1},i-1),i-1)
|
||||
\endalign
|
||||
$$
|
||||
\end{align*}
|
||||
|
||||
Now we need to eliminate guys below $F_j$. Since $\Vert F^2_j\Vert <
|
||||
\Vert F_j\Vert$, we precalculate
|
||||
$$
|
||||
\align
|
||||
|
||||
\begin{align*}
|
||||
y_2&=(\alpha^2+\beta^2)(\gamma^2+\delta^2)
|
||||
\left(I_2\otimes\imF^2\otimes K^2\right)x_j\\
|
||||
y_1&=2\alpha(\gamma^2+\delta^2)\left(I_2\otimes\imF\otimes
|
||||
|
@ -360,37 +357,36 @@ K\right)x_j\\
|
|||
\left(
|
||||
F_j^2
|
||||
\otimes I_{m^{i-1}n}\right)y_2\right)\\
|
||||
&=\left(\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix
|
||||
&=\left(\begin{pmatrix}\gamma&-\delta_1\cr\delta_2&\gamma\end{pmatrix}
|
||||
\otimes I_{m^{i-1}n}\right)(d_j-x_j)
|
||||
-\left(\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix
|
||||
-\left(\begin{pmatrix}\gamma&\delta_1\cr-\delta_2&\gamma\end{pmatrix}
|
||||
\otimes I_{m^{i-1}n}\right)y_2
|
||||
\endalign
|
||||
$$
|
||||
\end{align*}
|
||||
|
||||
Then we go through all $k=\bar j+2,\ldots, m$. For clearer formulas, let
|
||||
$\bold f_k$ denote pair of $F^T$ elements in $k$-th line below $F_j$,
|
||||
this is $\bold f_k=(f_{\bar jk}\quad f_{\bar j+1k})$. And let $\bold g_k$
|
||||
denote the same for $F^{2T}$, this is $\bold g_k=(g_{\bar jk}\quad
|
||||
$\mathbf f_k$ denote pair of $F^T$ elements in $k$-th line below $F_j$,
|
||||
this is $\mathbf f_k=(f_{\bar jk}\quad f_{\bar j+1k})$. And let $\mathbf g_k$
|
||||
denote the same for $F^{2T}$, this is $\mathbf g_k=(g_{\bar jk}\quad
|
||||
g_{\bar j+1k})$. For each $k$ we put
|
||||
$$
|
||||
\align
|
||||
d_k &= d_k - \left(2\alpha\bold f_k\otimes
|
||||
|
||||
\begin{align*}
|
||||
d_k &= d_k - \left(2\alpha\mathbf f_k\otimes
|
||||
\imF\otimes K +
|
||||
(\alpha^2+\beta^2)\bold g_k\otimes
|
||||
(\alpha^2+\beta^2)\mathbf g_k\otimes
|
||||
\imF^2\otimes K^2\right)x_j\\
|
||||
&= d_k - \frac{1}{\gamma^2+\delta^2}
|
||||
\left(\bold f_k\otimes
|
||||
\left(\mathbf f_k\otimes
|
||||
I_{m^{i-1}n}\right)y_1
|
||||
- \frac{1}{\gamma^2+\delta^2}
|
||||
\left(\bold g_k\otimes
|
||||
\left(\mathbf g_k\otimes
|
||||
I_{m^{i-1}n}\right)y_2
|
||||
\endalign
|
||||
$$
|
||||
\end{align*}
|
||||
|
||||
\endroster
|
||||
\end{enumerate}
|
||||
|
||||
\head Final Notes\endhead
|
||||
\section{Final Notes}
|
||||
|
||||
\subhead Numerical Issues of $A^{-1}B$\endsubhead
|
||||
\subsection{Numerical Issues of $A^{-1}B$}
|
||||
|
||||
We began the solution of the Sylvester equation with multiplication by
|
||||
$A^{-1}$. This can introduce numerical errors, and we need more
|
||||
|
@ -448,7 +444,7 @@ We try to solve $M\vec(X) = T_n(0) = 0$. Since $M$ is
|
|||
skew symmetric, there is real orthonormal matrix $Q$, such that
|
||||
$M=Q\widehat{M}Q^T$, and $\widehat{M}$ is block diagonal matrix
|
||||
consisting of $2\times 2$ blocks of the form
|
||||
$$\left(\matrix 0&\alpha_i\cr-\alpha_i&0\endmatrix\right),$$
|
||||
$$\left(\begin{matrix} 0&\alpha_i\cr-\alpha_i&0\end{matrix}\right),$$
|
||||
and of additional zero, if $n^2$ is odd.
|
||||
|
||||
Now we solve equation $\widehat{M}y=0$, where $y=Q^T\vec(X)$. Now
|
||||
|
@ -462,7 +458,7 @@ structural zeros, a solution is obtained by picking arbitrary numbers
|
|||
for the same positions in $y$, and put $\vec(X)=Qy$.
|
||||
|
||||
The following questions need to be answered:
|
||||
\roster
|
||||
\begin{enumerate}
|
||||
\item How to recognize the structural rows?
|
||||
\item Is $A^{-1}$ generated by a $y$, which has non-zero elements only
|
||||
on structural rows? Note that $A$ can have repetitive eigenvalues. The
|
||||
|
@ -471,9 +467,9 @@ $y$ there is exactly one structural row.
|
|||
\item And very difficult one: How to pick $y$ so that $X$ would be
|
||||
regular, or even close to orthonormal (pure orthonormality
|
||||
overdeterminates $y$)?
|
||||
\endroster
|
||||
\end{enumerate}
|
||||
|
||||
\subhead Making Zeros in $F$\endsubhead
|
||||
\subsection{Making Zeros in $F$}
|
||||
|
||||
It is clear that the numerical complexity of the proposed algorithm
|
||||
strongly depends on a number of non-zero elements in the Schur factor
|
||||
|
@ -482,10 +478,10 @@ substantially less zeros than $F$, then the computation would be
|
|||
substantially faster. However, it seems that we have to pay price for
|
||||
any additional zero in terms of less numerical stability of $PFP^{-1}$
|
||||
multiplication. Consider $P$, and $F$ in form
|
||||
$$P=\pmatrix I &X\cr 0&I\endpmatrix,
|
||||
\qquad F=\pmatrix A&C\cr 0&B\endpmatrix$$
|
||||
$$P=\begin{pmatrix} I &X\cr 0&I\end{pmatrix},
|
||||
\qquad F=\begin{pmatrix} A&C\cr 0&B\end{pmatrix}$$
|
||||
we obtain
|
||||
$$PFP^{-1}=\pmatrix A& C + XB - AX\cr 0&B \endpmatrix$$
|
||||
$$PFP^{-1}=\begin{pmatrix} A& C + XB - AX\cr 0&B \end{pmatrix}$$
|
||||
|
||||
Thus, we need to solve $C = AX - XB$. Its clear that numerical
|
||||
stability of operator $Y\mapsto PYP^{-1}$ and its inverse $Y\mapsto
|
||||
|
@ -503,7 +499,7 @@ partitioning is not possible without breaking some user given limit
|
|||
for numerical errors. We have to keep in mind that the numerical
|
||||
errors are accumulated in product of all $P$'s of every step.
|
||||
|
||||
\subhead Exploiting constant rows in $F$\endsubhead
|
||||
\subsection{Exploiting constant rows in $F$}
|
||||
|
||||
If some of $F$'s rows consists of the same numbers, or a number of
|
||||
distict values within a row is small, then this structure can be
|
||||
|
@ -529,13 +525,12 @@ in order to minimize $\Vert X\Vert$ if $A$, and $B$ are given. Now, in
|
|||
the next step we need to introduce zeros (or constant rows) to matrix
|
||||
$A$, so we seek for regular matrix $P$, doing the
|
||||
job. If found, the product looks like:
|
||||
$$\pmatrix P&0\cr 0&I\endpmatrix\pmatrix A&R\cr 0&B\endpmatrix
|
||||
\pmatrix P^{-1}&0\cr 0&I\endpmatrix=
|
||||
\pmatrix PAP^{-1}&PR\cr 0&B\endpmatrix$$
|
||||
$$\begin{pmatrix} P&0\cr 0&I\end{pmatrix}\begin{pmatrix} A&R\cr 0&B\end{pmatrix}
|
||||
\begin{pmatrix} P^{-1}&0\cr 0&I\end{pmatrix}=
|
||||
\begin{pmatrix} PAP^{-1}&PR\cr 0&B\end{pmatrix}$$
|
||||
Now note, that matrix $PR$ has also constant rows. Thus,
|
||||
preconditioning of the matrix in upper left corner doesn't affect the
|
||||
property. However, a preconditioning of the matrix in lower right
|
||||
corner breaks the property, since we would obtain $RP^{-1}$.
|
||||
|
||||
|
||||
\enddocument
|
||||
\end{document}
|
|
@ -0,0 +1,246 @@
|
|||
\documentclass[11pt,a4paper]{article}
|
||||
|
||||
\usepackage{amssymb}
|
||||
\usepackage{amsmath}
|
||||
|
||||
\usepackage{fullpage}
|
||||
|
||||
\begin{document}
|
||||
\author{Ondra Kamenik}
|
||||
\title{Multidimensional Tensor Library \\ for perturbation methods applied to DSGE
|
||||
models}
|
||||
|
||||
\date{2004}
|
||||
\maketitle
|
||||
|
||||
\section{Introduction}
|
||||
|
||||
The design of the library was driven by the needs of perturbation
|
||||
methods for solving Stochastic Dynamic General Equilibrium models. The
|
||||
aim of the library is not to provide an exhaustive interface to
|
||||
multidimensional linear algebra. The tensor library's main purposes
|
||||
include:
|
||||
\begin{itemize}
|
||||
|
||||
\item Define types for tensors, for a multidimensional index of a
|
||||
tensor, and types for folded and unfolded tensors. The tensors defined
|
||||
here have only one multidimensional index and one reserved
|
||||
one-dimensional index. The tensors should allow modelling of higher
|
||||
order derivatives with respect to a few vectors with different sizes
|
||||
(for example $\left[g_{y^2u^3}\right]$). The tensors should allow
|
||||
folded and unfolded storage modes and conversion between them. A
|
||||
folded tensor stores symmetric elements only once, while an unfolded
|
||||
stores data as a whole multidimensional cube.
|
||||
|
||||
\item Define both sparse and dense tensors. We need only one particular
|
||||
type of sparse tensor. This in contrast to dense tensors, where we
|
||||
need much wider family of types.
|
||||
|
||||
\item Implement the Faa Di Bruno multidimensional formula. So, the main
|
||||
purpose of the library is to implement the following step of Faa Di Bruno:
|
||||
$$\left[B_{s^k}\right]_{\alpha_1\ldots\alpha_k}
|
||||
=\left[h_{y^l}\right]_{\gamma_1\ldots\gamma_l}
|
||||
\left(\sum_{c\in M_{l,k}}
|
||||
\prod_{m=1}^l\left[g_{s^{\vert c_m\vert}}\right]^{\gamma_m}_{c_m(\alpha)}\right)$$
|
||||
where $s$ can be a compound vector of variables, where $h_{y^l}$ and $g_{s^i}$
|
||||
are tensors, $M_{l,k}$ is a set of
|
||||
all equivalences of $k$ element set having $l$ classes, $c_m$ is
|
||||
$m$-th class of equivalence $c$, $\vert c_m\vert$ is its
|
||||
cardinality, and $c_m(\alpha)$ is a tuple of
|
||||
picked indices from $\alpha$ by class $c_m$.
|
||||
|
||||
Note that the sparse tensors play a role of $h$ in the Faa Di Bruno, not
|
||||
of $B$ nor $g$.
|
||||
|
||||
\end{itemize}
|
||||
|
||||
\section{Classes}
|
||||
|
||||
The following list is a road-map to various classes in the library.
|
||||
|
||||
\begin{description}
|
||||
|
||||
\item[Tensor]
|
||||
Virtual base class for all dense tensors, defines \emph{index} as the
|
||||
multidimensonal iterator
|
||||
\item[FTensor]
|
||||
Virtual base class for all folded tensors
|
||||
\item[UTensor]
|
||||
Virtual base class for all unfolded tensors
|
||||
\item[FFSTensor]
|
||||
Class representing folded full symmetry dense tensor,
|
||||
for instance $\left[g_{y^3}\right]$
|
||||
\item[FGSTensor]
|
||||
Class representing folded general symmetry dense tensor,
|
||||
for instance $\left[g_{y^2u^3}\right]$
|
||||
\item[UFSTensor]
|
||||
Class representing unfolded full symmetry dense tensor,
|
||||
for instance $\left[g_{y^3}\right]$
|
||||
\item[UGSTensor]
|
||||
Class representing unfolded general symmetry dense tensor,
|
||||
for instance $\left[g_{y^2u^3}\right]$
|
||||
\item[URTensor]
|
||||
Class representing unfolded/folded full symmetry, row-oriented,
|
||||
dense tensor. Row-oriented tensors are used in the Faa Di Bruno
|
||||
above as some part (few or one column) of a product of $g$'s. Their
|
||||
fold/unfold conversions are special in such a way, that they must
|
||||
yield equivalent results if multiplied with folded/unfolded
|
||||
column-oriented counterparts.
|
||||
\item[URSingleTensor]
|
||||
Class representing unfolded/folded full symmetry, row-oriented,
|
||||
single column, dense tensor. Besides use in the Faa Di Bruno, the
|
||||
single column row oriented tensor models also higher moments of normal
|
||||
distribution.
|
||||
\item[UPSTensor]
|
||||
Class representing unfolded, column-oriented tensor whose symmetry
|
||||
is not that of the $\left[B_{y^2u^3}\right]$ but rather of something
|
||||
as $\left[B_{yuuyu}\right]$. This tensor evolves during the product
|
||||
operation for unfolded tensors and its basic operation is to add
|
||||
itself to a tensor with nicer symmetry, here $\left[B_{y^2u^3}\right]$.
|
||||
\item[FPSTensor]
|
||||
Class representing partially folded, column-oriented tensor whose
|
||||
symmetry is not that of the $\left[B_{y^3u^4}\right]$ but rather
|
||||
something as $\left[B_{yu\vert y^3u\vert u^4}\right]$, where the
|
||||
portions of symmetries represent folded dimensions which are combined
|
||||
in unfolded manner. This tensor evolves during the Faa Di Bruno
|
||||
for folded tensors and its basic operation is to add itself to a
|
||||
tensor with nicer symmetry, here folded $\left[B_{y^3u^4}\right]$.
|
||||
\item[USubTensor]
|
||||
Class representing unfolded full symmetry, row-oriented tensor which
|
||||
contains a few columns of huge product
|
||||
$\prod_{m=1}^l\left[g_{s^{\vert c_m\vert}}\right]^{\gamma_m}_{c_m(\alpha)}$. This is
|
||||
needed during the Faa Di Bruno for folded matrices.
|
||||
\item[IrregTensor]
|
||||
Class representing a product of columns of derivatives
|
||||
$\left[z_{y^ku^l}\right]$, where $z=[y^T,v^T,w^T]^T$. Since the first
|
||||
part of $z$ is $y$, the derivatives contain many zeros, which are not
|
||||
stored, hence the tensor's irregularity. The tensor is used when
|
||||
calculating one step of Faa Di Bruno formula, i.e.
|
||||
$\left[h_{y^l}\right]_{\gamma_1\ldots\gamma_l}
|
||||
\left(\sum_{c\in M_{l,k}}
|
||||
\prod_{m=1}^l\left[g_{s^{\vert c_m\vert}}\right]^{\gamma_m}_{c_m(\alpha)}\right)$.
|
||||
\item[FSSparseTensor]
|
||||
Class representing full symmetry, column-oriented, sparse tensor. It
|
||||
is able to store elements keyed by the multidimensional index, and
|
||||
multiply itself with one column of row-oriented tensor.
|
||||
\item[FGSContainer]
|
||||
Container of \texttt{FGSTensor}s. It implements the Faa Di Bruno with
|
||||
unfolded or folded tensor $h$ yielding folded $B$. The methods are
|
||||
\texttt{FGSContainer::multAndAdd}.
|
||||
\item[UGSContainer]
|
||||
Container of \texttt{UGSTensor}s. It implements the Faa Di Bruno with
|
||||
unfolded tensor $h$ yielding unfolded $B$. The method is
|
||||
\texttt{UGSContainer::multAndAdd}.
|
||||
\item[StackContainerInterface]
|
||||
Virtual pure interface describing all logic
|
||||
of stacked containers for which we will do the Faa Di Bruno operation.
|
||||
\item[UnfoldedStackContainer]
|
||||
Implements the Faa Di Bruno operation for stack of
|
||||
containers of unfolded tensors.
|
||||
\item[FoldedStackContainer]
|
||||
Implements the Faa Di Bruno for stack of
|
||||
containers of folded tensors.
|
||||
\item[ZContainer]
|
||||
The class implements the interface \texttt{StackContainerInterface} according
|
||||
to $z$ appearing in context of DSGE models. By a simple inheritance,
|
||||
we obtain \texttt{UnfoldedZContainer} and also \texttt{FoldedZContainer}.
|
||||
\item[GContainer]
|
||||
The class implements the interface \texttt{StackContainerInterface} according
|
||||
to $G$ appearing in context of DSGE models. By a simple inheritance,
|
||||
we obtain \texttt{UnfoldedGContainer} and also \texttt{FoldedGContainer}.
|
||||
\item[Equivalence]
|
||||
The class represents an equivalence on $n$-element set. Useful in the
|
||||
Faa Di Bruno.
|
||||
\item[EquivalenceSet]
|
||||
The class representing all equivalences on $n$-element set. Useful in the
|
||||
Faa Di Bruno.
|
||||
\item[Symmetry]
|
||||
The class defines a symmetry of general symmetry tensor. This is it
|
||||
defines a basic shape of the tensor. For $\left[B_{y^2u^3}\right]$,
|
||||
the symmetry is $y^2u^3$.
|
||||
\item[Permutation]
|
||||
The class represents a permutation of $n$ indices. Useful in the
|
||||
Faa Di Bruno.
|
||||
\item[IntSequence]
|
||||
The class represents a sequence of integers. Useful everywhere.
|
||||
\item[TwoDMatrix and ConstTwoDMatrix]
|
||||
These classes provide an interface to a code handling two-dimensional
|
||||
matrices. The code resides in Sylvester module, in directory {\tt
|
||||
sylv/cc}. There is
|
||||
no similar interface to \texttt{Vector} and \texttt{ConstVector} classes from the
|
||||
Sylvester module and they are used directly.
|
||||
\item[KronProdAll]
|
||||
The class represents a Kronecker product of a sequence of arbitrary
|
||||
matrices and is able to multiply a matrix from the right without
|
||||
storing the Kronecker product in memory.
|
||||
\item[KronProdAllOptim]
|
||||
The same as \texttt{KronProdAll} but it optimizes the order of matrices in
|
||||
the product to minimize the used memory during the Faa Di Bruno
|
||||
operation. Note that it is close to optimal flops.
|
||||
\item[FTensorPolynomial and UTensorPolynomial]
|
||||
Abstractions representing a polynomial whose coefficients are
|
||||
folded/unfolded tensors and variable is a column vector. The classes
|
||||
provide methods for traditional and horner-like polynomial
|
||||
evaluation. This is useful in simulation code.
|
||||
\item[FNormalMoments and UNormalMoments]
|
||||
These are containers for folded/unfolded single column tensors for
|
||||
higher moments of normal distribution. The code contains an algorithm
|
||||
for generating the moments for arbitrary covariance matrix.
|
||||
\item[TLStatic]
|
||||
The class encapsulates all static information needed for the
|
||||
library. It includes precalculated equivalence sets.
|
||||
\item[TLException]
|
||||
Simple class thrown as an exception.
|
||||
\end{description}
|
||||
|
||||
\section{Multi-threading}
|
||||
|
||||
The tensor library is multi-threaded. The basic property of the
|
||||
thread implementation in the library is that we do not allow running
|
||||
more concurrent threads than the preset limit. This prevents threads
|
||||
from competing for memory in such a way that the OS constantly switches
|
||||
among threads with frequent I/O for swaps. This may occur since one
|
||||
thread might need much own memory. The threading support allows for
|
||||
detached threads, the synchronization points during the Faa Di Bruno
|
||||
operation are relatively short, so the resulting load is close to the
|
||||
preset maximum number parallel threads.
|
||||
|
||||
\section{Tests}
|
||||
|
||||
A few words to the library's test suite. The suite resides in
|
||||
directory {\tt tl/testing}. There is a file {\tt tests.cc} which
|
||||
contains all tests and {\tt main()} function. Also there are files
|
||||
{\tt factory.hh} and {\tt factory.cc} implementing random generation
|
||||
of various objects. The important property of these random objects is
|
||||
that they are the same for all object's invocations. This is very
|
||||
important in testing and debugging. Further, one can find files {\tt
|
||||
monoms.hh} and {\tt monoms.cc}. See below for their explanation.
|
||||
|
||||
There are a few types of tests:
|
||||
\begin{itemize}
|
||||
\item We test for tensor indices. We go through various tensors with
|
||||
various symmetries, convert indices from folded to unfolded and
|
||||
vice-versa. We test whether their coordinates are as expected.
|
||||
\item We test the Faa Di Bruno by comparison of the results of
|
||||
\texttt{FGSContainer::multAndAdd} against the results of \texttt{UGSContainer::multAndAdd}. The two
|
||||
implementations are pretty different, so this is a good test.
|
||||
\item We use a code in {\tt monoms.hh} and {\tt monoms.cc} to generate a
|
||||
random vector function $f(x(y,u))$ along with derivatives of
|
||||
$\left[f_x\right]$, $\left[x_{y^ku^l}\right]$, and
|
||||
$\left[f_{y^ku^l}\right]$. Then we calculate the resulting derivatives
|
||||
$\left[f_{y^ku^l}\right]$ using \texttt{multAndAdd} method of \texttt{UGSContainer}
|
||||
or \texttt{FGSContainer} and compare the derivatives provided by {\tt
|
||||
monoms}. The functions generated in {\tt monoms} are monomials with
|
||||
integer exponents, so the implementation of {\tt monoms} is quite
|
||||
easy.
|
||||
\item We do a similar thing for sparse tensors. In this case the {\tt monoms}
|
||||
generate a function $f(y,v(y,u),w(y,u))$, provide all the derivatives
|
||||
and the result $\left[f_{y^ku^l}\right]$. Then we calculate the
|
||||
derivatives with \texttt{multAndAdd} of \texttt{ZContainer} and compare.
|
||||
\item We test the polynomial evaluation by evaluating a folded and
|
||||
unfolded polynomial in traditional and Horner-like fashion. This gives
|
||||
four methods in total. The four results are compared.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
\end{document}
|
|
@ -1,54 +0,0 @@
|
|||
RINTERNALS=/usr/share/R/include/
|
||||
|
||||
sylvcppsource := $(wildcard ../../sylv/cc/*.cpp)
|
||||
sylvhsource := $(wildcard ../../sylv/cc/*.h)
|
||||
sylvobjects := $(patsubst %.cpp, %.o, $(sylvcppsource))
|
||||
|
||||
tlcwebsource := $(wildcard ../../tl/cc/*.cweb)
|
||||
tlcppsource := $(patsubst %.cweb,%.cpp,$(tlcwebsource))
|
||||
tlhwebsource := $(wildcard ../../tl/cc/*.hweb)
|
||||
tlhsource := $(patsubst %.hweb,%.h,$(tlhwebsource))
|
||||
tlobjects := $(patsubst %.cweb,%.o,$(tlcwebsource))
|
||||
|
||||
kordcwebsource := $(wildcard ../../kord/*.cweb)
|
||||
kordcppsource := $(patsubst %.cweb,%.cpp,$(kordcwebsource))
|
||||
kordhwebsource := $(wildcard ../../kord/*.hweb)
|
||||
kordhsource := $(patsubst %.hweb,%.h,$(kordhwebsource))
|
||||
kordobjects := $(patsubst %.cweb,%.o,$(kordcwebsource))
|
||||
|
||||
integcwebsource := $(wildcard ../../integ/cc/*.cweb)
|
||||
integcppsource := $(patsubst %.cweb,%.cpp,$(integcwebsource))
|
||||
integhwebsource := $(wildcard ../../integ/cc/*.hweb)
|
||||
integhsource := $(patsubst %.hweb,%.h,$(integhwebsource))
|
||||
integobjects := $(patsubst %.cweb,%.o,$(integcwebsource))
|
||||
|
||||
parserhsource := $(wildcard ../../parser/cc/*.h)
|
||||
parsercppsource := $(wildcard ../parser/cc/*.cpp)
|
||||
|
||||
utilshsource := $(wildcard ../../utils/cc/*.h)
|
||||
utilscppsource := $(wildcard ../utils/cc/*.cpp)
|
||||
|
||||
srccpp := dynare3.cpp dynare_model.cpp planner_builder.cpp dynare_atoms.cpp dynare_params.cpp nlsolve.cpp
|
||||
objects := $(patsubst %.cpp,../../src/%.o,$(srccpp)) \
|
||||
$(patsubst %.y,%_ll.o,$(wildcard ../../src/*.y)) \
|
||||
$(patsubst %.lex,%_tab.o,$(wildcard ../../src/*.lex))
|
||||
|
||||
PKG_CPPFLAGS= -I../../tl/cc -I../../sylv/cc -I../../kord -I../../src -I../.. -I$(RINTERNALS)
|
||||
PKG_LIBS= ${LAPACK_LIBS} ${BLAS_LIBS} $(objects) $(kordobjects) $(integobjects) $(tlobjects) ../../parser/cc/parser.a ../../utils/cc/utils.a $(sylvobjects) -lpthread -llapack -lcblas -lf77blas -latlas -lg2c -lstdc++
|
||||
|
||||
ifneq ($(LD_LIBRARY_PATH),) # use LD_LIBRARY_PATH from environment
|
||||
PKG_LIBS := -Wl,--library-path $(LD_LIBRARY_PATH) $(PKG_LIBS)
|
||||
endif
|
||||
|
||||
dynareR.so: dynareR.o
|
||||
g++ -shared -o dynareR.so dynareR.o -L/usr/lib/R/lib -lR $(PKG_LIBS)
|
||||
|
||||
dynareR.o: dynareR.cpp
|
||||
g++ -I/usr/share/R/include -I/usr/share/R/include $(PKG_CPPFLAGS) \
|
||||
-fpic -g -O2 -c dynareR.cpp -o dynareR.o -DDEBUG
|
||||
|
||||
test: test.cpp dynareR.cpp
|
||||
g++ -O0 -g -o test test.cpp -DDEBUG $(PKG_LIBS) $(PKG_CPPFLAGS)
|
||||
|
||||
test-debug:
|
||||
valgrind --leak-check=yes ./test
|
|
@ -1,17 +0,0 @@
|
|||
COMPILING
|
||||
|
||||
The makefile for this interface is still preliminary, I will write a decent
|
||||
one when I have the time. It needs all the compiled files from dynare++,
|
||||
but doesn't know how to make them. So first you need to run make in the
|
||||
src/ directory, then run make in extern/R.
|
||||
|
||||
You need Rinternals.h to make this file. If you are not using prepackaged R
|
||||
on Unix/Linux, you need to modify the variable RINCLUDE in the Makefile
|
||||
accordingly.
|
||||
|
||||
To compile dynare++, read doc/compiling-notes.txt.
|
||||
|
||||
INSTALLATION
|
||||
|
||||
Copy the dynareR.r and dynareR.so files to your working directory so that R
|
||||
can find them.
|
|
@ -1,249 +0,0 @@
|
|||
// $Id: dynareR.cpp 862 2006-08-04 17:34:56Z tamas $
|
||||
|
||||
// Copyright 2006, Tamas K Papp
|
||||
|
||||
#include "dynare3.h" // Dynare class
|
||||
#include "approximation.h" // Approximation class
|
||||
|
||||
// exceptions
|
||||
#include "dynare_exception.h"
|
||||
#include "parser/cc/parser_exception.h"
|
||||
#include "utils/cc/exception.h"
|
||||
#include "SylvException.h"
|
||||
#include "tl_exception.h"
|
||||
#include "kord_exception.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <R_ext/Memory.h>
|
||||
|
||||
/** This file containt the C glue functions for an R interface to
|
||||
* Dynare++. Although written in standard C (except for the use of
|
||||
* R_alloc), the indexing, calling and memory management conventions
|
||||
* of the functions in this file were tailored for R.
|
||||
*
|
||||
* It is not recommended that you use this interface for anything else
|
||||
* but R.
|
||||
*/
|
||||
|
||||
/** Error codes: these error codes correspond to possible
|
||||
* exceptions. */
|
||||
#define DYNARER_SYLVEXCEPTION 1
|
||||
#define DYNARER_DYNAREEXCEPTION 2
|
||||
#define DYNARER_OGUEXCEPTION 3
|
||||
#define DYNARER_TLEXCEPTION 4
|
||||
#define DYNARER_KORDEXCEPTION 5
|
||||
#define DYNARER_NAMESMATCHINGERROR 6
|
||||
|
||||
/** Copies the message into a buffer. The buffer is allocated and
|
||||
* managed by R, ie it will be garbage collected after the .C call
|
||||
* returns and the contents are duplicated.
|
||||
*/
|
||||
char *passmessage(const char *errormessage) {
|
||||
long l = strlen(errormessage);
|
||||
char *em = R_alloc(l, 1);
|
||||
return strcpy(em, errormessage);
|
||||
}
|
||||
|
||||
/** This function puts the mapping between the newtotal items after
|
||||
* nl[offset] and the items in orig into the buffer perm, which has to
|
||||
* be at least as long as newtotal. The function uses R indexing,
|
||||
* that is to say, the first index is 1.
|
||||
*/
|
||||
int matchnames(const char **orig, int origtotal,
|
||||
const NameList &nl, int offset, int newtotal,
|
||||
int *perm) {
|
||||
#ifdef DEBUG
|
||||
printf("matching names (R indexing):\n");
|
||||
#endif
|
||||
for (int i=0; i < newtotal; i++) {
|
||||
int j;
|
||||
for (j=0; j < origtotal; j++)
|
||||
if (strcmp(nl.getName(offset+i), *(orig+j))==0) {
|
||||
*(perm+i) = j+1;
|
||||
#ifdef DEBUG
|
||||
printf("%d -> %d\n",i+1,j+1);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if (j==origtotal)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** dynareR is the interface function. The user provides:
|
||||
* - a list of endogenous and exogenous variables, a list of
|
||||
* parameters (and the length of each list)
|
||||
* - the model equations (modeleq, pointer to a 0-terminated string)
|
||||
* - the order of expansion (ord)
|
||||
* - journal file name (jnlfile, can be "/dev/null" for no journal)
|
||||
* - values for the parametes (parval)
|
||||
* - variance-covariance matrix (vcov, stacked by columns, R does
|
||||
* this)
|
||||
* - initial values for finding the steady state (initval)
|
||||
* - and the number of steps for the approximation algorithm
|
||||
* (numsteps)
|
||||
*
|
||||
* If successful, the interface will write the results to these
|
||||
* buffers:
|
||||
* - tensorbuffer for the steady state and the flattened tensors
|
||||
* - num_state for the number of endogenous variables that ended up in
|
||||
* the state
|
||||
* - mappings to variable names (ordering_state, ordering_endo,
|
||||
* ordering_exo), indices start from 1
|
||||
* - the deterministic steady state (newinitval)
|
||||
*
|
||||
* If dynare throws an exception, the interface tries to catch it and
|
||||
* return an error code (error), and error message (errormessage), and
|
||||
* if applicable, information on the stability of the model
|
||||
* (kordcode). errormessage is allocated into R's memory, and will be
|
||||
* collected after duplication.
|
||||
*/
|
||||
extern "C" {
|
||||
void dynareR(const char** endo, const int* num_endo,
|
||||
const char** exo, const int* num_exo,
|
||||
const char** par, const int* num_par,
|
||||
const char** equations, const int* ord, const char* jnlfile,
|
||||
const double *parval, const double *vcov,
|
||||
const double *initval,
|
||||
const int *num_steps,
|
||||
double* tensorbuffer,
|
||||
int *num_state, int *ordering_state,
|
||||
int *ordering_endo, int *ordering_exo,
|
||||
double *newinitval,
|
||||
int* error, char **errormessage, int *kordcode) {
|
||||
// construct the model here
|
||||
try {
|
||||
#ifdef DEBUG // will print only first var names etc.
|
||||
printf("eq: %s\nendo: %d %s\nexo: %d %s\npar: %d %s\nord: %d\n",
|
||||
*equations,*num_endo,*endo,*num_exo,*exo,*num_par,*par,*ord);
|
||||
#endif
|
||||
// create journal
|
||||
Journal journal(jnlfile);
|
||||
// create Dynare object
|
||||
Dynare dynare(endo, *num_endo, exo, *num_exo,
|
||||
par, *num_par, *equations, strlen(*equations),
|
||||
*ord, journal);
|
||||
// set Vcov and parameter values
|
||||
copy(parval,parval+(*num_par),dynare.getParams().base());
|
||||
#ifdef DEBUG
|
||||
printf("parameter values (%d):\n",dynare.getParams().length());
|
||||
dynare.getParams().print();
|
||||
#endif
|
||||
copy(vcov,vcov+(*num_exo)*(*num_exo),dynare.getVcov().base());
|
||||
#ifdef DEBUG
|
||||
printf("vcov matrix:\n");
|
||||
dynare.getVcov().print();
|
||||
#endif
|
||||
// set initial values
|
||||
Vector iv(initval,*num_endo);
|
||||
#ifdef DEBUG
|
||||
printf("initial values:\n");
|
||||
iv.print();
|
||||
#endif
|
||||
dynare.setInitOuter(iv);
|
||||
// construct approximation
|
||||
tls.init(dynare.order(),
|
||||
dynare.nstat()+2*dynare.npred()+3*dynare.nboth()+
|
||||
2*dynare.nforw()+dynare.nexog());
|
||||
Approximation approximation(dynare,journal,*num_steps);
|
||||
approximation.walkStochSteady();
|
||||
// write the steady state into the buffer
|
||||
int ny = dynare.ny();
|
||||
const Vector ss(dynare.getSteady());
|
||||
// ss = ConstVector(approximation.getSS(), 0); // FIXME allow
|
||||
// // for nonzero
|
||||
int s = dynare.getStateNames().getNum();
|
||||
int sm = s;
|
||||
tensorbuffer = copy(ss.base(),ss.base()+ny,tensorbuffer);
|
||||
// write the tensors into buffer
|
||||
const UnfoldDecisionRule& udr =
|
||||
approximation.getUnfoldDecisionRule();
|
||||
for (int i=1; i <= *ord; i++) {
|
||||
const UFSTensor* t = udr.get(Symmetry(i));
|
||||
#ifdef DEBUG
|
||||
printf("tensor %d:\n", i);
|
||||
t->print();
|
||||
#endif
|
||||
tensorbuffer = copy(t->base(), t->base()+ny*sm, tensorbuffer);
|
||||
sm *= s;
|
||||
}
|
||||
// save number of endogenous states
|
||||
*num_state = s-(*num_exo);
|
||||
// ordering
|
||||
#ifdef DEBUG
|
||||
printf("all endo names:\n");
|
||||
dynare.getAllEndoNames().print();
|
||||
printf("all state names:\n");
|
||||
dynare.getStateNames().print();
|
||||
#endif
|
||||
if (matchnames(endo, *num_endo, dynare.getAllEndoNames(),
|
||||
0, *num_endo, ordering_endo) ||
|
||||
matchnames(endo, *num_endo, dynare.getStateNames(),
|
||||
0, *num_state, ordering_state) ||
|
||||
matchnames(exo, *num_exo, dynare.getStateNames(),
|
||||
*num_state, *num_exo, ordering_exo)) {
|
||||
*error = DYNARER_NAMESMATCHINGERROR;
|
||||
*errormessage = "There was a problem when matching names. This is weird and should not happen.";
|
||||
return;
|
||||
}
|
||||
// return new init values (first column of SS matrix)
|
||||
ConstVector newinit((const GeneralMatrix&) approximation.getSS(), 0);
|
||||
#ifdef DEBUG
|
||||
printf("new initial values:\n");
|
||||
newinit.print();
|
||||
#endif
|
||||
copy(newinit.base(),newinit.base()+(*num_endo),newinitval);
|
||||
} catch (const SylvException &e) {
|
||||
*error = DYNARER_SYLVEXCEPTION;
|
||||
char errorbuffer[501];
|
||||
e.printMessage(errorbuffer, 500);
|
||||
*errormessage = passmessage(errorbuffer);
|
||||
#ifdef DEBUG
|
||||
printf("Caught Sylv exception: ");
|
||||
e.printMessage();
|
||||
#endif
|
||||
return;
|
||||
} catch (const DynareException &e) {
|
||||
*error = DYNARER_DYNAREEXCEPTION;
|
||||
*errormessage = passmessage(e.message());
|
||||
#ifdef DEBUG
|
||||
printf("Caught Dynare exception: %s\n", e.message());
|
||||
#endif
|
||||
return;
|
||||
} catch (const ogu::Exception &e) {
|
||||
*error = DYNARER_OGUEXCEPTION;
|
||||
*errormessage = passmessage(e.message());
|
||||
#ifdef DEBUG
|
||||
printf("Caught ogu::Exception: ");
|
||||
e.print();
|
||||
#endif
|
||||
return;
|
||||
} catch (const TLException &e) {
|
||||
*error = DYNARER_TLEXCEPTION;
|
||||
*errormessage = passmessage(e.getmessage());
|
||||
#ifdef DEBUG
|
||||
printf("Caugth TL exception: ");
|
||||
e.print();
|
||||
#endif
|
||||
return;
|
||||
} catch (const KordException &e) {
|
||||
*error = DYNARER_KORDEXCEPTION;
|
||||
*errormessage = passmessage(e.getmessage());
|
||||
*kordcode = e.code(); // Kord error code
|
||||
#ifdef DEBUG
|
||||
printf("Caugth Kord exception: ");
|
||||
e.print();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
*error = 0;
|
||||
return;}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
## $Id: dynareR.r 862 2006-08-04 17:34:56Z tamas $
|
||||
|
||||
## Copyright 2006, Tamas K Papp
|
||||
|
||||
dyn.load("dynareR.so") # FIXME: make it platform-independent
|
||||
|
||||
## FIXME hide auxiliary functions in a namespace
|
||||
|
||||
dynareR.indextensor <- function(ord, nume, nums) {
|
||||
nume*((nums^ord-1)/(nums-1))
|
||||
}
|
||||
|
||||
dynareR.extracttensor <- function(tensor, ord, nume, nums) {
|
||||
aperm(array(tensor[dynareR.indextensor(ord,nume,nums)+(1:(nume*nums^ord))],
|
||||
c(nume,rep(nums,ord))),(ord+1):1)
|
||||
}
|
||||
|
||||
dynareR.errormessages <- c("Sylvester exception",
|
||||
"Dynare exception",
|
||||
"OGU exception",
|
||||
"Tensor library exception",
|
||||
"K-order expansion library exception",
|
||||
"Error matching names")
|
||||
|
||||
calldynare <- function(modeleq, endo, exo, parameters, expandorder,
|
||||
parval, vcovmatrix, initval=rep(1,length(endo)),
|
||||
numsteps=0, jnlfile="/dev/null") {
|
||||
## check type of parameters
|
||||
local({
|
||||
is.charvector <- function(cv) { is.character(cv) && is.vector(cv) }
|
||||
stopifnot(is.charvector(modeleq) && is.charvector(endo) &&
|
||||
is.charvector(exo) && is.charvector(parameters) &&
|
||||
is.charvector(jnlfile))
|
||||
})
|
||||
stopifnot(is.numeric(expandorder) && is.vector(expandorder) &&
|
||||
(length(expandorder) == 1) && (expandorder >= 0))
|
||||
stopifnot(length(jnlfile) == 1)
|
||||
local({ # variable names
|
||||
checkvarname <- function(v) {
|
||||
stopifnot(length(grep("[^a-zA-Z].*",v)) == 0) # look for strange chars
|
||||
}
|
||||
checkvarname(endo)
|
||||
checkvarname(exo)
|
||||
checkvarname(parameters)
|
||||
})
|
||||
stopifnot(is.vector(parval) && is.numeric(parval))
|
||||
stopifnot(is.vector(initval) && is.numeric(initval))
|
||||
stopifnot(is.matrix(vcovmatrix) && is.numeric(vcovmatrix))
|
||||
stopifnot(is.numeric(numsteps) && is.vector(numsteps) &&
|
||||
(length(numsteps)==1))
|
||||
## append semicolons to model equations if necessary
|
||||
modeleq <- sapply(modeleq, function(s) {
|
||||
if (length(grep("^.*; *$",s))==1)
|
||||
s
|
||||
else
|
||||
sprintf("%s;",s)
|
||||
})
|
||||
## then concatenate into a single string
|
||||
modeleq <- paste(modeleq, collapse=" ")
|
||||
## call dynareR
|
||||
nume <- length(endo)
|
||||
maxs <- length(endo)+length(exo)
|
||||
dr <- .C("dynareR",
|
||||
endo,as.integer(nume),
|
||||
exo,as.integer(length(exo)),
|
||||
parameters,as.integer(length(parameters)),
|
||||
modeleq,as.integer(expandorder),jnlfile,
|
||||
as.double(parval),as.double(vcovmatrix),
|
||||
as.double(initval),
|
||||
as.integer(numsteps),
|
||||
tensorbuffer=double(dynareR.indextensor(expandorder+1,nume,maxs)),
|
||||
numstate=integer(1), orderstate=integer(maxs),
|
||||
orderendo=integer(nume),
|
||||
orderexo=integer(length(exo)),
|
||||
newinitval=double(nume),
|
||||
error=integer(1),
|
||||
errormessage=character(1),
|
||||
kordcode=integer(1))
|
||||
## check for errors
|
||||
kordcode <- 0
|
||||
if (dr$error == 0) {
|
||||
if (dr$error == 5) {
|
||||
list(kordcode=dr$kordcode - 251) # magic dynare++ constant
|
||||
} else {
|
||||
## return result
|
||||
with(dr, {
|
||||
nums <- numstate+length(exo)
|
||||
list(ss=dynareR.extracttensor(dr$tensorbuffer,0,nume,nums), # ss
|
||||
rule=sapply(1:expandorder,function (o) { # decision rule
|
||||
dynareR.extracttensor(dr$tensorbuffer,o,nume,nums)
|
||||
}),
|
||||
orderstate=orderstate[1:numstate], # state ordering
|
||||
orderendo=orderendo, # endog. ordering
|
||||
orderexo=orderexo, # exog. ordering
|
||||
newinitval=newinitval, # new init values
|
||||
kordcode=0)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
stop(sprintf("%s (\"%s\")",dynareR.errormessages[dr$error],
|
||||
dr$errormessage))
|
||||
}
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
%% $Id: dynareR.tex 863 2006-08-04 17:35:21Z tamas $
|
||||
%% Copyright Tamas K Papp, 2006
|
||||
%% should compile with any reasonable TeX distribution, I am using tetex
|
||||
\documentclass[12pt,a4paper]{article}
|
||||
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amsfonts}
|
||||
%\usepackage[letterpaper,vmargin=1.7in]{geometry}
|
||||
%\usepackage[letterpaper,left=2cm,right=8cm,bottom=3cm,top=3cm,marginparwidth=4cm]{geometry}
|
||||
%\usepackage{natbib}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{url}
|
||||
\usepackage{natbib}
|
||||
\usepackage{color}
|
||||
\usepackage{paralist} % compactitem
|
||||
\DeclareMathOperator{\Var}{Var}
|
||||
\DeclareMathOperator{\Cov}{Cov}
|
||||
\DeclareMathOperator{\argmin}{argmin}
|
||||
\DeclareMathOperator{\argmax}{argmax}
|
||||
\DeclareMathSymbol{\ueps}{\mathord}{letters}{"0F} % ugly epsilon
|
||||
\renewcommand{\epsilon}{\varepsilon}
|
||||
\newcommand{\aseq}{\overset{as}=} % almost surely equals
|
||||
|
||||
\usepackage{fancyhdr}
|
||||
\pagestyle{fancy}
|
||||
\lhead{Tam\'as K Papp} \chead{} \rhead{DynareR}
|
||||
\cfoot{\thepage}
|
||||
|
||||
\renewcommand\floatpagefraction{.9}
|
||||
\renewcommand\topfraction{.9}
|
||||
\renewcommand\bottomfraction{.9}
|
||||
\renewcommand\textfraction{.1}
|
||||
|
||||
\usepackage{listings}
|
||||
\lstset{
|
||||
language=R,
|
||||
extendedchars=true,
|
||||
basicstyle=\footnotesize,
|
||||
stringstyle=\ttfamily,
|
||||
commentstyle=\slshape,
|
||||
% numbers=left,
|
||||
% stepnumber=5,
|
||||
% numbersep=6pt,
|
||||
% numberstyle=\footnotesize,
|
||||
breaklines=true,
|
||||
frame=single,
|
||||
columns=fullflexible,
|
||||
}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\title{DynareR}
|
||||
\author{Tam\'as K Papp (\url{tpapp@princeton.edu})}
|
||||
\date{\today}
|
||||
\maketitle
|
||||
|
||||
DynareR is an R interface for Ondra Kamen\'ik's Dynare++ program. The
|
||||
interface is still under development, and the functions might change.
|
||||
However, I thought that some documentation would help to get users
|
||||
started.
|
||||
|
||||
The purpose of DynareR is to return the transition rule (the
|
||||
steady state and a list of tensors) for a given model. DynareR
|
||||
does not simulate, and currently does no checking of the
|
||||
approximation. Primarily, the interface is to be intended to be used
|
||||
in Bayesian estimation of DSGE models (via MCMC).
|
||||
|
||||
Before you read on, make sure that
|
||||
\begin{compactitem}
|
||||
\item you understand what Dynare++ is and how it works,
|
||||
\item you have compiled Dynare++ and DynareR (see \verb!README! in
|
||||
\verb!extern/R!), and placed \verb!dynareR.so! and
|
||||
\verb!dynareR.r! in your load path for R.
|
||||
\end{compactitem}
|
||||
|
||||
The function that performs all the work is called
|
||||
\lstinline{calldynare}. Its is defined like this:
|
||||
\begin{lstlisting}
|
||||
calldynare <- function(modeleq, endo, exo, parameters, expandorder,
|
||||
parval, vcovmatrix, initval=rep(1,length(endo)),
|
||||
numsteps=0, jnlfile="/dev/null") {
|
||||
...
|
||||
}
|
||||
\end{lstlisting}
|
||||
\lstinline{modeleq} is a character vector for the model equations, and
|
||||
it may have a length longer than one. First, \lstinline{calldynare}
|
||||
checks if each string in the vector has a terminating semicolon (may
|
||||
be followed by whitespace), if it doesn't, then it appends one. Then
|
||||
it concatenates all equations into a single string. Thus, the
|
||||
following versions of \lstinline{modeleq} give equivalent results:
|
||||
\begin{lstlisting}
|
||||
modeleq1 <- c("(c/c(1))^gamma*beta*(alpha*exp(a(1))*k^(alpha-1)+1-delta)=1",
|
||||
"a=rho*a(-1)+eps",
|
||||
"k+c=exp(a)*k(-1)^alpha+(1-delta)*k(-1)")
|
||||
modeleq2 <- c("(c/c(1))^gamma*beta*(alpha*exp(a(1))*k^(alpha-1)+1-delta)=1;",
|
||||
"a=rho*a(-1)+eps ; ",
|
||||
"k+c=exp(a)*k(-1)^alpha+(1-delta)*k(-1) \t;\t ")
|
||||
modeleq3 <- paste(modeleq1, collapse=" ")
|
||||
\end{lstlisting}
|
||||
The next three arguments name the endo- and exogenous variables and
|
||||
the parameters. The names should be character vectors, for example,
|
||||
\begin{lstlisting}
|
||||
parameters <- c("beta","gamma","rho","alpha","delta")
|
||||
varendo <- c("k","c","a")
|
||||
varexo <- "eps"
|
||||
\end{lstlisting}
|
||||
\lstinline{calldynare} also needs the order of the approximation
|
||||
\lstinline{expandorder} (a nonnegative integer), the parameter values
|
||||
\lstinline{parval} (should be the same length as
|
||||
\lstinline{parameters}), a variance-covariance matrix \lstinline{vcov}
|
||||
(dimensions should match the length of \lstinline{exo}) and initial
|
||||
values for finding the deterministic steady state
|
||||
(\lstinline{initval}). If you don't provide initial values,
|
||||
\lstinline{calldynare} will use a sequence of $1$s, on the assumption
|
||||
that most variables in economics are positive --- you should always
|
||||
try to provide a reasonable initial guess for the nonlinear solver if
|
||||
possible (if you are doing MCMC, chances are that you only have to do
|
||||
it once, see \lstinline{newinitval} below).
|
||||
|
||||
You can also provide the number of steps for calculating the
|
||||
stochastic steady state (\lstinline{numsteps}, the default is zero,
|
||||
see the dynare++ tutorial for more information) and the name of the
|
||||
journal file \lstinline{jnlfile}. If you don't provide a journal
|
||||
file, the default is \verb!/dev/null!.
|
||||
|
||||
Below, you see an example of using dynareR.
|
||||
\lstinputlisting{test.r}
|
||||
|
||||
\lstinline{calldynare} returns the results in a list, variables below
|
||||
refer to elements of this list. First, you should always check
|
||||
\lstinline{kordcode}, which tells whether dynare++ could calculate an
|
||||
approximation. It can have the following values:
|
||||
\begin{description}
|
||||
\item[0] the calculation was successful
|
||||
\item[1] the system is not stable (Blanchard-Kahn)
|
||||
\item[2] failed to calculate fixed point (infinite values)
|
||||
\item[3] failed to calculate fixed point (NaN values)
|
||||
\end{description}
|
||||
If \lstinline{kordcode} is nonzero, then the list has only this
|
||||
element.
|
||||
|
||||
If \lstinline{kordcode} equals zero, then the list has the following
|
||||
elements:
|
||||
\begin{description}
|
||||
\item[ss] the steady state (ordered by \lstinline{orderendo}), which
|
||||
is a vector
|
||||
\item[rule] the transition rule (ordered by \lstinline{orderendo},
|
||||
\lstinline{orderstate} and \lstinline{orderexo}), a list of arrays
|
||||
\item[newinitval] the deterministic steady state, you can use this to
|
||||
initialize the nonlinear solver for a nearby point in the parameter
|
||||
space (ordered by \lstinline{orderendo})
|
||||
\item[orderstate] the index of endogenous variables that ended up in
|
||||
the state
|
||||
\item[orderendo] the ordering of endogenous variables
|
||||
\item[orderexo] the ordering of exogenous variables
|
||||
\item[kordcode] discussed above
|
||||
\end{description}
|
||||
|
||||
An example will illustrate the ordering. To continue the example above,
|
||||
\begin{lstlisting}
|
||||
> dd$orderstate
|
||||
[1] 1 3
|
||||
> dd$orderendo
|
||||
[1] 1 3 2
|
||||
> dd$orderexo
|
||||
[1] 1
|
||||
> dd$rule[[1]]
|
||||
[,1] [,2] [,3]
|
||||
[1,] 0.9669374 0.0 0.02071077
|
||||
[2,] 2.4230073 0.9 0.45309125
|
||||
[3,] 2.6922303 1.0 0.50343473
|
||||
\end{lstlisting}
|
||||
Recall that the original ordering of endogenous variables was
|
||||
\lstinline{k, c, a}. The vectors and matrices of the result are
|
||||
ordered as \lstinline{varendo[dd$orderendo]}, that is, as
|
||||
\lstinline{k, a, c}. This is the ordering for the steady state and
|
||||
the first dimension of the tensors in \lstinline{rule}. The other
|
||||
dimensions are ordered as
|
||||
\lstinline{c(varendo[dd$orderstate],varexo[dd$orderexo])}, that is to
|
||||
say, as \lstinline{k, a, eps}. Use these orderings when calculating
|
||||
with the tensors and the steady state. Also, remember that the $i$th
|
||||
tensor is already divided by $i!$.
|
||||
|
||||
\lstinline{calldynare} also handles exceptions from dynare. All
|
||||
exceptions (except KordException, which sets \lstinline{kordcode})
|
||||
generate an error in the R interface. Normally, when solving a
|
||||
well-formed model (no typos in the equations, etc), users should not
|
||||
encounter these exceptions. Having a journal file is useful for
|
||||
debugging. If you are making long calculations, it is reasonable to
|
||||
catch errors with \lstinline{try} so that they won't abort the
|
||||
calculation.
|
||||
|
||||
% \bibliographystyle{apalike}
|
||||
% \bibliography{/home/tpapp/doc/general.bib}
|
||||
|
||||
\end{document}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: t
|
||||
%%% End:
|
|
@ -1,32 +0,0 @@
|
|||
#include "dynareR.cpp"
|
||||
|
||||
int main(void) {
|
||||
const char *parameters[] = {"beta","gamma","rho","alpha","delta"};
|
||||
const char *varendo[] = {"k","c","a"};
|
||||
const char *varexo[] = {"eps"};
|
||||
const int numpar = 5;
|
||||
const int numendo = 3;
|
||||
const int numexo = 1;
|
||||
const int ord = 2;
|
||||
const int numsteps = 0;
|
||||
const double parval[] = {.99,2,.9,.3,.025};
|
||||
const double vcov[] = {0.001};
|
||||
const double initval[] = {0.066, 0.43, 0.01};
|
||||
|
||||
int e;
|
||||
double tensorbuffer[100];
|
||||
int num_state;
|
||||
int ordering_state[] = {0,0,0};
|
||||
int ordering_endo[] = {0,0,0};
|
||||
int ordering_exo[] = {0};
|
||||
double newinitval[] = {0,0,0};
|
||||
|
||||
const char *modeleq[] = {"(c/c(1))^gamma*beta*(alpha*exp(a(1))*k^(alpha-1)+1-delta)=1; a=rho*a(-1)+eps; k+c=exp(a)*k(-1)^alpha+(1-delta)*k(-1);"};
|
||||
|
||||
dynareR(varendo, &numendo, varexo, &numexo, parameters, &numpar, modeleq,
|
||||
&ord, "journal", parval, vcov, initval,
|
||||
&numsteps, tensorbuffer,
|
||||
&num_state, ordering_state, ordering_endo, ordering_exo,
|
||||
newinitval,&e);
|
||||
printf("error code: %d\n", e);
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
source("dynareR.r")
|
||||
|
||||
parameters <- c("beta","gamma","rho","alpha","delta")
|
||||
varendo <- c("k","c","a")
|
||||
varexo <- "eps"
|
||||
parval <- c(.99,2,.9,.3,.025)
|
||||
vcovmatrix <- matrix(1,1,1)
|
||||
initval <- c(0.066, 0.43, 0.01)
|
||||
|
||||
modeleq <- c("(c/c(1))^gamma*beta*(alpha*exp(a(1))*k^(alpha-1)+1-delta)=1",
|
||||
"a=rho*a(-1)+eps",
|
||||
"k+c=exp(a)*k(-1)^alpha+(1-delta)*k(-1)")
|
||||
|
||||
|
||||
dd <- calldynare(modeleq,varendo,varexo,parameters,2,parval,vcovmatrix,initval)
|
|
@ -1,129 +0,0 @@
|
|||
// Copyright (C) 2005-2011, Ondra Kamenik
|
||||
|
||||
// This is the mexFunction providing interface to
|
||||
// DecisionRule<>::simulate(). It takes the following input
|
||||
// parameters:
|
||||
// order the order of approximation, needs order+1 derivatives
|
||||
// nstat
|
||||
// npred
|
||||
// nboth
|
||||
// nforw
|
||||
// nexog
|
||||
// ystart starting value (full vector of endogenous)
|
||||
// shocks matrix of shocks (nexog x number of period)
|
||||
// vcov covariance matrix of shocks (nexog x nexog)
|
||||
// seed integer seed
|
||||
// ysteady full vector of decision rule's steady
|
||||
// ... order+1 matrices of derivatives
|
||||
|
||||
// output:
|
||||
// res simulated results
|
||||
|
||||
#include "dynmex.h"
|
||||
#include "mex.h"
|
||||
|
||||
#include "decision_rule.h"
|
||||
#include "fs_tensor.h"
|
||||
#include "SylvException.h"
|
||||
|
||||
extern "C" {
|
||||
void mexFunction(int nlhs, mxArray* plhs[],
|
||||
int nhrs, const mxArray* prhs[])
|
||||
{
|
||||
if (nhrs < 12 || nlhs != 2)
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT("dynare_simul_ must have at least 12 input parameters and exactly 2 output arguments.\n");
|
||||
|
||||
int order = (int)mxGetScalar(prhs[0]);
|
||||
if (nhrs != 12 + order)
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT("dynare_simul_ must have exactly 11+order input parameters.\n");
|
||||
|
||||
int nstat = (int)mxGetScalar(prhs[1]);
|
||||
int npred = (int)mxGetScalar(prhs[2]);
|
||||
int nboth = (int)mxGetScalar(prhs[3]);
|
||||
int nforw = (int)mxGetScalar(prhs[4]);
|
||||
int nexog = (int)mxGetScalar(prhs[5]);
|
||||
|
||||
const mxArray* const ystart = prhs[6];
|
||||
const mxArray* const shocks = prhs[7];
|
||||
const mxArray* const vcov = prhs[8];
|
||||
int seed = (int)mxGetScalar(prhs[9]);
|
||||
const mxArray* const ysteady = prhs[10];
|
||||
const mwSize* const ystart_dim = mxGetDimensions(ystart);
|
||||
const mwSize* const shocks_dim = mxGetDimensions(shocks);
|
||||
const mwSize* const vcov_dim = mxGetDimensions(vcov);
|
||||
const mwSize* const ysteady_dim = mxGetDimensions(ysteady);
|
||||
|
||||
int ny = nstat + npred + nboth + nforw;
|
||||
if (ny != (int) ystart_dim[0])
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT("ystart has wrong number of rows.\n");
|
||||
if (1 != ystart_dim[1])
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT("ystart has wrong number of cols.\n");
|
||||
int nper = shocks_dim[1];
|
||||
if (nexog != (int) shocks_dim[0])
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT("shocks has a wrong number of rows.\n");
|
||||
if (nexog != (int) vcov_dim[0])
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT("vcov has a wrong number of rows.\n");
|
||||
if (nexog != (int) vcov_dim[1])
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT("vcov has a wrong number of cols.\n");
|
||||
if (ny != (int) ysteady_dim[0])
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT("ysteady has wrong number of rows.\n");
|
||||
if (1 != ysteady_dim[1])
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT("ysteady has wrong number of cols.\n");
|
||||
|
||||
mxArray* res = mxCreateDoubleMatrix(ny, nper, mxREAL);
|
||||
|
||||
try {
|
||||
// initialize tensor library
|
||||
tls.init(order, npred+nboth+nexog);
|
||||
|
||||
// form the polynomial
|
||||
UTensorPolynomial pol(ny, npred+nboth+nexog);
|
||||
for (int dim = 0; dim <= order; dim++) {
|
||||
const mxArray* gk = prhs[11+dim];
|
||||
const mwSize* const gk_dim = mxGetDimensions(gk);
|
||||
FFSTensor ft(ny, npred+nboth+nexog, dim);
|
||||
if (ft.ncols() != (int) gk_dim[1]) {
|
||||
char buf[1000];
|
||||
sprintf(buf, "Wrong number of columns for folded tensor: got %d but I want %d\n",
|
||||
(int) gk_dim[1], ft.ncols());
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT(buf);
|
||||
}
|
||||
if (ft.nrows() != (int) gk_dim[0]) {
|
||||
char buf[1000];
|
||||
sprintf(buf, "Wrong number of rows for folded tensor: got %d but I want %d\n",
|
||||
(int) gk_dim[0], ft.nrows());
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT(buf);
|
||||
}
|
||||
ft.zeros();
|
||||
ConstTwoDMatrix gk_mat(ft.nrows(), ft.ncols(), mxGetPr(gk));
|
||||
ft.add(1.0, gk_mat);
|
||||
UFSTensor* ut = new UFSTensor(ft);
|
||||
pol.insert(ut);
|
||||
}
|
||||
// form the decision rule
|
||||
UnfoldDecisionRule
|
||||
dr(pol, PartitionY(nstat, npred, nboth, nforw),
|
||||
nexog, ConstVector(mxGetPr(ysteady), ny));
|
||||
// form the shock realization
|
||||
TwoDMatrix shocks_mat(nexog, nper, (const double*)mxGetPr(shocks));
|
||||
TwoDMatrix vcov_mat(nexog, nexog, (const double*)mxGetPr(vcov));
|
||||
GenShockRealization sr(vcov_mat, shocks_mat, seed);
|
||||
// simulate and copy the results
|
||||
Vector ystart_vec((const double*)mxGetPr(ystart), ny);
|
||||
TwoDMatrix* res_mat =
|
||||
dr.simulate(DecisionRule::horner, nper,
|
||||
ystart_vec, sr);
|
||||
TwoDMatrix res_tmp_mat(ny, nper, mxGetPr(res));
|
||||
res_tmp_mat = (const TwoDMatrix&)(*res_mat);
|
||||
delete res_mat;
|
||||
plhs[1] = res;
|
||||
} catch (const KordException& e) {
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT("Caugth Kord exception.");
|
||||
} catch (const TLException& e) {
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT("Caugth TL exception.");
|
||||
} catch (SylvException& e) {
|
||||
DYN_MEX_FUNC_ERR_MSG_TXT("Caught Sylv exception.");
|
||||
}
|
||||
plhs[0] = mxCreateDoubleScalar(0);
|
||||
}
|
||||
};
|
|
@ -1,174 +0,0 @@
|
|||
%
|
||||
% SYNOPSIS
|
||||
%
|
||||
% r = dynare_simul(name, shocks)
|
||||
% r = dynare_simul(name, prefix, shocks)
|
||||
% r = dynare_simul(name, shocks, start)
|
||||
% r = dynare_simul(name, prefix, shocks, start)
|
||||
%
|
||||
% name name of MAT-file produced by dynare++
|
||||
% prefix prefix of variables in the MAT-file
|
||||
% shocks matrix of shocks
|
||||
% start zero period value
|
||||
%
|
||||
% Note that this file requires the dynare_simul_ DLL to be in the path.
|
||||
% This DLL is distributed with Dynare, under the mex/matlab or mex/octave
|
||||
% subdirectory.
|
||||
%
|
||||
% SEMANTICS
|
||||
%
|
||||
% The command reads a decision rule from the MAT-file having the given
|
||||
% prefix. Then it starts simulating the decision rule with zero time value
|
||||
% equal to the given start. It uses the given shocks for the simulation. If
|
||||
% the start is not given, the state about which the decision rule is
|
||||
% centralized is taken (called fix point, or stochastic steady state, take
|
||||
% your pick).
|
||||
%
|
||||
% prefix Use the prefix with which you called dynare++, the default
|
||||
% prefix in dynare++ is 'dyn'.
|
||||
% shocks Number of rows must be a number of exogenous shocks,
|
||||
% number of columns gives the number of simulated
|
||||
% periods. NaNs and Infs in the matrix are substitued by
|
||||
% draws from the normal distribution using the covariance
|
||||
% matrix given in the model file.
|
||||
% start Vector of endogenous variables in the ordering given by
|
||||
% <prefix>_vars.
|
||||
%
|
||||
% Seed for random generator is derived from calling rand(1,1). Therefore,
|
||||
% seeding can be controlled with rand('state') and rand('state',some_seed).
|
||||
%
|
||||
% EXAMPLES
|
||||
%
|
||||
% All examples suppose that the prefix is 'dyn' and that your_model.mat
|
||||
% has been loaded into Matlab.
|
||||
%
|
||||
% 1. response to permanent negative shock to the third exo var EPS3 for
|
||||
% 100 periods
|
||||
%
|
||||
% shocks = zeros(4,100); % 4 exogenous variables in the model
|
||||
% shocks(dyn_i_EPS3,:) = -0.1; % the permanent shock to EPS3
|
||||
% r = dynare_simul('your_model.mat',shocks);
|
||||
%
|
||||
% 2. one stochastic simulation for 100 periods
|
||||
%
|
||||
% shocks = zeros(4,100)./0; % put NaNs everywhere
|
||||
% r = dynare_simul('your_model.mat',shocks);
|
||||
%
|
||||
% 3. one stochastic simulation starting at 75% undercapitalized economy
|
||||
%
|
||||
% shocks = zeros(4,100)./0; % put NaNs everywhere
|
||||
% ystart = dyn_ss; % get copy of DR fix point
|
||||
% ystart(dyn_i_K) = 0.75*dyn_ss(dyn_i_K); % scale down the capital
|
||||
% r = dynare_simul('your_model.mat',shocks,ystart);
|
||||
%
|
||||
%
|
||||
% SEE ALSO
|
||||
%
|
||||
% "DSGE Models with Dynare++. A Tutorial.", Ondra Kamenik, 2005
|
||||
|
||||
% Copyright (C) 2005-2011, Ondra Kamenik
|
||||
|
||||
function r = dynare_simul(varargin)
|
||||
|
||||
if exist('dynare_simul_') ~= 3
|
||||
error('Can''t find dynare_simul_ DLL in the path. The simplest way to add it is to run Dynare once in this session.')
|
||||
end
|
||||
|
||||
% get the file name and load data
|
||||
fname = varargin{1};
|
||||
eval(['load ' fname]);
|
||||
|
||||
% set prefix, shocks, ystart
|
||||
if ischar(varargin{2})
|
||||
prefix = varargin{2};
|
||||
if length(varargin) == 3
|
||||
shocks = varargin{3};
|
||||
ystart = NaN;
|
||||
elseif length(varargin) == 4
|
||||
shocks = varargin{3};
|
||||
ystart = varargin{4};
|
||||
else
|
||||
error('Wrong number of parameters.');
|
||||
end
|
||||
else
|
||||
prefix = 'dyn';
|
||||
if length(varargin) == 2
|
||||
shocks = varargin{2};
|
||||
ystart = NaN;
|
||||
elseif length(varargin) == 3
|
||||
shocks = varargin{2};
|
||||
ystart = varargin{3};
|
||||
else
|
||||
error('Wrong number of parameters.');
|
||||
end
|
||||
end
|
||||
|
||||
% load all needed variables but prefix_g_*
|
||||
if (exist([prefix '_nstat']))
|
||||
nstat = eval([prefix '_nstat']);
|
||||
else
|
||||
error(['Could not find variable ' prefix '_nstat in workspace']);
|
||||
end
|
||||
if (exist([prefix '_npred']))
|
||||
npred = eval([prefix '_npred']);
|
||||
else
|
||||
error(['Could not find variable ' prefix '_npred in workspace']);
|
||||
end
|
||||
if (exist([prefix '_nboth']))
|
||||
nboth = eval([prefix '_nboth']);
|
||||
else
|
||||
error(['Could not find variable ' prefix '_nboth in workspace']);
|
||||
end
|
||||
if (exist([prefix '_nforw']))
|
||||
nforw = eval([prefix '_nforw']);
|
||||
else
|
||||
error(['Could not find variable ' prefix '_nforw in workspace']);
|
||||
end
|
||||
if (exist([prefix '_ss']))
|
||||
ss = eval([prefix '_ss']);
|
||||
else
|
||||
error(['Could not find variable ' prefix '_ss in workspace']);
|
||||
end
|
||||
if (exist([prefix '_vcov_exo']))
|
||||
vcov_exo = eval([prefix '_vcov_exo']);
|
||||
else
|
||||
error(['Could not find variable ' prefix '_vcov_exo in workspace']);
|
||||
end
|
||||
nexog = size(vcov_exo,1);
|
||||
|
||||
if isnan(ystart)
|
||||
ystart = ss;
|
||||
end
|
||||
|
||||
% newer version of dynare++ doesn't return prefix_g_0, we make it here if
|
||||
% it does not exist in workspace
|
||||
g_zero = [prefix '_g_0'];
|
||||
if (~ exist(g_zero))
|
||||
eval([ g_zero '= zeros(nstat+npred+nboth+nforw,1);']);
|
||||
end
|
||||
|
||||
% make derstr a string of comma seperated existing prefix_g_*
|
||||
derstr = [',' g_zero];
|
||||
order = 1;
|
||||
cont = 1;
|
||||
while cont == 1
|
||||
g_ord = [prefix '_g_' num2str(order)];
|
||||
if (exist(g_ord))
|
||||
derstr = [derstr ',' g_ord];
|
||||
order = order + 1;
|
||||
else
|
||||
cont = 0;
|
||||
end
|
||||
end
|
||||
|
||||
% set seed
|
||||
seed = ceil(10000*rand(1,1));
|
||||
|
||||
% call dynare_simul_
|
||||
command = ['[err,r]=dynare_simul_(' num2str(order-1) ',nstat,npred,nboth,nforw,' ...
|
||||
'nexog,ystart,shocks,vcov_exo,seed,ss' derstr ');'];
|
||||
eval(command);
|
||||
|
||||
if err
|
||||
error('Simulation failed')
|
||||
end
|
|
@ -1,54 +1,16 @@
|
|||
CWEBSRC = \
|
||||
product.cweb \
|
||||
quadrature.cweb \
|
||||
quasi_mcarlo.cweb \
|
||||
smolyak.cweb \
|
||||
vector_function.cweb \
|
||||
product.hweb \
|
||||
quadrature.hweb \
|
||||
quasi_mcarlo.hweb \
|
||||
smolyak.hweb \
|
||||
vector_function.hweb
|
||||
|
||||
GENERATED_FILES = \
|
||||
product.cpp \
|
||||
quadrature.cpp \
|
||||
quasi_mcarlo.cpp \
|
||||
smolyak.cpp \
|
||||
vector_function.cpp \
|
||||
product.h \
|
||||
quadrature.h \
|
||||
quasi_mcarlo.h \
|
||||
smolyak.h \
|
||||
vector_function.h
|
||||
|
||||
noinst_LIBRARIES = libinteg.a
|
||||
|
||||
libinteg_a_SOURCES = $(CWEBSRC) $(GENERATED_FILES) precalc_quadrature.dat
|
||||
libinteg_a_CPPFLAGS = -I../../sylv/cc -I../../tl/cc -I$(top_srcdir)/mex/sources
|
||||
libinteg_a_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
|
||||
|
||||
BUILT_SOURCES = $(GENERATED_FILES)
|
||||
|
||||
EXTRA_DIST = main.web dummy.ch
|
||||
|
||||
%.cpp: %.cweb dummy.ch
|
||||
$(CTANGLE) -bhp $< dummy.ch $@
|
||||
|
||||
%.h: %.hweb dummy.ch
|
||||
$(CTANGLE) -bhp $< dummy.ch $@
|
||||
|
||||
if HAVE_CWEAVE
|
||||
if HAVE_PDFTEX
|
||||
if HAVE_EPLAIN
|
||||
pdf-local: integ.pdf
|
||||
|
||||
integ.pdf: main.web $(CWEBSRC)
|
||||
$(CWEAVE) -bhp main.web
|
||||
$(PDFTEX) main
|
||||
mv main.pdf integ.pdf
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
CLEANFILES = integ.pdf main.idx main.log main.scn main.tex main.toc
|
||||
libinteg_a_SOURCES = \
|
||||
quadrature.cc \
|
||||
quadrature.hh \
|
||||
quasi_mcarlo.cc \
|
||||
quasi_mcarlo.hh \
|
||||
product.cc \
|
||||
product.hh \
|
||||
smolyak.cc \
|
||||
smolyak.hh \
|
||||
vector_function.cc \
|
||||
vector_function.hh \
|
||||
precalc_quadrature.hh
|
||||
libinteg_a_CPPFLAGS = -I../../sylv/cc -I../../utils/cc -I../../tl/cc -I$(top_srcdir)/mex/sources
|
||||
libinteg_a_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
@q $Id: main.web 2333 2009-01-14 10:32:55Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@q cwebmac.tex defines its own \ifpdf, which is incompatible with the @>
|
||||
@q \ifpdf defined by eplain, so undefine it @>
|
||||
\let\ifpdf\relax
|
||||
\input eplain
|
||||
|
||||
@q now define \ifpdf to be always false: PDF macros of cwebmac are buggy @>
|
||||
\newif\ifpdf
|
||||
\iffalse\fi
|
||||
|
||||
\def\title{{\mainfont Numerical Integration Module}}
|
||||
|
||||
|
||||
@i ../../c++lib.w
|
||||
@s Vector int
|
||||
@s ConstVector int
|
||||
@s IntSequence int
|
||||
@s GeneralMatrix int
|
||||
@s THREAD int
|
||||
@s THREAD_GROUP int
|
||||
@s SYNCHRO int
|
||||
|
||||
\titletrue
|
||||
\null\vfill
|
||||
\centerline{\titlefont Numerical Integration Module}
|
||||
\vfill\vfill
|
||||
Copyright \copyright\ 2005 by Ondra Kamenik
|
||||
|
||||
\penalty-10000
|
||||
|
||||
@i vector_function.hweb
|
||||
@i vector_function.cweb
|
||||
|
||||
@i quadrature.hweb
|
||||
@i quadrature.cweb
|
||||
|
||||
@i product.hweb
|
||||
@i product.cweb
|
||||
|
||||
@i smolyak.hweb
|
||||
@i smolyak.cweb
|
||||
|
||||
@i quasi_mcarlo.hweb
|
||||
@i quasi_mcarlo.cweb
|
||||
|
||||
|
|
@ -1,25 +1,42 @@
|
|||
// $Id: precalc_quadrature.dat 431 2005-08-16 15:41:01Z kamenik $
|
||||
// Copyright 2005, Ondra Kamenik
|
||||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// The file contains one dimensional quadrature points and weights for
|
||||
// a few quadratures. The format of data is clear. There is a class
|
||||
// OneDPrecalcQuadrature which implements an interface OneDQuadrature
|
||||
// using the data of this format.
|
||||
// The file contains one dimensional quadrature points and weights for a few
|
||||
// quadratures. The format of data is clear. There is a class
|
||||
// OneDPrecalcQuadrature which implements an interface OneDQuadrature using the
|
||||
// data of this format.
|
||||
|
||||
// Gauss-Hermite quadrature; prefix gh
|
||||
|
||||
// number of levels
|
||||
// Number of levels
|
||||
static const int gh_num_levels = 26;
|
||||
|
||||
// number of points in each level
|
||||
// Number of points in each level
|
||||
static const int gh_num_points[] = {
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
30, 32, 40, 50, 60, 64
|
||||
};
|
||||
|
||||
// weights, starting with the first level
|
||||
// Weights, starting with the first level
|
||||
static const double gh_weights[] = {
|
||||
// weights 1 = sqrt(pi)
|
||||
// weights 1 = √π
|
||||
1.77245385090551588191942755656782537698745727539062,
|
||||
// weights 2
|
||||
0.886226925452758013649083741671e+00,
|
||||
|
@ -533,7 +550,7 @@ static const double gh_weights[] = {
|
|||
0.553570653584e-48
|
||||
};
|
||||
|
||||
// points, starting with the first level
|
||||
// Points, starting with the first level
|
||||
static const double gh_points[] = {
|
||||
// points 1
|
||||
0.0,
|
||||
|
@ -1051,16 +1068,16 @@ static const double gh_points[] = {
|
|||
|
||||
// Gauss-Legendre quadrature; prefix gl
|
||||
|
||||
// number of levels
|
||||
// Number of levels
|
||||
static const int gl_num_levels = 22;
|
||||
|
||||
// number of points in each level
|
||||
// Number of points in each level
|
||||
static const int gl_num_points[] = {
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
32, 64
|
||||
};
|
||||
|
||||
// weights, starting with the first level
|
||||
// Weights, starting with the first level
|
||||
static const double gl_weights[] = {
|
||||
// weight 1
|
||||
2.0e+00,
|
||||
|
@ -1392,7 +1409,7 @@ static const double gl_weights[] = {
|
|||
0.178328072169643294729607914497e-02
|
||||
};
|
||||
|
||||
// points, starting with the first level
|
||||
// Points, starting with the first level
|
||||
static const double gl_points[] = {
|
||||
// points 1
|
||||
0.0e+00,
|
||||
|
@ -1723,99 +1740,3 @@ static const double gl_points[] = {
|
|||
0.996340116771955279346924500676e+00,
|
||||
0.999305041735772139456905624346e+00
|
||||
};
|
||||
|
||||
// this is the positive half of normal inverse cum distribution
|
||||
// function starting at 0.5 and ending at 0.998, with step 0.002
|
||||
static const int normal_icdf_num = 250;
|
||||
static const double normal_icdf_end = 0.998;
|
||||
static const double normal_icdf_step = 0.002;
|
||||
static const double normal_icdf_data[] = {
|
||||
0, 5.013277548926632e-03, 1.002668110027482e-02,
|
||||
1.504033667863573e-02, 2.005437035295075e-02, 2.506890825871118e-02,
|
||||
3.008407662018906e-02, 3.510000177270896e-02, 4.011681018496811e-02,
|
||||
4.513462848142118e-02, 5.015358346473358e-02, 5.517380213831685e-02,
|
||||
6.019541172895673e-02, 6.521853970954372e-02, 7.024331382191684e-02,
|
||||
7.526986209982979e-02, 8.029831289205518e-02, 8.532879488562921e-02,
|
||||
9.036143712925872e-02, 9.539636905689193e-02, 1.004337205114700e-01,
|
||||
1.054736217688682e-01, 1.105162035620419e-01, 1.155615971053833e-01,
|
||||
1.206099341193073e-01, 1.256613468550742e-01, 1.307159681198632e-01,
|
||||
1.357739313021116e-01, 1.408353703971274e-01, 1.459004200329941e-01,
|
||||
1.509692154967774e-01, 1.560418927610502e-01, 1.611185885107454e-01,
|
||||
1.661994401703590e-01, 1.712845859315068e-01, 1.763741647808615e-01,
|
||||
1.814683165284770e-01, 1.865671818365194e-01, 1.916709022484199e-01,
|
||||
1.967796202184666e-01, 2.018934791418509e-01, 2.070126233851871e-01,
|
||||
2.121371983175242e-01, 2.172673503418634e-01, 2.224032269272064e-01,
|
||||
2.275449766411493e-01, 2.326927491830447e-01, 2.378466954177492e-01,
|
||||
2.430069674099821e-01, 2.481737184593126e-01, 2.533471031357997e-01,
|
||||
2.585272773163098e-01, 2.637143982215299e-01, 2.689086244537098e-01,
|
||||
2.741101160351471e-01, 2.793190344474543e-01, 2.845355426716215e-01,
|
||||
2.897598052289143e-01, 2.949919882226262e-01, 3.002322593807220e-01,
|
||||
3.054807880993972e-01, 3.107377454875922e-01, 3.160033044124830e-01,
|
||||
3.212776395459965e-01, 3.265609274123727e-01, 3.318533464368166e-01,
|
||||
3.371550769952773e-01, 3.424663014653906e-01, 3.477872042786273e-01,
|
||||
3.531179719736894e-01, 3.584587932511938e-01, 3.638098590296960e-01,
|
||||
3.691713625030897e-01, 3.745434991994428e-01, 3.799264670413076e-01,
|
||||
3.853204664075677e-01, 3.907257001968699e-01, 3.961423738926983e-01,
|
||||
4.015706956301487e-01, 4.070108762644656e-01, 4.124631294414047e-01,
|
||||
4.179276716694820e-01, 4.234047223941831e-01, 4.288945040742017e-01,
|
||||
4.343972422597815e-01, 4.399131656732339e-01, 4.454425062917200e-01,
|
||||
4.509854994323708e-01, 4.565423838398405e-01, 4.621134017763774e-01,
|
||||
4.676987991145082e-01, 4.732988254324370e-01, 4.789137341122557e-01,
|
||||
4.845437824410792e-01, 4.901892317152095e-01, 4.958503473474533e-01,
|
||||
5.015273989777081e-01, 5.072206605869456e-01, 5.129304106147284e-01,
|
||||
5.186569320803909e-01, 5.244005127080407e-01, 5.301614450555191e-01,
|
||||
5.359400266474903e-01, 5.417365601128169e-01, 5.475513533264015e-01,
|
||||
5.533847195556728e-01, 5.592369776119069e-01, 5.651084520065839e-01,
|
||||
5.709994731129874e-01, 5.769103773332714e-01, 5.828415072712163e-01,
|
||||
5.887932119109195e-01, 5.947658468016782e-01, 6.007597742493188e-01,
|
||||
6.067753635142652e-01, 6.128129910166273e-01, 6.188730405486286e-01,
|
||||
6.249559034946875e-01, 6.310619790594989e-01, 6.371916745044747e-01,
|
||||
6.433454053929173e-01, 6.495235958443252e-01, 6.557266787982537e-01,
|
||||
6.619550962881621e-01, 6.682092997257233e-01, 6.744897501960819e-01,
|
||||
6.807969187645747e-01, 6.871312867954694e-01, 6.934933462832894e-01,
|
||||
6.998836001973414e-01, 7.063025628400875e-01, 7.127507602200432e-01,
|
||||
7.192287304399239e-01, 7.257370241008051e-01, 7.322762047230997e-01,
|
||||
7.388468491852137e-01, 7.454495481807891e-01, 7.520849066954916e-01,
|
||||
7.587535445043710e-01, 7.654560966908778e-01, 7.721932141886847e-01,
|
||||
7.789655643475453e-01, 7.857738315244843e-01, 7.926187177017122e-01,
|
||||
7.995009431327367e-01, 8.064212470182405e-01, 8.133803882134047e-01,
|
||||
8.203791459684610e-01, 8.274183207043821e-01, 8.344987348257406e-01,
|
||||
8.416212335729145e-01, 8.487866859159668e-01, 8.559959854926823e-01,
|
||||
8.632500515934207e-01, 8.705498301956541e-01, 8.778962950512290e-01,
|
||||
8.852904488296417e-01, 8.927333243208563e-01, 9.002259857014339e-01,
|
||||
9.077695298680560e-01, 9.153650878428145e-01, 9.230138262549803e-01,
|
||||
9.307169489043392e-01, 9.384756984115684e-01, 9.462913579615760e-01,
|
||||
9.541652531461944e-01, 9.620987539131418e-01, 9.700932766287370e-01,
|
||||
9.781502862624715e-01, 9.862712987022384e-01, 9.944578832097529e-01,
|
||||
1.002711665026549e+00, 1.011034328141817e+00, 1.019427618234370e+00,
|
||||
1.027893345802143e+00, 1.036433389493790e+00, 1.045049699658389e+00,
|
||||
1.053744302130666e+00, 1.062519302270867e+00, 1.071376889280213e+00,
|
||||
1.080319340814956e+00, 1.089349027924277e+00, 1.098468420339863e+00,
|
||||
1.107680092147800e+00, 1.116986727876610e+00, 1.126391129038801e+00,
|
||||
1.135896221167312e+00, 1.145505061392697e+00, 1.155220846611952e+00,
|
||||
1.165046922305602e+00, 1.174986792066090e+00, 1.185044127907810e+00,
|
||||
1.195222781437427e+00, 1.205526795972518e+00, 1.215960419707319e+00,
|
||||
1.226528120036610e+00, 1.237234599162827e+00, 1.248084811127547e+00,
|
||||
1.259083980427072e+00, 1.270237622393149e+00, 1.281551565544601e+00,
|
||||
1.293031976144243e+00, 1.304685385228790e+00, 1.316518718418261e+00,
|
||||
1.328539328856810e+00, 1.340755033690217e+00, 1.353174154548003e+00,
|
||||
1.365805562572272e+00, 1.378658728623277e+00, 1.391743779396326e+00,
|
||||
1.405071560309632e+00, 1.418653706172739e+00, 1.432502720825812e+00,
|
||||
1.446632067158978e+00, 1.461056269186906e+00, 1.475791028179170e+00,
|
||||
1.490853355246661e+00, 1.506261723278244e+00, 1.522036241735856e+00,
|
||||
1.538198858584064e+00, 1.554773594596853e+00, 1.571786816509860e+00,
|
||||
1.589267557051392e+00, 1.607247891900218e+00, 1.625763386233235e+00,
|
||||
1.644853626951473e+00, 1.664562861202721e+00, 1.684940767871913e+00,
|
||||
1.706043396888962e+00, 1.727934322388419e+00, 1.750686071252170e+00,
|
||||
1.774381910344958e+00, 1.799118106837967e+00, 1.825006821146403e+00,
|
||||
1.852179858769047e+00, 1.880793608151250e+00, 1.911035647549119e+00,
|
||||
1.943133751105067e+00, 1.977368428181947e+00, 2.014090812018140e+00,
|
||||
2.053748910631823e+00, 2.096927429164343e+00, 2.144410620911840e+00,
|
||||
2.197286376641053e+00, 2.257129244486226e+00, 2.326347874040842e+00,
|
||||
2.408915545815460e+00, 2.512144327930459e+00, 2.652069807902199e+00,
|
||||
2.878161739095476e+00
|
||||
};
|
||||
|
||||
// Local Variables:
|
||||
// mode:C++
|
||||
// End:
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "product.hh"
|
||||
#include "symmetry.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
/* This constructs a product iterator corresponding to index (j0,0,…,0). */
|
||||
|
||||
prodpit::prodpit(const ProductQuadrature &q, int j0, int l)
|
||||
: prodq(q), level(l), npoints(q.uquad.numPoints(l)),
|
||||
jseq(q.dimen(), 0),
|
||||
end_flag(false),
|
||||
sig{q.dimen()},
|
||||
p{q.dimen()}
|
||||
{
|
||||
if (j0 < npoints)
|
||||
{
|
||||
jseq[0] = j0;
|
||||
setPointAndWeight();
|
||||
}
|
||||
else
|
||||
end_flag = true;
|
||||
}
|
||||
|
||||
bool
|
||||
prodpit::operator==(const prodpit &ppit) const
|
||||
{
|
||||
return &prodq == &ppit.prodq && end_flag == ppit.end_flag && jseq == ppit.jseq;
|
||||
}
|
||||
|
||||
prodpit &
|
||||
prodpit::operator++()
|
||||
{
|
||||
int i = prodq.dimen()-1;
|
||||
jseq[i]++;
|
||||
while (i >= 0 && jseq[i] == npoints)
|
||||
{
|
||||
jseq[i] = 0;
|
||||
i--;
|
||||
if (i >= 0)
|
||||
jseq[i]++;
|
||||
}
|
||||
sig.signalAfter(std::max(i, 0));
|
||||
|
||||
if (i == -1)
|
||||
end_flag = true;
|
||||
|
||||
if (!end_flag)
|
||||
setPointAndWeight();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* This calculates the weight and sets point coordinates from the indices. */
|
||||
|
||||
void
|
||||
prodpit::setPointAndWeight()
|
||||
{
|
||||
w = 1.0;
|
||||
for (int i = 0; i < prodq.dimen(); i++)
|
||||
{
|
||||
p[i] = (prodq.uquad).point(level, jseq[i]);
|
||||
w *= (prodq.uquad).weight(level, jseq[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Debug print. */
|
||||
|
||||
void
|
||||
prodpit::print() const
|
||||
{
|
||||
auto ff = std::cout.flags();
|
||||
std::cout << "j=[";
|
||||
for (int i = 0; i < prodq.dimen(); i++)
|
||||
std::cout << std::setw(2) << jseq[i];
|
||||
std::cout << std::showpos << std::fixed << std::setprecision(3)
|
||||
<< "] " << std::setw(4) << w << "*(";
|
||||
for (int i = 0; i < prodq.dimen()-1; i++)
|
||||
std::cout << std::setw(4) << p[i] << ' ';
|
||||
std::cout << std::setw(4) << p[prodq.dimen()-1] << ')' << std::endl;
|
||||
std::cout.flags(ff);
|
||||
}
|
||||
|
||||
ProductQuadrature::ProductQuadrature(int d, const OneDQuadrature &uq)
|
||||
: QuadratureImpl<prodpit>(d), uquad(uq)
|
||||
{
|
||||
// TODO: check d≥1
|
||||
}
|
||||
|
||||
/* This calls prodpit constructor to return an iterator which points
|
||||
approximatelly at ‘ti’-th portion out of ‘tn’ portions. First we find
|
||||
out how many points are in the level, and then construct an interator
|
||||
(j0,0,…,0) where j0=ti·npoints/tn. */
|
||||
|
||||
prodpit
|
||||
ProductQuadrature::begin(int ti, int tn, int l) const
|
||||
{
|
||||
// TODO: raise if l<dimen()
|
||||
// TODO: check l ≤ uquad.numLevels()
|
||||
int npoints = uquad.numPoints(l);
|
||||
return prodpit(*this, ti*npoints/tn, l);
|
||||
}
|
||||
|
||||
/* This just starts at the first level and goes to a higher level as long as a
|
||||
number of evaluations (which is nₖᵈ for k being the level) is less than the
|
||||
given number of evaluations. */
|
||||
|
||||
void
|
||||
ProductQuadrature::designLevelForEvals(int max_evals, int &lev, int &evals) const
|
||||
{
|
||||
int last_evals;
|
||||
evals = 1;
|
||||
lev = 1;
|
||||
do
|
||||
{
|
||||
lev++;
|
||||
last_evals = evals;
|
||||
evals = numEvals(lev);
|
||||
}
|
||||
while (lev < uquad.numLevels()-2 && evals < max_evals);
|
||||
lev--;
|
||||
evals = last_evals;
|
||||
}
|
|
@ -1,213 +0,0 @@
|
|||
@q $Id: product.cweb 431 2005-08-16 15:41:01Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@ This is {\tt product.cpp} file.
|
||||
|
||||
@c
|
||||
#include "product.h"
|
||||
#include "symmetry.h"
|
||||
|
||||
@<|prodpit| empty constructor@>;
|
||||
@<|prodpit| regular constructor@>;
|
||||
@<|prodpit| copy constructor@>;
|
||||
@<|prodpit| destructor@>;
|
||||
@<|prodpit::operator==| code@>;
|
||||
@<|prodpit::operator=| code@>;
|
||||
@<|prodpit::operator++| code@>;
|
||||
@<|prodpit::setPointAndWeight| code@>;
|
||||
@<|prodpit::print| code@>;
|
||||
@<|ProductQuadrature| constructor@>;
|
||||
@<|ProductQuadrature::begin| code@>;
|
||||
@<|ProductQuadrature::designLevelForEvals| code@>;
|
||||
|
||||
@
|
||||
@<|prodpit| empty constructor@>=
|
||||
prodpit::prodpit()
|
||||
: prodq(NULL), level(0), npoints(0), jseq(NULL),
|
||||
end_flag(true), sig(NULL), p(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ This constructs a product iterator corresponding to index $(j0,0\ldots,0)$.
|
||||
@<|prodpit| regular constructor@>=
|
||||
prodpit::prodpit(const ProductQuadrature& q, int j0, int l)
|
||||
: prodq(&q), level(l), npoints(q.uquad.numPoints(l)), jseq(new IntSequence(q.dimen(), 0)),
|
||||
end_flag(false), sig(new ParameterSignal(q.dimen())), p(new Vector(q.dimen()))
|
||||
{
|
||||
if (j0 < npoints) {
|
||||
(*jseq)[0] = j0;
|
||||
setPointAndWeight();
|
||||
} else {
|
||||
end_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ Copy constructor, clear.
|
||||
@<|prodpit| copy constructor@>=
|
||||
prodpit::prodpit(const prodpit& ppit)
|
||||
: prodq(ppit.prodq), level(ppit.level), npoints(ppit.npoints),
|
||||
end_flag(ppit.end_flag), w(ppit.w)
|
||||
{
|
||||
if (ppit.jseq)
|
||||
jseq = new IntSequence(*(ppit.jseq));
|
||||
else
|
||||
jseq = NULL;
|
||||
if (ppit.sig)
|
||||
sig = new ParameterSignal(*(ppit.sig));
|
||||
else
|
||||
sig = NULL;
|
||||
if (ppit.p)
|
||||
p = new Vector(*(ppit.p));
|
||||
else
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
@
|
||||
@<|prodpit| destructor@>=
|
||||
prodpit::~prodpit()
|
||||
{
|
||||
if (jseq)
|
||||
delete jseq;
|
||||
if (sig)
|
||||
delete sig;
|
||||
if (p)
|
||||
delete p;
|
||||
}
|
||||
|
||||
@
|
||||
@<|prodpit::operator==| code@>=
|
||||
bool prodpit::operator==(const prodpit& ppit) const
|
||||
{
|
||||
bool ret = true;
|
||||
ret = ret & prodq == ppit.prodq;
|
||||
ret = ret & end_flag == ppit.end_flag;
|
||||
ret = ret & ((jseq==NULL && ppit.jseq==NULL) ||
|
||||
(jseq!=NULL && ppit.jseq!=NULL && *jseq == *(ppit.jseq)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@
|
||||
@<|prodpit::operator=| code@>=
|
||||
const prodpit& prodpit::operator=(const prodpit& ppit)
|
||||
{
|
||||
prodq = ppit.prodq;
|
||||
end_flag = ppit.end_flag;
|
||||
w = ppit.w;
|
||||
|
||||
if (jseq)
|
||||
delete jseq;
|
||||
if (sig)
|
||||
delete sig;
|
||||
if (p)
|
||||
delete p;
|
||||
|
||||
if (ppit.jseq)
|
||||
jseq = new IntSequence(*(ppit.jseq));
|
||||
else
|
||||
jseq = NULL;
|
||||
if (ppit.sig)
|
||||
sig = new ParameterSignal(*(ppit.sig));
|
||||
else
|
||||
sig = NULL;
|
||||
if (ppit.p)
|
||||
p = new Vector(*(ppit.p));
|
||||
else
|
||||
p = NULL;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@
|
||||
@<|prodpit::operator++| code@>=
|
||||
prodpit& prodpit::operator++()
|
||||
{
|
||||
// todo: throw if |prodq==NULL| or |jseq==NULL| or |sig==NULL| or |end_flag==true|
|
||||
int i = prodq->dimen()-1;
|
||||
(*jseq)[i]++;
|
||||
while (i >= 0 && (*jseq)[i] == npoints) {
|
||||
(*jseq)[i] = 0;
|
||||
i--;
|
||||
if (i >= 0)
|
||||
(*jseq)[i]++;
|
||||
}
|
||||
sig->signalAfter(std::max(i,0));
|
||||
|
||||
if (i == -1)
|
||||
end_flag = true;
|
||||
|
||||
if (! end_flag)
|
||||
setPointAndWeight();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@ This calculates the weight and sets point coordinates from the indices.
|
||||
@<|prodpit::setPointAndWeight| code@>=
|
||||
void prodpit::setPointAndWeight()
|
||||
{
|
||||
// todo: raise if |prodq==NULL| or |jseq==NULL| or |sig==NULL| or
|
||||
// |p==NULL| or |end_flag==true|
|
||||
w = 1.0;
|
||||
for (int i = 0; i < prodq->dimen(); i++) {
|
||||
(*p)[i] = (prodq->uquad).point(level, (*jseq)[i]);
|
||||
w* = (prodq->uquad).weight(level, (*jseq)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ Debug print.
|
||||
@<|prodpit::print| code@>=
|
||||
void prodpit::print() const
|
||||
{
|
||||
printf("j=[");
|
||||
for (int i = 0; i < prodq->dimen(); i++)
|
||||
printf("%2d ", (*jseq)[i]);
|
||||
printf("] %+4.3f*(",w);
|
||||
for (int i = 0; i < prodq->dimen()-1; i++)
|
||||
printf("%+4.3f ", (*p)[i]);
|
||||
printf("%+4.3f)\n",(*p)[prodq->dimen()-1]);
|
||||
}
|
||||
|
||||
@
|
||||
@<|ProductQuadrature| constructor@>=
|
||||
ProductQuadrature::ProductQuadrature(int d, const OneDQuadrature& uq)
|
||||
: QuadratureImpl<prodpit>(d), uquad(uq)
|
||||
{
|
||||
// todo: check |d>=1|
|
||||
}
|
||||
|
||||
@ This calls |prodpit| constructor to return an iterator which points
|
||||
approximatelly at |ti|-th portion out of |tn| portions. First we find
|
||||
out how many points are in the level, and then construct an interator
|
||||
$(j0,0,\ldots,0)$ where $j0=$|ti*npoints/tn|.
|
||||
|
||||
@<|ProductQuadrature::begin| code@>=
|
||||
prodpit ProductQuadrature::begin(int ti, int tn, int l) const
|
||||
{
|
||||
// todo: raise is |l<dimen()|
|
||||
// todo: check |l<=uquad.numLevels()|
|
||||
int npoints = uquad.numPoints(l);
|
||||
return prodpit(*this, ti*npoints/tn, l);
|
||||
}
|
||||
|
||||
@ This just starts at the first level and goes to a higher level as
|
||||
long as a number of evaluations (which is $n_k^d$ for $k$ being the
|
||||
level) is less than the given number of evaluations.
|
||||
|
||||
@<|ProductQuadrature::designLevelForEvals| code@>=
|
||||
void ProductQuadrature::designLevelForEvals(int max_evals, int& lev, int& evals) const
|
||||
{
|
||||
int last_evals;
|
||||
evals = 1;
|
||||
lev = 1;
|
||||
do {
|
||||
lev++;
|
||||
last_evals = evals;
|
||||
evals = numEvals(lev);
|
||||
} while (lev < uquad.numLevels()-2 && evals < max_evals);
|
||||
lev--;
|
||||
evals = last_evals;
|
||||
|
||||
}
|
||||
|
||||
@ End of {\tt product.cpp} file
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Product quadrature.
|
||||
|
||||
/* This file defines a product multidimensional quadrature. If Qₖ$ denotes the
|
||||
one dimensional quadrature, then the product quadrature Q of k level and
|
||||
dimension d takes the form:
|
||||
|
||||
nₖ nₖ
|
||||
Qf = ∑ … ∑ w_i₁·…·w_{i_d} f(x_i₁,…,x_{i_d})
|
||||
i₁=1 i_d=1
|
||||
|
||||
which can be written in terms of the one dimensional quadrature Qₖ as
|
||||
|
||||
Qf=(Qₖ⊗…⊗Qₖ)f
|
||||
|
||||
Here we define the product quadrature iterator prodpit and plug it into
|
||||
QuadratureImpl to obtains ProductQuadrature. */
|
||||
|
||||
#ifndef PRODUCT_H
|
||||
#define PRODUCT_H
|
||||
|
||||
#include "int_sequence.hh"
|
||||
#include "vector_function.hh"
|
||||
#include "quadrature.hh"
|
||||
|
||||
/* This defines a product point iterator. We have to maintain the following: a
|
||||
pointer to product quadrature in order to know the dimension and the
|
||||
underlying one dimensional quadrature, then level, number of points in the
|
||||
level, integer sequence of indices, signal, the coordinates of the point and
|
||||
the weight.
|
||||
|
||||
The point indices, signal, and point coordinates are implmented as pointers
|
||||
in order to allow for empty constructor.
|
||||
|
||||
The constructor prodpit(const ProductQuadrature& q, int j0, int l)
|
||||
constructs an iterator pointing to (j0,0,…,0), which is used by begin()
|
||||
dictated by QuadratureImpl. */
|
||||
|
||||
class ProductQuadrature;
|
||||
|
||||
class prodpit
|
||||
{
|
||||
protected:
|
||||
const ProductQuadrature &prodq;
|
||||
int level{0};
|
||||
int npoints{0};
|
||||
IntSequence jseq;
|
||||
bool end_flag{true};
|
||||
ParameterSignal sig;
|
||||
Vector p;
|
||||
double w;
|
||||
public:
|
||||
prodpit() = default;
|
||||
prodpit(const ProductQuadrature &q, int j0, int l);
|
||||
prodpit(const prodpit &ppit) = default;
|
||||
~prodpit() = default;
|
||||
bool operator==(const prodpit &ppit) const;
|
||||
bool
|
||||
operator!=(const prodpit &ppit) const
|
||||
{
|
||||
return !operator==(ppit);
|
||||
}
|
||||
prodpit &operator=(const prodpit &spit) = delete;
|
||||
prodpit &operator++();
|
||||
const ParameterSignal &
|
||||
signal() const
|
||||
{
|
||||
return sig;
|
||||
}
|
||||
const Vector &
|
||||
point() const
|
||||
{
|
||||
return p;
|
||||
}
|
||||
double
|
||||
weight() const
|
||||
{
|
||||
return w;
|
||||
}
|
||||
void print() const;
|
||||
protected:
|
||||
void setPointAndWeight();
|
||||
};
|
||||
|
||||
/* The product quadrature is just QuadratureImpl with the product iterator
|
||||
plugged in. The object is constructed by just giving the underlying one
|
||||
dimensional quadrature, and the dimension. The only extra method is
|
||||
designLevelForEvals() which for the given maximum number of evaluations (and
|
||||
dimension and underlying quadrature from the object) returns a maximum level
|
||||
yeilding number of evaluations less than the given number. */
|
||||
|
||||
class ProductQuadrature : public QuadratureImpl<prodpit>
|
||||
{
|
||||
friend class prodpit;
|
||||
const OneDQuadrature &uquad;
|
||||
public:
|
||||
ProductQuadrature(int d, const OneDQuadrature &uq);
|
||||
~ProductQuadrature() override = default;
|
||||
int
|
||||
numEvals(int l) const override
|
||||
{
|
||||
int res = 1;
|
||||
for (int i = 0; i < dimen(); i++)
|
||||
res *= uquad.numPoints(l);
|
||||
return res;
|
||||
}
|
||||
void designLevelForEvals(int max_eval, int &lev, int &evals) const;
|
||||
protected:
|
||||
prodpit begin(int ti, int tn, int level) const override;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,107 +0,0 @@
|
|||
@q $Id: product.hweb 431 2005-08-16 15:41:01Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@*2 Product quadrature. This is {\tt product.h} file
|
||||
|
||||
This file defines a product multidimensional quadrature. If $Q_k$
|
||||
denotes the one dimensional quadrature, then the product quadrature
|
||||
$Q$ of $k$ level and dimension $d$ takes the form
|
||||
$$Qf=\sum_{i_1=1}^{n_k}\ldots\sum_{i_d=1}^{n^k}w_{i_1}\cdot\ldots\cdot w_{i_d}
|
||||
f(x_{i_1},\ldots,x_{i_d})$$
|
||||
which can be written in terms of the one dimensional quadrature $Q_k$ as
|
||||
$$Qf=(Q_k\otimes\ldots\otimes Q_k)f$$
|
||||
|
||||
Here we define the product quadrature iterator |prodpit| and plug it
|
||||
into |QuadratureImpl| to obtains |ProductQuadrature|.
|
||||
|
||||
@s prodpit int
|
||||
@s ProductQuadrature int
|
||||
|
||||
@c
|
||||
#ifndef PRODUCT_H
|
||||
#define PRODUCT_H
|
||||
|
||||
#include "int_sequence.h"
|
||||
#include "vector_function.h"
|
||||
#include "quadrature.h"
|
||||
|
||||
@<|prodpit| class declaration@>;
|
||||
@<|ProductQuadrature| class declaration@>;
|
||||
|
||||
#endif
|
||||
|
||||
@ This defines a product point iterator. We have to maintain the
|
||||
following: a pointer to product quadrature in order to know the
|
||||
dimension and the underlying one dimensional quadrature, then level,
|
||||
number of points in the level, integer sequence of indices, signal,
|
||||
the coordinates of the point and the weight.
|
||||
|
||||
The point indices, signal, and point coordinates are implmented as
|
||||
pointers in order to allow for empty constructor.
|
||||
|
||||
The constructor |prodpit(const ProductQuadrature& q, int j0, int l)|
|
||||
constructs an iterator pointing to $(j0,0,\ldots,0)$, which is used by
|
||||
|begin| dictated by |QuadratureImpl|.
|
||||
|
||||
@<|prodpit| class declaration@>=
|
||||
class ProductQuadrature;
|
||||
|
||||
class prodpit {
|
||||
protected:@;
|
||||
const ProductQuadrature* prodq;
|
||||
int level;
|
||||
int npoints;
|
||||
IntSequence* jseq;
|
||||
bool end_flag;
|
||||
ParameterSignal* sig;
|
||||
Vector* p;
|
||||
double w;
|
||||
public:@;
|
||||
prodpit();
|
||||
prodpit(const ProductQuadrature& q, int j0, int l);
|
||||
prodpit(const prodpit& ppit);
|
||||
~prodpit();
|
||||
bool operator==(const prodpit& ppit) const;
|
||||
bool operator!=(const prodpit& ppit) const
|
||||
{@+ return ! operator==(ppit);@+}
|
||||
const prodpit& operator=(const prodpit& spit);
|
||||
prodpit& operator++();
|
||||
const ParameterSignal& signal() const
|
||||
{@+ return *sig;@+}
|
||||
const Vector& point() const
|
||||
{@+ return *p;@+}
|
||||
double weight() const
|
||||
{@+ return w;@+}
|
||||
void print() const;
|
||||
protected:@;
|
||||
void setPointAndWeight();
|
||||
};
|
||||
|
||||
@ The product quadrature is just |QuadratureImpl| with the product
|
||||
iterator plugged in. The object is constructed by just giving the
|
||||
underlying one dimensional quadrature, and the dimension. The only
|
||||
extra method is |designLevelForEvals| which for the given maximum
|
||||
number of evaluations (and dimension and underlying quadrature from
|
||||
the object) returns a maximum level yeilding number of evaluations
|
||||
less than the given number.
|
||||
|
||||
@<|ProductQuadrature| class declaration@>=
|
||||
class ProductQuadrature : public QuadratureImpl<prodpit> {
|
||||
friend class prodpit;
|
||||
const OneDQuadrature& uquad;
|
||||
public:@;
|
||||
ProductQuadrature(int d, const OneDQuadrature& uq);
|
||||
virtual ~ProductQuadrature()@+ {}
|
||||
int numEvals(int l) const
|
||||
{
|
||||
int res = 1;
|
||||
for (int i = 0; i < dimen(); i++)
|
||||
res *= uquad.numPoints(l);
|
||||
return res;
|
||||
}
|
||||
void designLevelForEvals(int max_eval, int& lev, int& evals) const;
|
||||
protected:@;
|
||||
prodpit begin(int ti, int tn, int level) const;
|
||||
};
|
||||
|
||||
@ End of {\tt product.h} file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "quadrature.hh"
|
||||
#include "precalc_quadrature.hh"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
void
|
||||
OneDPrecalcQuadrature::calcOffsets()
|
||||
{
|
||||
offsets[0] = 0;
|
||||
for (int i = 1; i < num_levels; i++)
|
||||
offsets[i] = offsets[i-1] + num_points[i-1];
|
||||
}
|
||||
|
||||
GaussHermite::GaussHermite()
|
||||
: OneDPrecalcQuadrature(gh_num_levels, gh_num_points, gh_weights, gh_points)
|
||||
{
|
||||
}
|
||||
|
||||
GaussLegendre::GaussLegendre()
|
||||
: OneDPrecalcQuadrature(gl_num_levels, gl_num_points, gl_weights, gl_points)
|
||||
{
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
@q $Id: quadrature.cweb 431 2005-08-16 15:41:01Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@ This is {\tt quadrature.cpp} file.
|
||||
|
||||
@c
|
||||
#include "quadrature.h"
|
||||
#include "precalc_quadrature.dat"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@<|OneDPrecalcQuadrature::calcOffsets| code@>;
|
||||
@<|GaussHermite| constructor code@>;
|
||||
@<|GaussLegendre| constructor code@>;
|
||||
@<|NormalICDF| get code@>;
|
||||
|
||||
@
|
||||
@<|OneDPrecalcQuadrature::calcOffsets| code@>=
|
||||
void OneDPrecalcQuadrature::calcOffsets()
|
||||
{
|
||||
offsets[0] = 0;
|
||||
for (int i = 1; i < num_levels; i++)
|
||||
offsets[i] = offsets[i-1] + num_points[i-1];
|
||||
}
|
||||
|
||||
@
|
||||
@<|GaussHermite| constructor code@>=
|
||||
GaussHermite::GaussHermite()
|
||||
: OneDPrecalcQuadrature(gh_num_levels, gh_num_points, gh_weights, gh_points)@+ {}
|
||||
|
||||
@
|
||||
@<|GaussLegendre| constructor code@>=
|
||||
GaussLegendre::GaussLegendre()
|
||||
: OneDPrecalcQuadrature(gl_num_levels, gl_num_points, gl_weights, gl_points)@+ {}
|
||||
|
||||
@ Here we transform a draw from univariate $\langle 0,1\rangle$ to the
|
||||
draw from Gaussina $N(0,1)$. This is done by a table lookup, the table
|
||||
is given by |normal_icdf_step|, |normal_icfd_data|, |normal_icdf_num|,
|
||||
and a number |normal_icdf_end|. In order to avoid wrong tails for lookups close
|
||||
to zero or one, we rescale input |x| by $(1-2*(1-end))=2*end-1$.
|
||||
|
||||
@<|NormalICDF| get code@>=
|
||||
double NormalICDF::get(double x)
|
||||
{
|
||||
double xx = (2*normal_icdf_end-1)*std::abs(x-0.5);
|
||||
int i = (int)floor(xx/normal_icdf_step);
|
||||
double xx1 = normal_icdf_step*i;
|
||||
double yy1 = normal_icdf_data[i];
|
||||
double y;
|
||||
if (i < normal_icdf_num-1) {
|
||||
double yy2 = normal_icdf_data[i+1];
|
||||
y = yy1 + (yy2-yy1)*(xx-xx1)/normal_icdf_step;
|
||||
} else { // this should never happen
|
||||
y = yy1;
|
||||
}
|
||||
if (x > 0.5)
|
||||
return y;
|
||||
else
|
||||
return -y;
|
||||
}
|
||||
|
||||
|
||||
@ End of {\tt quadrature.cpp} file
|
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Quadrature.
|
||||
|
||||
/* This file defines an interface for one dimensional (non-nested) quadrature
|
||||
OneDQuadrature, and a parent for all multi-dimensional quadratures. This
|
||||
parent class Quadrature presents a general concept of quadrature, this is
|
||||
|
||||
N
|
||||
∫ f(x)dx ≃ ∑ wᵢxᵢ
|
||||
ⁱ⁼¹
|
||||
|
||||
The class Quadrature just declares this concept. The concept is implemented
|
||||
by class QuadratureImpl which paralelizes the summation. All implementations
|
||||
therefore wishing to use the parallel implementation should inherit from
|
||||
QuadratureImpl and integration is done.
|
||||
|
||||
The integration concept relies on a point iterator, which goes through all
|
||||
xᵢ and wᵢ for i=1,…,N. All the iterators must be able to go through only a
|
||||
portion of the set i=1,…,N. This enables us to implement paralelism, for two
|
||||
threads for example, one iterator goes from the beginning to the
|
||||
(approximately) half, and the other goes from the half to the end.
|
||||
|
||||
Besides this concept of the general quadrature, this file defines also one
|
||||
dimensional quadrature, which is basically a scheme of points and weights
|
||||
for different levels. The class OneDQuadrature is a parent of all such
|
||||
objects, the classes GaussHermite and GaussLegendre are specific
|
||||
implementations for Gauss-Hermite and Gauss-Legendre quadratures resp. */
|
||||
|
||||
#ifndef QUADRATURE_H
|
||||
#define QUADRATURE_H
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "vector_function.hh"
|
||||
#include "int_sequence.hh"
|
||||
#include "sthread.hh"
|
||||
|
||||
/* This pure virtual class represents a concept of one-dimensional (non-nested)
|
||||
quadrature. So, one dimensional quadrature must return number of levels,
|
||||
number of points in a given level, and then a point and a weight in a given
|
||||
level and given order. */
|
||||
|
||||
class OneDQuadrature
|
||||
{
|
||||
public:
|
||||
virtual ~OneDQuadrature() = default;
|
||||
virtual int numLevels() const = 0;
|
||||
virtual int numPoints(int level) const = 0;
|
||||
virtual double point(int level, int i) const = 0;
|
||||
virtual double weight(int lelel, int i) const = 0;
|
||||
};
|
||||
|
||||
/* This is a general concept of multidimensional quadrature. at this general
|
||||
level, we maintain only a dimension, and declare virtual functions for
|
||||
integration. The function take two forms; first takes a constant
|
||||
VectorFunction as an argument, creates locally VectorFunctionSet and do
|
||||
calculation, second one takes as an argument VectorFunctionSet.
|
||||
|
||||
Part of the interface is a method returning a number of evaluations for a
|
||||
specific level. Note two things: this assumes that the number of evaluations
|
||||
is known apriori and thus it is not applicable for adaptive quadratures,
|
||||
second for Monte Carlo type of quadrature, the level is a number of
|
||||
evaluations. */
|
||||
|
||||
class Quadrature
|
||||
{
|
||||
protected:
|
||||
int dim;
|
||||
public:
|
||||
Quadrature(int d) : dim(d)
|
||||
{
|
||||
}
|
||||
virtual ~Quadrature() = default;
|
||||
int
|
||||
dimen() const
|
||||
{
|
||||
return dim;
|
||||
}
|
||||
virtual void integrate(const VectorFunction &func, int level,
|
||||
int tn, Vector &out) const = 0;
|
||||
virtual void integrate(VectorFunctionSet &fs, int level, Vector &out) const = 0;
|
||||
virtual int numEvals(int level) const = 0;
|
||||
};
|
||||
|
||||
/* This is just an integration worker, which works over a given QuadratureImpl.
|
||||
It also needs the function, level, a specification of the subgroup of
|
||||
points, and output vector.
|
||||
|
||||
See QuadratureImpl class declaration for details. */
|
||||
|
||||
template <typename _Tpit>
|
||||
class QuadratureImpl;
|
||||
|
||||
template <typename _Tpit>
|
||||
class IntegrationWorker : public sthread::detach_thread
|
||||
{
|
||||
const QuadratureImpl<_Tpit> &quad;
|
||||
VectorFunction &func;
|
||||
int level;
|
||||
int ti;
|
||||
int tn;
|
||||
Vector &outvec;
|
||||
public:
|
||||
IntegrationWorker(const QuadratureImpl<_Tpit> &q, VectorFunction &f, int l,
|
||||
int tii, int tnn, Vector &out)
|
||||
: quad(q), func(f), level(l), ti(tii), tn(tnn), outvec(out)
|
||||
{
|
||||
}
|
||||
|
||||
/* This integrates the given portion of the integral. We obtain first and
|
||||
last iterators for the portion (‘beg’ and ‘end’). Then we iterate through
|
||||
the portion. and finally we add the intermediate result to the result
|
||||
‘outvec’.
|
||||
|
||||
This method just everything up as it is coming. This might be imply large
|
||||
numerical errors, perhaps in future something smarter should be implemented. */
|
||||
|
||||
void
|
||||
operator()(std::mutex &mut) override
|
||||
{
|
||||
_Tpit beg = quad.begin(ti, tn, level);
|
||||
_Tpit end = quad.begin(ti+1, tn, level);
|
||||
Vector tmpall(outvec.length());
|
||||
tmpall.zeros();
|
||||
Vector tmp(outvec.length());
|
||||
|
||||
/* Note that since ‘beg’ came from begin(), it has empty signal and first
|
||||
evaluation gets no signal */
|
||||
for (_Tpit run = beg; run != end; ++run)
|
||||
{
|
||||
func.eval(run.point(), run.signal(), tmp);
|
||||
tmpall.add(run.weight(), tmp);
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lk{mut};
|
||||
outvec.add(1.0, tmpall);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* This is the class which implements the integration. The class is templated
|
||||
by the iterator type. We declare a method begin() returning an iterator to
|
||||
the beginnning of the ‘ti’-th portion out of total ‘tn’ portions for a given
|
||||
level.
|
||||
|
||||
In addition, we define a method which saves all the points to a given file.
|
||||
Only for debugging purposes. */
|
||||
|
||||
template <typename _Tpit>
|
||||
class QuadratureImpl : public Quadrature
|
||||
{
|
||||
friend class IntegrationWorker<_Tpit>;
|
||||
public:
|
||||
QuadratureImpl(int d) : Quadrature(d)
|
||||
{
|
||||
}
|
||||
|
||||
/* Just fill a thread group with workes and run it. */
|
||||
void
|
||||
integrate(VectorFunctionSet &fs, int level, Vector &out) const override
|
||||
{
|
||||
// TODO: out.length()==func.outdim()
|
||||
// TODO: dim == func.indim()
|
||||
out.zeros();
|
||||
sthread::detach_thread_group gr;
|
||||
for (int ti = 0; ti < fs.getNum(); ti++)
|
||||
gr.insert(std::make_unique<IntegrationWorker<_Tpit>>(*this, fs.getFunc(ti),
|
||||
level, ti, fs.getNum(), out));
|
||||
gr.run();
|
||||
}
|
||||
void
|
||||
integrate(const VectorFunction &func,
|
||||
int level, int tn, Vector &out) const override
|
||||
{
|
||||
VectorFunctionSet fs(func, tn);
|
||||
integrate(fs, level, out);
|
||||
}
|
||||
|
||||
/* Just for debugging. */
|
||||
void
|
||||
savePoints(const std::string &fname, int level) const
|
||||
{
|
||||
std::ofstream fd{fname, std::ios::out | std::ios::trunc};
|
||||
if (fd.fail())
|
||||
{
|
||||
// TODO: raise
|
||||
std::cerr << "Cannot open file " << fname << " for writing." << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
_Tpit beg = begin(0, 1, level);
|
||||
_Tpit end = begin(1, 1, level);
|
||||
fd << std::setprecision(12);
|
||||
for (_Tpit run = beg; run != end; ++run)
|
||||
{
|
||||
fd << std::setw(16) << run.weight();
|
||||
for (int i = 0; i < dimen(); i++)
|
||||
fd << '\t' << std::setw(16) << run.point()[i];
|
||||
fd << std::endl;
|
||||
}
|
||||
fd.close();
|
||||
}
|
||||
|
||||
_Tpit
|
||||
start(int level) const
|
||||
{
|
||||
return begin(0, 1, level);
|
||||
}
|
||||
_Tpit
|
||||
end(int level) const
|
||||
{
|
||||
return begin(1, 1, level);
|
||||
}
|
||||
protected:
|
||||
virtual _Tpit begin(int ti, int tn, int level) const = 0;
|
||||
};
|
||||
|
||||
/* This is only an interface to a precalculated data in file
|
||||
precalc_quadrature.hh which is basically C coded static data. It implements
|
||||
OneDQuadrature. The data file is supposed to define the following data:
|
||||
number of levels, array of number of points at each level, an array of
|
||||
weights and array of points. The both latter array store data level by
|
||||
level. An offset for a specific level is stored in ‘offsets’ integer
|
||||
sequence.
|
||||
|
||||
The implementing subclasses just fill the necessary data from the file, the
|
||||
rest is calculated here. */
|
||||
|
||||
class OneDPrecalcQuadrature : public OneDQuadrature
|
||||
{
|
||||
int num_levels;
|
||||
const int *num_points;
|
||||
const double *weights;
|
||||
const double *points;
|
||||
IntSequence offsets;
|
||||
public:
|
||||
OneDPrecalcQuadrature(int nlevels, const int *npoints,
|
||||
const double *wts, const double *pts)
|
||||
: num_levels(nlevels), num_points(npoints),
|
||||
weights(wts), points(pts), offsets(num_levels)
|
||||
{
|
||||
calcOffsets();
|
||||
}
|
||||
~OneDPrecalcQuadrature() override = default;
|
||||
int
|
||||
numLevels() const override
|
||||
{
|
||||
return num_levels;
|
||||
}
|
||||
int
|
||||
numPoints(int level) const override
|
||||
{
|
||||
return num_points[level-1];
|
||||
}
|
||||
double
|
||||
point(int level, int i) const override
|
||||
{
|
||||
return points[offsets[level-1]+i];
|
||||
}
|
||||
double
|
||||
weight(int level, int i) const override
|
||||
{
|
||||
return weights[offsets[level-1]+i];
|
||||
}
|
||||
protected:
|
||||
void calcOffsets();
|
||||
};
|
||||
|
||||
/* Just precalculated Gauss-Hermite quadrature. This quadrature integrates
|
||||
exactly integrals
|
||||
|
||||
+∞
|
||||
∫ xᵏe^{−x²}dx
|
||||
−∞
|
||||
|
||||
for level k.
|
||||
|
||||
Note that if pluging this one-dimensional quadrature to product or Smolyak
|
||||
rule in order to integrate a function f through normally distributed inputs,
|
||||
one has to wrap f to GaussConverterFunction and apply the product or Smolyak
|
||||
rule to the new function.
|
||||
|
||||
Check precalc_quadrature.hh for available levels. */
|
||||
|
||||
class GaussHermite : public OneDPrecalcQuadrature
|
||||
{
|
||||
public:
|
||||
GaussHermite();
|
||||
};
|
||||
|
||||
/* Just precalculated Gauss-Legendre quadrature. This quadrature integrates
|
||||
exactly integrals
|
||||
|
||||
₁
|
||||
∫ xᵏdx
|
||||
⁰
|
||||
|
||||
for level k.
|
||||
|
||||
Check precalc_quadrature.hh for available levels. */
|
||||
|
||||
class GaussLegendre : public OneDPrecalcQuadrature
|
||||
{
|
||||
public:
|
||||
GaussLegendre();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,311 +0,0 @@
|
|||
@q $Id: quadrature.hweb 2269 2008-11-23 14:33:22Z michel $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@*2 Quadrature. This is {\tt quadrature.h} file
|
||||
|
||||
This file defines an interface for one dimensional (non-nested) quadrature
|
||||
|OneDQuadrature|, and a parent for all multi-dimensional
|
||||
quadratures. This parent class |Quadrature| presents a general concept of
|
||||
quadrature, this is
|
||||
$$\int f(x){\rm d}x \approx\sum_{i=1}^N w_ix_i$$
|
||||
The class |Quadrature| just declares this concept. The concept is
|
||||
implemented by class |QuadratureImpl| which paralelizes the
|
||||
summation. All implementations therefore wishing to use the parallel
|
||||
implementation should inherit from |QuadratureImpl| and integration is
|
||||
done.
|
||||
|
||||
The integration concept relies on a point iterator, which goes through
|
||||
all $x_i$ and $w_i$ for $i=1,\ldots,N$. All the iterators must be able
|
||||
to go through only a portion of the set $i=1,\ldots,N$. This enables
|
||||
us to implement paralelism, for two threads for example, one iterator
|
||||
goes from the beginning to the (approximately) half, and the other
|
||||
goes from the half to the end.
|
||||
|
||||
Besides this concept of the general quadrature, this file defines also
|
||||
one dimensional quadrature, which is basically a scheme of points and
|
||||
weights for different levels. The class |OneDQuadrature| is a parent
|
||||
of all such objects, the classes |GaussHermite| and |GaussLegendre|
|
||||
are specific implementations for Gauss--Hermite and Gauss--Legendre
|
||||
quadratures resp.
|
||||
|
||||
@s OneDQuadrature int
|
||||
@s Quadrature int
|
||||
@s IntegrationWorker int
|
||||
@s QuadratureImpl int
|
||||
@s OneDPrecalcQuadrature int
|
||||
@s GaussHermite int
|
||||
@s GaussLegendre int
|
||||
@s NormalICDF int
|
||||
@s _Tpit int
|
||||
|
||||
@c
|
||||
#ifndef QUADRATURE_H
|
||||
#define QUADRATURE_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include "vector_function.h"
|
||||
#include "int_sequence.h"
|
||||
#include "sthread.h"
|
||||
|
||||
@<|OneDQuadrature| class declaration@>;
|
||||
@<|Quadrature| class declaration@>;
|
||||
@<|IntegrationWorker| class declaration@>;
|
||||
@<|QuadratureImpl| class declaration@>;
|
||||
@<|OneDPrecalcQuadrature| class declaration@>;
|
||||
@<|GaussHermite| class declaration@>;
|
||||
@<|GaussLegendre| class declaration@>;
|
||||
@<|NormalICDF| class declaration@>;
|
||||
|
||||
#endif
|
||||
|
||||
@ This pure virtual class represents a concept of one-dimensional
|
||||
(non-nested) quadrature. So, one dimensional quadrature must return
|
||||
number of levels, number of points in a given level, and then a point
|
||||
and a weight in a given level and given order.
|
||||
|
||||
@<|OneDQuadrature| class declaration@>=
|
||||
class OneDQuadrature {
|
||||
public:@;
|
||||
virtual ~OneDQuadrature()@+ {}
|
||||
virtual int numLevels() const =0;
|
||||
virtual int numPoints(int level) const =0;
|
||||
virtual double point(int level, int i) const =0;
|
||||
virtual double weight(int lelel, int i) const =0;
|
||||
};
|
||||
|
||||
@ This is a general concept of multidimensional quadrature. at this
|
||||
general level, we maintain only a dimension, and declare virtual
|
||||
functions for integration. The function take two forms; first takes a
|
||||
constant |VectorFunction| as an argument, creates locally
|
||||
|VectorFunctionSet| and do calculation, second one takes as an
|
||||
argument |VectorFunctionSet|.
|
||||
|
||||
Part of the interface is a method returning a number of evaluations
|
||||
for a specific level. Note two things: this assumes that the number of
|
||||
evaluations is known apriori and thus it is not applicable for
|
||||
adaptive quadratures, second for Monte Carlo type of quadrature, the
|
||||
level is a number of evaluations.
|
||||
|
||||
@<|Quadrature| class declaration@>=
|
||||
class Quadrature {
|
||||
protected:@;
|
||||
int dim;
|
||||
public:@;
|
||||
Quadrature(int d) : dim(d)@+ {}
|
||||
virtual ~Quadrature()@+ {}
|
||||
int dimen() const
|
||||
{@+ return dim;@+}
|
||||
virtual void integrate(const VectorFunction& func, int level,
|
||||
int tn, Vector& out) const =0;
|
||||
virtual void integrate(VectorFunctionSet& fs, int level, Vector& out) const =0;
|
||||
virtual int numEvals(int level) const =0;
|
||||
};
|
||||
|
||||
@ This is just an integration worker, which works over a given
|
||||
|QuadratureImpl|. It also needs the function, level, a specification
|
||||
of the subgroup of points, and output vector.
|
||||
|
||||
See |@<|QuadratureImpl| class declaration@>| for details.
|
||||
|
||||
@<|IntegrationWorker| class declaration@>=
|
||||
template <typename _Tpit>
|
||||
class QuadratureImpl;
|
||||
|
||||
template <typename _Tpit>
|
||||
class IntegrationWorker : public THREAD {
|
||||
const QuadratureImpl<_Tpit>& quad;
|
||||
VectorFunction& func;
|
||||
int level;
|
||||
int ti;
|
||||
int tn;
|
||||
Vector& outvec;
|
||||
public:@;
|
||||
IntegrationWorker(const QuadratureImpl<_Tpit>& q, VectorFunction& f, int l,
|
||||
int tii, int tnn, Vector& out)
|
||||
: quad(q), func(f), level(l), ti(tii), tn(tnn), outvec(out) @+{}
|
||||
@<|IntegrationWorker::operator()()| code@>;
|
||||
};
|
||||
|
||||
|
||||
@ This integrates the given portion of the integral. We obtain first
|
||||
and last iterators for the portion (|beg| and |end|). Then we iterate
|
||||
through the portion. and finally we add the intermediate result to the
|
||||
result |outvec|.
|
||||
|
||||
This method just everything up as it is coming. This might be imply
|
||||
large numerical errors, perhaps in future I will implement something
|
||||
smarter.
|
||||
|
||||
@<|IntegrationWorker::operator()()| code@>=
|
||||
void operator()() {
|
||||
_Tpit beg = quad.begin(ti, tn, level);
|
||||
_Tpit end = quad.begin(ti+1, tn, level);
|
||||
Vector tmpall(outvec.length());
|
||||
tmpall.zeros();
|
||||
Vector tmp(outvec.length());
|
||||
|
||||
// note that since beg came from begin, it has empty signal
|
||||
// and first evaluation gets no signal
|
||||
for (_Tpit run = beg; run != end; ++run) {
|
||||
func.eval(run.point(), run.signal(), tmp);
|
||||
tmpall.add(run.weight(), tmp);
|
||||
}
|
||||
|
||||
{
|
||||
SYNCHRO@, syn(&outvec, "IntegrationWorker");
|
||||
outvec.add(1.0, tmpall);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ This is the class which implements the integration. The class is
|
||||
templated by the iterator type. We declare a method |begin| returning
|
||||
an iterator to the beginnning of the |ti|-th portion out of total |tn|
|
||||
portions for a given level.
|
||||
|
||||
In addition, we define a method which saves all the points to a given
|
||||
file. Only for debugging purposes.
|
||||
|
||||
@<|QuadratureImpl| class declaration@>=
|
||||
template <typename _Tpit>
|
||||
class QuadratureImpl : public Quadrature {
|
||||
friend class IntegrationWorker<_Tpit>;
|
||||
public:@;
|
||||
QuadratureImpl(int d) : Quadrature(d)@+ {}
|
||||
@<|QuadratureImpl::integrate| code@>;
|
||||
void integrate(const VectorFunction& func,
|
||||
int level, int tn, Vector& out) const {
|
||||
VectorFunctionSet fs(func, tn);
|
||||
integrate(fs, level, out);
|
||||
}
|
||||
@<|Quadrature::savePoints| code@>;
|
||||
_Tpit start(int level) const
|
||||
{@+ return begin(0,1,level);@+}
|
||||
_Tpit end(int level) const
|
||||
{@+ return begin(1,1,level);@+}
|
||||
protected:@;
|
||||
virtual _Tpit begin(int ti, int tn, int level) const =0;
|
||||
};
|
||||
|
||||
@ Just fill a thread group with workes and run it.
|
||||
@<|QuadratureImpl::integrate| code@>=
|
||||
void integrate(VectorFunctionSet& fs, int level, Vector& out) const {
|
||||
// todo: out.length()==func.outdim()
|
||||
// todo: dim == func.indim()
|
||||
out.zeros();
|
||||
THREAD_GROUP@, gr;
|
||||
for (int ti = 0; ti < fs.getNum(); ti++) {
|
||||
gr.insert(new IntegrationWorker<_Tpit>(*this, fs.getFunc(ti),
|
||||
level, ti, fs.getNum(), out));
|
||||
}
|
||||
gr.run();
|
||||
}
|
||||
|
||||
|
||||
@ Just for debugging.
|
||||
@<|Quadrature::savePoints| code@>=
|
||||
void savePoints(const char* fname, int level) const
|
||||
{
|
||||
FILE* fd;
|
||||
if (NULL==(fd = fopen(fname,"w"))) {
|
||||
// todo: raise
|
||||
fprintf(stderr, "Cannot open file %s for writing.\n", fname);
|
||||
exit(1);
|
||||
}
|
||||
_Tpit beg = begin(0,1,level);
|
||||
_Tpit end = begin(1,1,level);
|
||||
for (_Tpit run = beg; run != end; ++run) {
|
||||
fprintf(fd, "%16.12g", run.weight());
|
||||
for (int i = 0; i < dimen(); i++)
|
||||
fprintf(fd, "\t%16.12g", run.point()[i]);
|
||||
fprintf(fd, "\n");
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
|
||||
@ This is only an interface to a precalculated data in file {\tt
|
||||
precalc\_quadrature.dat} which is basically C coded static data. It
|
||||
implements |OneDQuadrature|. The data file is supposed to define the
|
||||
following data: number of levels, array of number of points at each
|
||||
level, an array of weights and array of points. The both latter array
|
||||
store data level by level. An offset for a specific level is stored in
|
||||
|offsets| integer sequence.
|
||||
|
||||
The implementing subclasses just fill the necessary data from the
|
||||
file, the rest is calculated here.
|
||||
|
||||
@<|OneDPrecalcQuadrature| class declaration@>=
|
||||
class OneDPrecalcQuadrature : public OneDQuadrature {
|
||||
int num_levels;
|
||||
const int* num_points;
|
||||
const double* weights;
|
||||
const double* points;
|
||||
IntSequence offsets;
|
||||
public:@;
|
||||
OneDPrecalcQuadrature(int nlevels, const int* npoints,
|
||||
const double* wts, const double* pts)
|
||||
: num_levels(nlevels), num_points(npoints),
|
||||
weights(wts), points(pts), offsets(num_levels)
|
||||
{@+ calcOffsets();@+}
|
||||
virtual ~OneDPrecalcQuadrature()@+ {}
|
||||
int numLevels() const
|
||||
{@+ return num_levels;@+}
|
||||
int numPoints(int level) const
|
||||
{@+ return num_points[level-1];@+}
|
||||
double point(int level, int i) const
|
||||
{@+ return points[offsets[level-1]+i];@+}
|
||||
double weight(int level, int i) const
|
||||
{@+ return weights[offsets[level-1]+i];@+}
|
||||
protected:@;
|
||||
void calcOffsets();
|
||||
};
|
||||
|
||||
@ Just precalculated Gauss--Hermite quadrature. This quadrature integrates exactly integrals
|
||||
$$\int_{-\infty}^{\infty} x^ke^{-x^2}{\rm d}x$$
|
||||
for level $k$.
|
||||
|
||||
Note that if pluging this one-dimensional quadrature to product or
|
||||
Smolyak rule in order to integrate a function $f$ through normally
|
||||
distributed inputs, one has to wrap $f$ to
|
||||
|GaussConverterFunction| and apply the product or Smolyak rule to the
|
||||
new function.
|
||||
|
||||
Check {\tt precalc\_quadrature.dat} for available levels.
|
||||
|
||||
@<|GaussHermite| class declaration@>=
|
||||
class GaussHermite : public OneDPrecalcQuadrature {
|
||||
public:@;
|
||||
GaussHermite();
|
||||
};
|
||||
|
||||
@ Just precalculated Gauss--Legendre quadrature. This quadrature integrates exactly integrals
|
||||
$$\int_0^1x^k{\rm d}x$$
|
||||
for level $k$.
|
||||
|
||||
Check {\tt precalc\_quadrature.dat} for available levels.
|
||||
|
||||
@<|GaussLegendre| class declaration@>=
|
||||
class GaussLegendre : public OneDPrecalcQuadrature {
|
||||
public:@;
|
||||
GaussLegendre();
|
||||
};
|
||||
|
||||
@ This is just an inverse cummulative density function of normal
|
||||
distribution. Its only method |get| returns for a given number
|
||||
$x\in(0,1)$ a number $y$ such that $P(z<y)=x$, where the probability
|
||||
is taken over normal distribution $N(0,1)$.
|
||||
|
||||
Currently, the implementation is done by a table lookup which implies
|
||||
that the tails had to be chopped off. This further implies that Monte
|
||||
Carlo quadratures using this transformation to draw points from
|
||||
multidimensional $N(0,I)$ fail to integrate with satisfactory
|
||||
precision polynomial functions, for which the tails matter.
|
||||
|
||||
@<|NormalICDF| class declaration@>=
|
||||
class NormalICDF {
|
||||
public:@;
|
||||
static double get(double x);
|
||||
};
|
||||
|
||||
@ End of {\tt quadrature.h} file
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "quasi_mcarlo.hh"
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <array>
|
||||
|
||||
/* Here in the constructor, we have to calculate a maximum length of ‘coeff’
|
||||
array for a given ‘base’ and given maximum ‘maxn’. After allocation, we
|
||||
calculate the coefficients. */
|
||||
|
||||
RadicalInverse::RadicalInverse(int n, int b, int mxn)
|
||||
: num(n), base(b), maxn(mxn),
|
||||
coeff(static_cast<int>(floor(log(static_cast<double>(maxn))/log(static_cast<double>(b)))+2), 0)
|
||||
{
|
||||
int nr = num;
|
||||
j = -1;
|
||||
do
|
||||
{
|
||||
j++;
|
||||
coeff[j] = nr % base;
|
||||
nr = nr / base;
|
||||
}
|
||||
while (nr > 0);
|
||||
}
|
||||
|
||||
/* This evaluates the radical inverse. If there was no permutation, we have to
|
||||
calculate:
|
||||
|
||||
c₀ c₁ cⱼ
|
||||
── + ── + … + ────
|
||||
b b² bʲ⁺¹
|
||||
|
||||
which is evaluated as:
|
||||
|
||||
⎛ ⎛⎛cⱼ 1 cⱼ₋₁⎞ 1 cⱼ₋₂⎞ ⎞ 1 c₀
|
||||
⎢…⎢⎢──·─ + ────⎥·─ + ────⎥…⎥·─ + ──
|
||||
⎝ ⎝⎝ b b b ⎠ b b ⎠ ⎠ b b
|
||||
|
||||
|
||||
Now with permutation π, we have:
|
||||
|
||||
⎛ ⎛⎛π(cⱼ) 1 π(cⱼ₋₁)⎞ 1 π(cⱼ₋₂)⎞ ⎞ 1 π(c₀)
|
||||
⎢…⎢⎢─────·─ + ───────⎥·─ + ───────⎥…⎥·─ + ─────
|
||||
⎝ ⎝⎝ b b b ⎠ b b ⎠ ⎠ b b
|
||||
*/
|
||||
|
||||
double
|
||||
RadicalInverse::eval(const PermutationScheme &p) const
|
||||
{
|
||||
double res = 0;
|
||||
for (int i = j; i >= 0; i--)
|
||||
{
|
||||
int cper = p.permute(i, base, coeff[i]);
|
||||
res = (cper + res)/base;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* We just add 1 to the lowest coefficient and check for overflow with respect
|
||||
to the base. */
|
||||
void
|
||||
RadicalInverse::increase()
|
||||
{
|
||||
// TODO: raise if num+1 > maxn
|
||||
num++;
|
||||
int i = 0;
|
||||
coeff[i]++;
|
||||
while (coeff[i] == base)
|
||||
{
|
||||
coeff[i] = 0;
|
||||
coeff[++i]++;
|
||||
}
|
||||
if (i > j)
|
||||
j = i;
|
||||
}
|
||||
|
||||
/* Debug print. */
|
||||
void
|
||||
RadicalInverse::print() const
|
||||
{
|
||||
std::cout << "n=" << num << " b=" << base << " c=";
|
||||
coeff.print();
|
||||
}
|
||||
|
||||
/* Here we have the first 170 primes. This means that we are not able to
|
||||
integrate dimensions greater than 170. */
|
||||
|
||||
std::array<int, 170> HaltonSequence::primes = {
|
||||
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
|
||||
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
|
||||
73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
|
||||
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
|
||||
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
|
||||
233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
|
||||
283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
|
||||
353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
|
||||
419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
|
||||
467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
|
||||
547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
|
||||
607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
|
||||
661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
|
||||
739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
|
||||
811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
|
||||
877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
|
||||
947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013
|
||||
};
|
||||
|
||||
/* This takes first ‘dim’ primes and constructs ‘dim’ radical inverses and
|
||||
calls eval(). */
|
||||
|
||||
HaltonSequence::HaltonSequence(int n, int mxn, int dim, const PermutationScheme &p)
|
||||
: num(n), maxn(mxn), per(p), pt(dim)
|
||||
{
|
||||
// TODO: raise if dim > num_primes
|
||||
// TODO: raise if n > mxn
|
||||
for (int i = 0; i < dim; i++)
|
||||
ri.emplace_back(num, primes[i], maxn);
|
||||
eval();
|
||||
}
|
||||
|
||||
/* This calls RadicalInverse::increase() for all radical inverses and calls
|
||||
eval(). */
|
||||
|
||||
void
|
||||
HaltonSequence::increase()
|
||||
{
|
||||
for (auto & i : ri)
|
||||
i.increase();
|
||||
num++;
|
||||
if (num <= maxn)
|
||||
eval();
|
||||
}
|
||||
|
||||
/* This sets point ‘pt’ to radical inverse evaluations in each dimension. */
|
||||
void
|
||||
HaltonSequence::eval()
|
||||
{
|
||||
for (unsigned int i = 0; i < ri.size(); i++)
|
||||
pt[i] = ri[i].eval(per);
|
||||
}
|
||||
|
||||
/* Debug print. */
|
||||
void
|
||||
HaltonSequence::print() const
|
||||
{
|
||||
auto ff = std::cout.flags();
|
||||
for (const auto & i : ri)
|
||||
i.print();
|
||||
std::cout << "point=[ "
|
||||
<< std::fixed << std::setprecision(6);
|
||||
for (unsigned int i = 0; i < ri.size(); i++)
|
||||
std::cout << std::setw(7) << pt[i] << ' ';
|
||||
std::cout << ']' << std::endl;
|
||||
std::cout.flags(ff);
|
||||
}
|
||||
|
||||
qmcpit::qmcpit(const QMCSpecification &s, int n)
|
||||
: spec(s), halton{n, s.level(), s.dimen(), s.getPerScheme()},
|
||||
sig{s.dimen()}
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
qmcpit::operator==(const qmcpit &qpit) const
|
||||
{
|
||||
return &spec == &qpit.spec && halton.getNum() == qpit.halton.getNum();
|
||||
}
|
||||
|
||||
qmcpit &
|
||||
qmcpit::operator++()
|
||||
{
|
||||
halton.increase();
|
||||
return *this;
|
||||
}
|
||||
|
||||
double
|
||||
qmcpit::weight() const
|
||||
{
|
||||
return 1.0/spec.level();
|
||||
}
|
||||
|
||||
int
|
||||
WarnockPerScheme::permute(int i, int base, int c) const
|
||||
{
|
||||
return (c+i) % base;
|
||||
}
|
||||
|
||||
int
|
||||
ReversePerScheme::permute(int i, int base, int c) const
|
||||
{
|
||||
return (base-c) % base;
|
||||
}
|
|
@ -1,341 +0,0 @@
|
|||
@q $Id: quasi_mcarlo.cweb 431 2005-08-16 15:41:01Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@ This is {\tt quasi\_mcarlo.cpp} file.
|
||||
|
||||
@c
|
||||
#include "quasi_mcarlo.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@<|RadicalInverse| constructor code@>;
|
||||
@<|RadicalInverse::eval| code@>;
|
||||
@<|RadicalInverse::increase| code@>;
|
||||
@<|RadicalInverse::print| code@>;
|
||||
@<|HaltonSequence| static data@>;
|
||||
@<|HaltonSequence| constructor code@>;
|
||||
@<|HaltonSequence::operator=| code@>;
|
||||
@<|HaltonSequence::increase| code@>;
|
||||
@<|HaltonSequence::eval| code@>;
|
||||
@<|HaltonSequence::print| code@>;
|
||||
@<|qmcpit| empty constructor code@>;
|
||||
@<|qmcpit| regular constructor code@>;
|
||||
@<|qmcpit| copy constructor code@>;
|
||||
@<|qmcpit| destructor@>;
|
||||
@<|qmcpit::operator==| code@>;
|
||||
@<|qmcpit::operator=| code@>;
|
||||
@<|qmcpit::operator++| code@>;
|
||||
@<|qmcpit::weight| code@>;
|
||||
@<|qmcnpit| empty constructor code@>;
|
||||
@<|qmcnpit| regular constructor code@>;
|
||||
@<|qmcnpit| copy constructor code@>;
|
||||
@<|qmcnpit| destructor@>;
|
||||
@<|qmcnpit::operator=| code@>;
|
||||
@<|qmcnpit::operator++| code@>;
|
||||
@<|WarnockPerScheme::permute| code@>;
|
||||
@<|ReversePerScheme::permute| code@>;
|
||||
|
||||
@ Here in the constructor, we have to calculate a maximum length of
|
||||
|coeff| array for a given |base| and given maximum |maxn|. After
|
||||
allocation, we calculate the coefficients.
|
||||
|
||||
@<|RadicalInverse| constructor code@>=
|
||||
RadicalInverse::RadicalInverse(int n, int b, int mxn)
|
||||
: num(n), base(b), maxn(mxn),
|
||||
coeff((int)(floor(log((double)maxn)/log((double)b))+2), 0)
|
||||
{
|
||||
int nr = num;
|
||||
j = -1;
|
||||
do {
|
||||
j++;
|
||||
coeff[j] = nr % base;
|
||||
nr = nr / base;
|
||||
} while (nr > 0);
|
||||
}
|
||||
|
||||
@ This evaluates the radical inverse. If there was no permutation, we have to calculate
|
||||
$$
|
||||
{c_0\over b}+{c_1\over b^2}+\ldots+{c_j\over b^{j+1}}
|
||||
$$
|
||||
which is evaluated as
|
||||
$$
|
||||
\left(\ldots\left(\left({c_j\over b}\cdot{1\over b}+{c_{j-1}\over b}\right)
|
||||
\cdot{1\over b}+{c_{j-2}\over b}\right)
|
||||
\ldots\right)\cdot{1\over b}+{c_0\over b}
|
||||
$$
|
||||
Now with permutation $\pi$, we have
|
||||
$$
|
||||
\left(\ldots\left(\left({\pi(c_j)\over b}\cdot{1\over b}+
|
||||
{\pi(c_{j-1})\over b}\right)\cdot{1\over b}+
|
||||
{\pi(c_{j-2})\over b}\right)
|
||||
\ldots\right)\cdot{1\over b}+{\pi(c_0)\over b}
|
||||
$$
|
||||
|
||||
|
||||
@<|RadicalInverse::eval| code@>=
|
||||
double RadicalInverse::eval(const PermutationScheme& p) const
|
||||
{
|
||||
double res = 0;
|
||||
for (int i = j; i >= 0; i--) {
|
||||
int cper = p.permute(i, base, coeff[i]);
|
||||
res = (cper + res)/base;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ We just add 1 to the lowest coefficient and check for overflow with respect to the base.
|
||||
@<|RadicalInverse::increase| code@>=
|
||||
void RadicalInverse::increase()
|
||||
{
|
||||
// todo: raise if |num+1 > maxn|
|
||||
num++;
|
||||
int i = 0;
|
||||
coeff[i]++;
|
||||
while (coeff[i] == base) {
|
||||
coeff[i] = 0;
|
||||
coeff[++i]++;
|
||||
}
|
||||
if (i > j)
|
||||
j = i;
|
||||
}
|
||||
|
||||
@ Debug print.
|
||||
@<|RadicalInverse::print| code@>=
|
||||
void RadicalInverse::print() const
|
||||
{
|
||||
printf("n=%d b=%d c=", num, base);
|
||||
coeff.print();
|
||||
}
|
||||
|
||||
@ Here we have the first 170 primes. This means that we are not able
|
||||
to integrate dimensions greater than 170.
|
||||
|
||||
@<|HaltonSequence| static data@>=
|
||||
int HaltonSequence::num_primes = 170;
|
||||
int HaltonSequence::primes[] = {
|
||||
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
|
||||
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
|
||||
73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
|
||||
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
|
||||
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
|
||||
233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
|
||||
283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
|
||||
353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
|
||||
419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
|
||||
467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
|
||||
547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
|
||||
607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
|
||||
661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
|
||||
739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
|
||||
811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
|
||||
877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
|
||||
947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013
|
||||
};
|
||||
|
||||
|
||||
@ This takes first |dim| primes and constructs |dim| radical inverses
|
||||
and calls |eval|.
|
||||
|
||||
@<|HaltonSequence| constructor code@>=
|
||||
HaltonSequence::HaltonSequence(int n, int mxn, int dim, const PermutationScheme& p)
|
||||
: num(n), maxn(mxn), per(p), pt(dim)
|
||||
{
|
||||
// todo: raise if |dim > num_primes|
|
||||
// todo: raise if |n > mxn|
|
||||
for (int i = 0; i < dim; i++)
|
||||
ri.push_back(RadicalInverse(num, primes[i], maxn));
|
||||
eval();
|
||||
}
|
||||
|
||||
@
|
||||
@<|HaltonSequence::operator=| code@>=
|
||||
const HaltonSequence& HaltonSequence::operator=(const HaltonSequence& hs)
|
||||
{
|
||||
num = hs.num;
|
||||
maxn = hs.maxn;
|
||||
ri.clear();
|
||||
for (unsigned int i = 0; i < hs.ri.size(); i++)
|
||||
ri.push_back(RadicalInverse(hs.ri[i]));
|
||||
pt = hs.pt;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ This calls |RadicalInverse::increase| for all radical inverses and
|
||||
calls |eval|.
|
||||
|
||||
@<|HaltonSequence::increase| code@>=
|
||||
void HaltonSequence::increase()
|
||||
{
|
||||
for (unsigned int i = 0; i < ri.size(); i++)
|
||||
ri[i].increase();
|
||||
num++;
|
||||
if (num <= maxn)
|
||||
eval();
|
||||
}
|
||||
|
||||
@ This sets point |pt| to radical inverse evaluations in each dimension.
|
||||
@<|HaltonSequence::eval| code@>=
|
||||
void HaltonSequence::eval()
|
||||
{
|
||||
for (unsigned int i = 0; i < ri.size(); i++)
|
||||
pt[i] = ri[i].eval(per);
|
||||
}
|
||||
|
||||
@ Debug print.
|
||||
@<|HaltonSequence::print| code@>=
|
||||
void HaltonSequence::print() const
|
||||
{
|
||||
for (unsigned int i = 0; i < ri.size(); i++)
|
||||
ri[i].print();
|
||||
printf("point=[ ");
|
||||
for (unsigned int i = 0; i < ri.size(); i++)
|
||||
printf("%7.6f ", pt[i]);
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
@
|
||||
@<|qmcpit| empty constructor code@>=
|
||||
qmcpit::qmcpit()
|
||||
: spec(NULL), halton(NULL), sig(NULL)@+ {}
|
||||
|
||||
@
|
||||
@<|qmcpit| regular constructor code@>=
|
||||
qmcpit::qmcpit(const QMCSpecification& s, int n)
|
||||
: spec(&s), halton(new HaltonSequence(n, s.level(), s.dimen(), s.getPerScheme())),
|
||||
sig(new ParameterSignal(s.dimen()))
|
||||
{
|
||||
}
|
||||
|
||||
@
|
||||
@<|qmcpit| copy constructor code@>=
|
||||
qmcpit::qmcpit(const qmcpit& qpit)
|
||||
: spec(qpit.spec), halton(NULL), sig(NULL)
|
||||
{
|
||||
if (qpit.halton)
|
||||
halton = new HaltonSequence(*(qpit.halton));
|
||||
if (qpit.sig)
|
||||
sig = new ParameterSignal(qpit.spec->dimen());
|
||||
}
|
||||
|
||||
@
|
||||
@<|qmcpit| destructor@>=
|
||||
qmcpit::~qmcpit()
|
||||
{
|
||||
if (halton)
|
||||
delete halton;
|
||||
if (sig)
|
||||
delete sig;
|
||||
}
|
||||
|
||||
@
|
||||
@<|qmcpit::operator==| code@>=
|
||||
bool qmcpit::operator==(const qmcpit& qpit) const
|
||||
{
|
||||
return (spec == qpit.spec) &&
|
||||
((halton == NULL && qpit.halton == NULL) ||
|
||||
(halton != NULL && qpit.halton != NULL && halton->getNum() == qpit.halton->getNum()));
|
||||
}
|
||||
|
||||
@
|
||||
@<|qmcpit::operator=| code@>=
|
||||
const qmcpit& qmcpit::operator=(const qmcpit& qpit)
|
||||
{
|
||||
spec = qpit.spec;
|
||||
if (halton)
|
||||
delete halton;
|
||||
if (qpit.halton)
|
||||
halton = new HaltonSequence(*(qpit.halton));
|
||||
else
|
||||
halton = NULL;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@
|
||||
@<|qmcpit::operator++| code@>=
|
||||
qmcpit& qmcpit::operator++()
|
||||
{
|
||||
// todo: raise if |halton == null || qmcq == NULL|
|
||||
halton->increase();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@
|
||||
@<|qmcpit::weight| code@>=
|
||||
double qmcpit::weight() const
|
||||
{
|
||||
return 1.0/spec->level();
|
||||
}
|
||||
|
||||
@
|
||||
@<|qmcnpit| empty constructor code@>=
|
||||
qmcnpit::qmcnpit()
|
||||
: qmcpit(), pnt(NULL)@+ {}
|
||||
|
||||
@
|
||||
@<|qmcnpit| regular constructor code@>=
|
||||
qmcnpit::qmcnpit(const QMCSpecification& s, int n)
|
||||
: qmcpit(s, n), pnt(new Vector(s.dimen()))
|
||||
{
|
||||
}
|
||||
|
||||
@
|
||||
@<|qmcnpit| copy constructor code@>=
|
||||
qmcnpit::qmcnpit(const qmcnpit& qpit)
|
||||
: qmcpit(qpit), pnt(NULL)
|
||||
{
|
||||
if (qpit.pnt)
|
||||
pnt = new Vector(*(qpit.pnt));
|
||||
}
|
||||
|
||||
@
|
||||
@<|qmcnpit| destructor@>=
|
||||
qmcnpit::~qmcnpit()
|
||||
{
|
||||
if (pnt)
|
||||
delete pnt;
|
||||
}
|
||||
|
||||
@
|
||||
@<|qmcnpit::operator=| code@>=
|
||||
const qmcnpit& qmcnpit::operator=(const qmcnpit& qpit)
|
||||
{
|
||||
qmcpit::operator=(qpit);
|
||||
if (pnt)
|
||||
delete pnt;
|
||||
if (qpit.pnt)
|
||||
pnt = new Vector(*(qpit.pnt));
|
||||
else
|
||||
pnt = NULL;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ Here we inccrease a point in Halton sequence ant then store images
|
||||
of the points in |NormalICDF| function.
|
||||
|
||||
@<|qmcnpit::operator++| code@>=
|
||||
qmcnpit& qmcnpit::operator++()
|
||||
{
|
||||
qmcpit::operator++();
|
||||
for (int i = 0; i < halton->point().length(); i++)
|
||||
(*pnt)[i] = NormalICDF::get(halton->point()[i]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ Clear from code.
|
||||
@<|WarnockPerScheme::permute| code@>=
|
||||
int WarnockPerScheme::permute(int i, int base, int c) const
|
||||
{
|
||||
return (c+i) % base;
|
||||
}
|
||||
|
||||
@ Clear from code.
|
||||
@<|ReversePerScheme::permute| code@>=
|
||||
int ReversePerScheme::permute(int i, int base, int c) const
|
||||
{
|
||||
return (base-c) % base;
|
||||
}
|
||||
|
||||
@ End of {\tt quasi\_mcarlo.cpp} file.
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Quasi Monte Carlo quadrature.
|
||||
|
||||
/* This defines quasi Monte Carlo quadratures for cube and for a function
|
||||
multiplied by normal density. The quadrature for a cube is named
|
||||
QMCarloCubeQuadrature and integrates:
|
||||
|
||||
∫ f(x)dx
|
||||
[0,1]ⁿ
|
||||
|
||||
The quadrature for a function of normally distributed parameters is named
|
||||
QMCarloNormalQuadrature and integrates:
|
||||
|
||||
1
|
||||
──────── ∫ f(x)e^{−½xᵀx}dx
|
||||
√{(2π)ⁿ} [−∞,+∞]ⁿ
|
||||
|
||||
For a cube we define qmcpit as iterator of QMCarloCubeQuadrature, and for
|
||||
the normal density multiplied function we define qmcnpit as iterator of
|
||||
QMCarloNormalQuadrature.
|
||||
|
||||
The quasi Monte Carlo method generates low discrepancy points with equal
|
||||
weights. The one dimensional low discrepancy sequences are generated by
|
||||
RadicalInverse class, the sequences are combined for higher dimensions by
|
||||
HaltonSequence class. The Halton sequence can use a permutation scheme;
|
||||
PermutattionScheme is an abstract class for all permutaton schemes. We have
|
||||
three implementations: WarnockPerScheme, ReversePerScheme, and
|
||||
IdentityPerScheme. */
|
||||
|
||||
#ifndef QUASI_MCARLO_H
|
||||
#define QUASI_MCARLO_H
|
||||
|
||||
#include "int_sequence.hh"
|
||||
#include "quadrature.hh"
|
||||
|
||||
#include "Vector.hh"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/* This abstract class declares permute() method which permutes coefficient ‘c’
|
||||
having index of ‘i’ fro the base ‘base’ and returns the permuted coefficient
|
||||
which must be in 0,…,base−1. */
|
||||
|
||||
class PermutationScheme
|
||||
{
|
||||
public:
|
||||
PermutationScheme() = default;
|
||||
virtual ~PermutationScheme() = default;
|
||||
virtual int permute(int i, int base, int c) const = 0;
|
||||
};
|
||||
|
||||
/* This class represents an integer number ‘num’ as c₀+c₁b+c₂b²+…+cⱼbʲ, where b
|
||||
is ‘base’ and c₀,…,cⱼ is stored in ‘coeff’. The size of IntSequence coeff
|
||||
does not grow with growing ‘num’, but is fixed from the very beginning and
|
||||
is set according to supplied maximum ‘maxn’.
|
||||
|
||||
The basic method is eval() which evaluates the RadicalInverse with a given
|
||||
permutation scheme and returns the point, and increase() which increases
|
||||
‘num’ and recalculates the coefficients. */
|
||||
|
||||
class RadicalInverse
|
||||
{
|
||||
int num;
|
||||
int base;
|
||||
int maxn;
|
||||
int j;
|
||||
IntSequence coeff;
|
||||
public:
|
||||
RadicalInverse(int n, int b, int mxn);
|
||||
RadicalInverse(const RadicalInverse &ri) = default;
|
||||
RadicalInverse &operator=(const RadicalInverse &radi) = default;
|
||||
double eval(const PermutationScheme &p) const;
|
||||
void increase();
|
||||
void print() const;
|
||||
};
|
||||
|
||||
/* This is a vector of RadicalInverses, each RadicalInverse has a different
|
||||
prime as its base. The static members ‘primes’ and ‘num_primes’ define a
|
||||
precalculated array of primes. The increase() method of the class increases
|
||||
indices in all RadicalInverse’s and sets point ‘pt’ to contain the points in
|
||||
each dimension. */
|
||||
|
||||
class HaltonSequence
|
||||
{
|
||||
private:
|
||||
static std::array<int, 170> primes;
|
||||
protected:
|
||||
int num;
|
||||
int maxn;
|
||||
std::vector<RadicalInverse> ri;
|
||||
const PermutationScheme &per;
|
||||
Vector pt;
|
||||
public:
|
||||
HaltonSequence(int n, int mxn, int dim, const PermutationScheme &p);
|
||||
HaltonSequence(const HaltonSequence &hs) = default;
|
||||
HaltonSequence &operator=(const HaltonSequence &hs) = delete;
|
||||
void increase();
|
||||
const Vector &
|
||||
point() const
|
||||
{
|
||||
return pt;
|
||||
}
|
||||
const int
|
||||
getNum() const
|
||||
{
|
||||
return num;
|
||||
}
|
||||
void print() const;
|
||||
protected:
|
||||
void eval();
|
||||
};
|
||||
|
||||
/* This is a specification of quasi Monte Carlo quadrature. It consists of
|
||||
dimension ‘dim’, number of points (or level) ‘lev’, and the permutation
|
||||
scheme. This class is common to all quasi Monte Carlo classes. */
|
||||
|
||||
class QMCSpecification
|
||||
{
|
||||
protected:
|
||||
int dim;
|
||||
int lev;
|
||||
const PermutationScheme &per_scheme;
|
||||
public:
|
||||
QMCSpecification(int d, int l, const PermutationScheme &p)
|
||||
: dim(d), lev(l), per_scheme(p)
|
||||
{
|
||||
}
|
||||
virtual ~QMCSpecification() = default;
|
||||
int
|
||||
dimen() const
|
||||
{
|
||||
return dim;
|
||||
}
|
||||
int
|
||||
level() const
|
||||
{
|
||||
return lev;
|
||||
}
|
||||
const PermutationScheme &
|
||||
getPerScheme() const
|
||||
{
|
||||
return per_scheme;
|
||||
}
|
||||
};
|
||||
|
||||
/* This is an iterator for quasi Monte Carlo over a cube QMCarloCubeQuadrature.
|
||||
The iterator maintains HaltonSequence of the same dimension as given by the
|
||||
specification. An iterator can be constructed from a given number ‘n’, or by
|
||||
a copy constructor. */
|
||||
|
||||
class qmcpit
|
||||
{
|
||||
protected:
|
||||
const QMCSpecification &spec;
|
||||
HaltonSequence halton;
|
||||
ParameterSignal sig;
|
||||
public:
|
||||
qmcpit(const QMCSpecification &s, int n);
|
||||
qmcpit(const qmcpit &qpit) = default;
|
||||
virtual ~qmcpit() = default;
|
||||
bool operator==(const qmcpit &qpit) const;
|
||||
bool
|
||||
operator!=(const qmcpit &qpit) const
|
||||
{
|
||||
return !operator==(qpit);
|
||||
}
|
||||
qmcpit &operator=(const qmcpit &qpit) = delete;
|
||||
qmcpit &operator++();
|
||||
const ParameterSignal &
|
||||
signal() const
|
||||
{
|
||||
return sig;
|
||||
}
|
||||
const Vector &
|
||||
point() const
|
||||
{
|
||||
return halton.point();
|
||||
}
|
||||
double weight() const;
|
||||
void
|
||||
print() const
|
||||
{
|
||||
halton.print();
|
||||
}
|
||||
};
|
||||
|
||||
/* This is an easy declaration of quasi Monte Carlo quadrature for a cube.
|
||||
Everything important has been done in its iterator qmcpit, so we only
|
||||
inherit from general Quadrature and reimplement begin() and numEvals(). */
|
||||
|
||||
class QMCarloCubeQuadrature : public QuadratureImpl<qmcpit>, public QMCSpecification
|
||||
{
|
||||
public:
|
||||
QMCarloCubeQuadrature(int d, int l, const PermutationScheme &p)
|
||||
: QuadratureImpl<qmcpit>(d), QMCSpecification(d, l, p)
|
||||
{
|
||||
}
|
||||
~QMCarloCubeQuadrature() override = default;
|
||||
int
|
||||
numEvals(int l) const override
|
||||
{
|
||||
return l;
|
||||
}
|
||||
protected:
|
||||
qmcpit
|
||||
begin(int ti, int tn, int lev) const override
|
||||
{
|
||||
return qmcpit(*this, ti*level()/tn + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/* Declares Warnock permutation scheme. */
|
||||
class WarnockPerScheme : public PermutationScheme
|
||||
{
|
||||
public:
|
||||
int permute(int i, int base, int c) const override;
|
||||
};
|
||||
|
||||
/* Declares reverse permutation scheme. */
|
||||
class ReversePerScheme : public PermutationScheme
|
||||
{
|
||||
public:
|
||||
int permute(int i, int base, int c) const override;
|
||||
};
|
||||
|
||||
/* Declares no permutation (identity) scheme. */
|
||||
class IdentityPerScheme : public PermutationScheme
|
||||
{
|
||||
public:
|
||||
int
|
||||
permute(int i, int base, int c) const override
|
||||
{
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,286 +0,0 @@
|
|||
@q $Id: quasi_mcarlo.hweb 431 2005-08-16 15:41:01Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@*2 Quasi Monte Carlo quadrature. This is {\tt quasi\_mcarlo.h} file.
|
||||
|
||||
This defines quasi Monte Carlo quadratures for cube and for a function
|
||||
multiplied by normal density. The quadrature for a cube is named
|
||||
|QMCarloCubeQuadrature| and integrates:
|
||||
$$\int_{\langle 0,1\rangle^n}f(x){\rm d}x$$
|
||||
The quadrature for a function of normally distributed parameters is
|
||||
named |QMCarloNormalQuadrature| and integrates:
|
||||
$${1\over\sqrt{(2\pi)^n}}\int_{(-\infty,\infty)^n}f(x)e^{-{1\over 2}x^Tx}{\rm d}x$$
|
||||
|
||||
For a cube we define |qmcpit| as iterator of |QMCarloCubeQuadrature|,
|
||||
and for the normal density multiplied function we define |qmcnpit| as
|
||||
iterator of |QMCarloNormalQuadrature|.
|
||||
|
||||
The quasi Monte Carlo method generates low discrepancy points with
|
||||
equal weights. The one dimensional low discrepancy sequences are
|
||||
generated by |RadicalInverse| class, the sequences are combined for
|
||||
higher dimensions by |HaltonSequence| class. The Halton sequence can
|
||||
use a permutation scheme; |PermutattionScheme| is an abstract class
|
||||
for all permutaton schemes. We have three implementations:
|
||||
|WarnockPerScheme|, |ReversePerScheme|, and |IdentityPerScheme|.
|
||||
|
||||
@s PermutationScheme int
|
||||
@s RadicalInverse int
|
||||
@s HaltonSequence int
|
||||
@s QMCSpecification int
|
||||
@s qmcpit int
|
||||
@s QMCarloCubeQuadrature int
|
||||
@s qmcnpit int
|
||||
@s QMCarloNormalQuadrature int
|
||||
@s WarnockPerScheme int
|
||||
@s ReversePerScheme int
|
||||
@s IdentityPerScheme int
|
||||
|
||||
@c
|
||||
#ifndef QUASI_MCARLO_H
|
||||
#define QUASI_MCARLO_H
|
||||
|
||||
#include "int_sequence.h"
|
||||
#include "quadrature.h"
|
||||
|
||||
#include "Vector.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@<|PermutationScheme| class declaration@>;
|
||||
@<|RadicalInverse| class declaration@>;
|
||||
@<|HaltonSequence| class declaration@>;
|
||||
@<|QMCSpecification| class declaration@>;
|
||||
@<|qmcpit| class declaration@>;
|
||||
@<|QMCarloCubeQuadrature| class declaration@>;
|
||||
@<|qmcnpit| class declaration@>;
|
||||
@<|QMCarloNormalQuadrature| class declaration@>;
|
||||
@<|WarnockPerScheme| class declaration@>;
|
||||
@<|ReversePerScheme| class declaration@>;
|
||||
@<|IdentityPerScheme| class declaration@>;
|
||||
|
||||
#endif
|
||||
|
||||
@ This abstract class declares |permute| method which permutes
|
||||
coefficient |c| having index of |i| fro the base |base| and returns
|
||||
the permuted coefficient which must be in $0,\ldots,base-1$.
|
||||
|
||||
@<|PermutationScheme| class declaration@>=
|
||||
class PermutationScheme {
|
||||
public:@;
|
||||
PermutationScheme()@+ {}
|
||||
virtual ~PermutationScheme()@+ {}
|
||||
virtual int permute(int i, int base, int c) const =0;
|
||||
};
|
||||
|
||||
|
||||
@ This class represents an integer number |num| as
|
||||
$c_0+c_1b+c_2b^2+\ldots+c_jb^j$, where $b$ is |base| and
|
||||
$c_0,\ldots,c_j$ is stored in |coeff|. The size of |IntSequence| coeff
|
||||
does not grow with growing |num|, but is fixed from the very beginning
|
||||
and is set according to supplied maximum |maxn|.
|
||||
|
||||
The basic method is |eval| which evaluates the |RadicalInverse| with a
|
||||
given permutation scheme and returns the point, and |increase| which
|
||||
increases |num| and recalculates the coefficients.
|
||||
|
||||
@<|RadicalInverse| class declaration@>=
|
||||
class RadicalInverse {
|
||||
int num;
|
||||
int base;
|
||||
int maxn;
|
||||
int j;
|
||||
IntSequence coeff;
|
||||
public:@;
|
||||
RadicalInverse(int n, int b, int mxn);
|
||||
RadicalInverse(const RadicalInverse& ri)
|
||||
: num(ri.num), base(ri.base), maxn(ri.maxn), j(ri.j), coeff(ri.coeff)@+ {}
|
||||
const RadicalInverse& operator=(const RadicalInverse& radi)
|
||||
{
|
||||
num = radi.num; base = radi.base; maxn = radi.maxn;
|
||||
j = radi.j; coeff = radi.coeff;
|
||||
return *this;
|
||||
}
|
||||
double eval(const PermutationScheme& p) const;
|
||||
void increase();
|
||||
void print() const;
|
||||
};
|
||||
|
||||
@ This is a vector of |RadicalInverse|s, each |RadicalInverse| has a
|
||||
different prime as its base. The static members |primes| and
|
||||
|num_primes| define a precalculated array of primes. The |increase|
|
||||
method of the class increases indices in all |RadicalInverse|s and
|
||||
sets point |pt| to contain the points in each dimension.
|
||||
|
||||
@<|HaltonSequence| class declaration@>=
|
||||
class HaltonSequence {
|
||||
private:@;
|
||||
static int primes[];
|
||||
static int num_primes;
|
||||
protected:@;
|
||||
int num;
|
||||
int maxn;
|
||||
vector<RadicalInverse> ri;
|
||||
const PermutationScheme& per;
|
||||
Vector pt;
|
||||
public:@;
|
||||
HaltonSequence(int n, int mxn, int dim, const PermutationScheme& p);
|
||||
HaltonSequence(const HaltonSequence& hs)
|
||||
: num(hs.num), maxn(hs.maxn), ri(hs.ri), per(hs.per), pt(hs.pt)@+ {}
|
||||
const HaltonSequence& operator=(const HaltonSequence& hs);
|
||||
void increase();
|
||||
const Vector& point() const
|
||||
{@+ return pt;@+}
|
||||
const int getNum() const
|
||||
{@+ return num;@+}
|
||||
void print() const;
|
||||
protected:@;
|
||||
void eval();
|
||||
};
|
||||
|
||||
@ This is a specification of quasi Monte Carlo quadrature. It consists
|
||||
of dimension |dim|, number of points (or level) |lev|, and the
|
||||
permutation scheme. This class is common to all quasi Monte Carlo
|
||||
classes.
|
||||
|
||||
@<|QMCSpecification| class declaration@>=
|
||||
class QMCSpecification {
|
||||
protected:@;
|
||||
int dim;
|
||||
int lev;
|
||||
const PermutationScheme& per_scheme;
|
||||
public:@;
|
||||
QMCSpecification(int d, int l, const PermutationScheme& p)
|
||||
: dim(d), lev(l), per_scheme(p)@+ {}
|
||||
virtual ~QMCSpecification() {}
|
||||
int dimen() const
|
||||
{@+ return dim;@+}
|
||||
int level() const
|
||||
{@+ return lev;@+}
|
||||
const PermutationScheme& getPerScheme() const
|
||||
{@+ return per_scheme;@+}
|
||||
};
|
||||
|
||||
|
||||
@ This is an iterator for quasi Monte Carlo over a cube
|
||||
|QMCarloCubeQuadrature|. The iterator maintains |HaltonSequence| of
|
||||
the same dimension as given by the specification. An iterator can be
|
||||
constructed from a given number |n|, or by a copy constructor. For
|
||||
technical reasons, there is also an empty constructor; for that
|
||||
reason, every member is a pointer.
|
||||
|
||||
@<|qmcpit| class declaration@>=
|
||||
class qmcpit {
|
||||
protected:@;
|
||||
const QMCSpecification* spec;
|
||||
HaltonSequence* halton;
|
||||
ParameterSignal* sig;
|
||||
public:@;
|
||||
qmcpit();
|
||||
qmcpit(const QMCSpecification& s, int n);
|
||||
qmcpit(const qmcpit& qpit);
|
||||
~qmcpit();
|
||||
bool operator==(const qmcpit& qpit) const;
|
||||
bool operator!=(const qmcpit& qpit) const
|
||||
{@+ return ! operator==(qpit);@+}
|
||||
const qmcpit& operator=(const qmcpit& qpit);
|
||||
qmcpit& operator++();
|
||||
const ParameterSignal& signal() const
|
||||
{@+ return *sig;@+}
|
||||
const Vector& point() const
|
||||
{@+ return halton->point();@+}
|
||||
double weight() const;
|
||||
void print() const
|
||||
{@+ halton->print();@+}
|
||||
};
|
||||
|
||||
@ This is an easy declaration of quasi Monte Carlo quadrature for a
|
||||
cube. Everything important has been done in its iterator |qmcpit|, so
|
||||
we only inherit from general |Quadrature| and reimplement |begin| and
|
||||
|numEvals|.
|
||||
|
||||
@<|QMCarloCubeQuadrature| class declaration@>=
|
||||
class QMCarloCubeQuadrature : public QuadratureImpl<qmcpit>, public QMCSpecification {
|
||||
public:@;
|
||||
QMCarloCubeQuadrature(int d, int l, const PermutationScheme& p)
|
||||
: QuadratureImpl<qmcpit>(d), QMCSpecification(d, l, p)@+ {}
|
||||
virtual ~QMCarloCubeQuadrature()@+ {}
|
||||
int numEvals(int l) const
|
||||
{@+ return l;@+}
|
||||
protected:@;
|
||||
qmcpit begin(int ti, int tn, int lev) const
|
||||
{@+ return qmcpit(*this, ti*level()/tn + 1);@+}
|
||||
};
|
||||
|
||||
@ This is an iterator for |QMCarloNormalQuadrature|. It is equivalent
|
||||
to an iterator for quasi Monte Carlo cube quadrature but a point. The
|
||||
point is obtained from a point of |QMCarloCubeQuadrature| by a
|
||||
transformation $\langle
|
||||
0,1\rangle\rightarrow\langle-\infty,\infty\rangle$ aplied to all
|
||||
dimensions. The transformation yields a normal distribution from a
|
||||
uniform distribution on $\langle0,1\rangle$. It is in fact
|
||||
|NormalICDF|.
|
||||
|
||||
@<|qmcnpit| class declaration@>=
|
||||
class qmcnpit : public qmcpit {
|
||||
protected:@;
|
||||
Vector* pnt;
|
||||
public:@;
|
||||
qmcnpit();
|
||||
qmcnpit(const QMCSpecification& spec, int n);
|
||||
qmcnpit(const qmcnpit& qpit);
|
||||
~qmcnpit();
|
||||
bool operator==(const qmcnpit& qpit) const
|
||||
{@+ return qmcpit::operator==(qpit);@+}
|
||||
bool operator!=(const qmcnpit& qpit) const
|
||||
{@+ return ! operator==(qpit);@+}
|
||||
const qmcnpit& operator=(const qmcnpit& qpit);
|
||||
qmcnpit& operator++();
|
||||
const ParameterSignal& signal() const
|
||||
{@+ return *sig;@+}
|
||||
const Vector& point() const
|
||||
{@+ return *pnt;@+}
|
||||
void print() const
|
||||
{@+ halton->print();pnt->print();@+}
|
||||
};
|
||||
|
||||
@ This is an easy declaration of quasi Monte Carlo quadrature for a
|
||||
cube. Everything important has been done in its iterator |qmcnpit|, so
|
||||
we only inherit from general |Quadrature| and reimplement |begin| and
|
||||
|numEvals|.
|
||||
|
||||
@<|QMCarloNormalQuadrature| class declaration@>=
|
||||
class QMCarloNormalQuadrature : public QuadratureImpl<qmcnpit>, public QMCSpecification {
|
||||
public:@;
|
||||
QMCarloNormalQuadrature(int d, int l, const PermutationScheme& p)
|
||||
: QuadratureImpl<qmcnpit>(d), QMCSpecification(d, l, p)@+ {}
|
||||
virtual ~QMCarloNormalQuadrature()@+ {}
|
||||
int numEvals(int l) const
|
||||
{@+ return l;@+}
|
||||
protected:@;
|
||||
qmcnpit begin(int ti, int tn, int lev) const
|
||||
{@+ return qmcnpit(*this, ti*level()/tn + 1);@+}
|
||||
};
|
||||
|
||||
@ Declares Warnock permutation scheme.
|
||||
@<|WarnockPerScheme| class declaration@>=
|
||||
class WarnockPerScheme : public PermutationScheme {
|
||||
public:@;
|
||||
int permute(int i, int base, int c) const;
|
||||
};
|
||||
|
||||
@ Declares reverse permutation scheme.
|
||||
@<|ReversePerScheme| class declaration@>=
|
||||
class ReversePerScheme : public PermutationScheme {
|
||||
public:@;
|
||||
int permute(int i, int base, int c) const;
|
||||
};
|
||||
|
||||
@ Declares no permutation (identity) scheme.
|
||||
@<|IdentityPerScheme| class declaration@>=
|
||||
class IdentityPerScheme : public PermutationScheme {
|
||||
public:@;
|
||||
int permute(int i, int base, int c) const
|
||||
{@+ return c;@+}
|
||||
};
|
||||
|
||||
@ End of {\tt quasi\_mcarlo.h} file
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "smolyak.hh"
|
||||
#include "symmetry.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
/* This constructs a beginning of ‘isum’ summand in ‘smolq’. We must be careful
|
||||
here, since ‘isum’ can be past-the-end, so no reference to vectors in
|
||||
‘smolq’ by ‘isum’ must be done in this case. */
|
||||
|
||||
smolpit::smolpit(const SmolyakQuadrature &q, unsigned int isum)
|
||||
: smolq(q), isummand(isum),
|
||||
jseq(q.dimen(), 0),
|
||||
sig{q.dimen()},
|
||||
p{q.dimen()}
|
||||
{
|
||||
if (isummand < q.numSummands())
|
||||
setPointAndWeight();
|
||||
}
|
||||
|
||||
bool
|
||||
smolpit::operator==(const smolpit &spit) const
|
||||
{
|
||||
return &smolq == &spit.smolq && isummand == spit.isummand && jseq == spit.jseq;
|
||||
}
|
||||
|
||||
/* We first try to increase index within the current summand. If we are at
|
||||
maximum, we go to a subsequent summand. Note that in this case all indices
|
||||
in ‘jseq’ will be zero, so no change is needed. */
|
||||
|
||||
smolpit &
|
||||
smolpit::operator++()
|
||||
{
|
||||
const IntSequence &levpts = smolq.levpoints[isummand];
|
||||
int i = smolq.dimen()-1;
|
||||
jseq[i]++;
|
||||
while (i >= 0 && jseq[i] == levpts[i])
|
||||
{
|
||||
jseq[i] = 0;
|
||||
i--;
|
||||
if (i >= 0)
|
||||
jseq[i]++;
|
||||
}
|
||||
sig.signalAfter(std::max(i, 0));
|
||||
|
||||
if (i < 0)
|
||||
isummand++;
|
||||
|
||||
if (isummand < smolq.numSummands())
|
||||
setPointAndWeight();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Here we set the point coordinates according to ‘jseq’ and
|
||||
‘isummand’. Also the weight is set here. */
|
||||
|
||||
void
|
||||
smolpit::setPointAndWeight()
|
||||
{
|
||||
// todo: raise if isummand ≥ smolq.numSummands()
|
||||
int l = smolq.level;
|
||||
int d = smolq.dimen();
|
||||
int sumk = (smolq.levels[isummand]).sum();
|
||||
int m1exp = l + d - sumk - 1;
|
||||
w = (2*(m1exp/2) == m1exp) ? 1.0 : -1.0;
|
||||
w *= PascalTriangle::noverk(d-1, sumk-l);
|
||||
for (int i = 0; i < d; i++)
|
||||
{
|
||||
int ki = (smolq.levels[isummand])[i];
|
||||
p[i] = (smolq.uquad).point(ki, jseq[i]);
|
||||
w *= (smolq.uquad).weight(ki, jseq[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Debug print. */
|
||||
void
|
||||
smolpit::print() const
|
||||
{
|
||||
auto ff = std::cout.flags();
|
||||
std::cout << "isum=" << std::left << std::setw(3) << isummand << std::right << ": [";
|
||||
for (int i = 0; i < smolq.dimen(); i++)
|
||||
std::cout << std::setw(2) << (smolq.levels[isummand])[i] << ' ';
|
||||
std::cout << "] j=[";
|
||||
for (int i = 0; i < smolq.dimen(); i++)
|
||||
std::cout << std::setw(2) << jseq[i] << ' ';
|
||||
std::cout << std::showpos << std::fixed << std::setprecision(3)
|
||||
<< "] " << std::setw(4) << w << "*(";
|
||||
for (int i = 0; i < smolq.dimen()-1; i++)
|
||||
std::cout << std::setw(4) << p[i] << ' ';
|
||||
std::cout << std::setw(4) << p[smolq.dimen()-1] << ')' << std::endl;
|
||||
std::cout.flags(ff);
|
||||
}
|
||||
|
||||
/* Here is the constructor of SmolyakQuadrature. We have to setup ‘levels’,
|
||||
‘levpoints’ and ‘cumevals’. We have to go through all d-dimensional
|
||||
sequences k, such that l≤|k|≤l+d−1 and all kᵢ are positive integers. This is
|
||||
equivalent to going through all k such that l−d≤|k|≤l−1 and all kᵢ are
|
||||
non-negative integers. This is equivalent to going through d+1 dimensional
|
||||
sequences (k,x) such that |(k,x)|=l−1 and x=0,…,d−1. The resulting sequence
|
||||
of positive integers is obtained by adding 1 to all kᵢ. */
|
||||
|
||||
SmolyakQuadrature::SmolyakQuadrature(int d, int l, const OneDQuadrature &uq)
|
||||
: QuadratureImpl<smolpit>(d), level(l), uquad(uq)
|
||||
{
|
||||
// TODO: check l>1, l≥d
|
||||
// TODO: check l≥uquad.miLevel(), l≤uquad.maxLevel()
|
||||
int cum = 0;
|
||||
for (const auto &si : SymmetrySet(l-1, d+1))
|
||||
{
|
||||
if (si[d] <= d-1)
|
||||
{
|
||||
IntSequence lev(si, 0, d);
|
||||
lev.add(1);
|
||||
levels.push_back(lev);
|
||||
IntSequence levpts(d);
|
||||
for (int i = 0; i < d; i++)
|
||||
levpts[i] = uquad.numPoints(lev[i]);
|
||||
levpoints.push_back(levpts);
|
||||
cum += levpts.mult();
|
||||
cumevals.push_back(cum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Here we return a number of evalutions of the quadrature for the given level.
|
||||
If the given level is the current one, we simply return the maximum
|
||||
cumulative number of evaluations. Otherwise we call costly
|
||||
calcNumEvaluations() method. */
|
||||
|
||||
int
|
||||
SmolyakQuadrature::numEvals(int l) const
|
||||
{
|
||||
if (l != level)
|
||||
return calcNumEvaluations(l);
|
||||
else
|
||||
return cumevals[numSummands()-1];
|
||||
}
|
||||
|
||||
/* This divides all the evaluations to ‘tn’ approximately equal groups, and
|
||||
returns the beginning of the specified group ‘ti’. The granularity of
|
||||
divisions are summands as listed by ‘levels’. */
|
||||
|
||||
smolpit
|
||||
SmolyakQuadrature::begin(int ti, int tn, int l) const
|
||||
{
|
||||
// TODO: raise is level≠l
|
||||
if (ti == tn)
|
||||
return smolpit(*this, numSummands());
|
||||
|
||||
int totevals = cumevals[numSummands()-1];
|
||||
int evals = (totevals*ti)/tn;
|
||||
unsigned int isum = 0;
|
||||
while (isum+1 < numSummands() && cumevals[isum+1] < evals)
|
||||
isum++;
|
||||
return smolpit(*this, isum);
|
||||
}
|
||||
|
||||
/* This is the same in a structure as SmolyakQuadrature constructor. We have to
|
||||
go through all summands and calculate a number of evaluations in each
|
||||
summand. */
|
||||
|
||||
int
|
||||
SmolyakQuadrature::calcNumEvaluations(int lev) const
|
||||
{
|
||||
int cum = 0;
|
||||
for (const auto &si : SymmetrySet(lev-1, dim+1))
|
||||
{
|
||||
if (si[dim] <= dim-1)
|
||||
{
|
||||
IntSequence lev(si, 0, dim);
|
||||
lev.add(1);
|
||||
IntSequence levpts(dim);
|
||||
for (int i = 0; i < dim; i++)
|
||||
levpts[i] = uquad.numPoints(lev[i]);
|
||||
cum += levpts.mult();
|
||||
}
|
||||
}
|
||||
return cum;
|
||||
}
|
||||
|
||||
/* This returns a maximum level such that the number of evaluations is less
|
||||
than the given number. */
|
||||
|
||||
void
|
||||
SmolyakQuadrature::designLevelForEvals(int max_evals, int &lev, int &evals) const
|
||||
{
|
||||
int last_evals;
|
||||
evals = 1;
|
||||
lev = 1;
|
||||
do
|
||||
{
|
||||
lev++;
|
||||
last_evals = evals;
|
||||
evals = calcNumEvaluations(lev);
|
||||
}
|
||||
while (lev < uquad.numLevels() && evals <= max_evals);
|
||||
lev--;
|
||||
evals = last_evals;
|
||||
}
|
|
@ -1,294 +0,0 @@
|
|||
@q $Id: smolyak.cweb 1208 2007-03-19 21:33:12Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@ This is {\tt smolyak.cpp} file.
|
||||
|
||||
@c
|
||||
#include "smolyak.h"
|
||||
#include "symmetry.h"
|
||||
|
||||
@<|smolpit| empty constructor@>;
|
||||
@<|smolpit| regular constructor@>;
|
||||
@<|smolpit| copy constructor@>;
|
||||
@<|smolpit| destructor@>;
|
||||
@<|smolpit::operator==| code@>;
|
||||
@<|smolpit::operator=| code@>;
|
||||
@<|smolpit::operator++| code@>;
|
||||
@<|smolpit::setPointAndWeight| code@>;
|
||||
@<|smolpit::print| code@>;
|
||||
@<|SmolyakQuadrature| constructor@>;
|
||||
@<|SmolyakQuadrature::numEvals| code@>;
|
||||
@<|SmolyakQuadrature::begin| code@>;
|
||||
@<|SmolyakQuadrature::calcNumEvaluations| code@>;
|
||||
@<|SmolyakQuadrature::designLevelForEvals| code@>;
|
||||
|
||||
@
|
||||
@<|smolpit| empty constructor@>=
|
||||
smolpit::smolpit()
|
||||
: smolq(NULL), isummand(0), jseq(NULL), sig(NULL), p(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ This constructs a beginning of |isum| summand in |smolq|. We must be
|
||||
careful here, since |isum| can be past-the-end, so no reference to
|
||||
vectors in |smolq| by |isum| must be done in this case.
|
||||
|
||||
@<|smolpit| regular constructor@>=
|
||||
smolpit::smolpit(const SmolyakQuadrature& q, unsigned int isum)
|
||||
: smolq(&q), isummand(isum), jseq(new IntSequence(q.dimen(), 0)),
|
||||
sig(new ParameterSignal(q.dimen())), p(new Vector(q.dimen()))
|
||||
{
|
||||
if (isummand < q.numSummands()) {
|
||||
setPointAndWeight();
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|smolpit| copy constructor@>=
|
||||
smolpit::smolpit(const smolpit& spit)
|
||||
: smolq(spit.smolq), isummand(spit.isummand), w(spit.w)
|
||||
{
|
||||
if (spit.jseq)
|
||||
jseq = new IntSequence(*(spit.jseq));
|
||||
else
|
||||
jseq = NULL;
|
||||
if (spit.sig)
|
||||
sig = new ParameterSignal(*(spit.sig));
|
||||
else
|
||||
sig = NULL;
|
||||
if (spit.p)
|
||||
p = new Vector(*(spit.p));
|
||||
else
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
@
|
||||
@<|smolpit| destructor@>=
|
||||
smolpit::~smolpit()
|
||||
{
|
||||
if (jseq)
|
||||
delete jseq;
|
||||
if (sig)
|
||||
delete sig;
|
||||
if (p)
|
||||
delete p;
|
||||
}
|
||||
|
||||
@
|
||||
@<|smolpit::operator==| code@>=
|
||||
bool smolpit::operator==(const smolpit& spit) const
|
||||
{
|
||||
bool ret = true;
|
||||
ret = ret & smolq == spit.smolq;
|
||||
ret = ret & isummand == spit.isummand;
|
||||
ret = ret & ((jseq==NULL && spit.jseq==NULL) ||
|
||||
(jseq!=NULL && spit.jseq!=NULL && *jseq == *(spit.jseq)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@
|
||||
@<|smolpit::operator=| code@>=
|
||||
const smolpit& smolpit::operator=(const smolpit& spit)
|
||||
{
|
||||
smolq = spit.smolq;
|
||||
isummand = spit.isummand;
|
||||
w = spit.w;
|
||||
|
||||
if (jseq)
|
||||
delete jseq;
|
||||
if (sig)
|
||||
delete sig;
|
||||
if (p)
|
||||
delete p;
|
||||
|
||||
if (spit.jseq)
|
||||
jseq = new IntSequence(*(spit.jseq));
|
||||
else
|
||||
jseq = NULL;
|
||||
if (spit.sig)
|
||||
sig = new ParameterSignal(*(spit.sig));
|
||||
else
|
||||
sig = NULL;
|
||||
if (spit.p)
|
||||
p = new Vector(*(spit.p));
|
||||
else
|
||||
p = NULL;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ We first try to increase index within the current summand. If we are
|
||||
at maximum, we go to a subsequent summand. Note that in this case all
|
||||
indices in |jseq| will be zero, so no change is needed.
|
||||
|
||||
@<|smolpit::operator++| code@>=
|
||||
smolpit& smolpit::operator++()
|
||||
{
|
||||
// todo: throw if |smolq==NULL| or |jseq==NULL| or |sig==NULL|
|
||||
const IntSequence& levpts = smolq->levpoints[isummand];
|
||||
int i = smolq->dimen()-1;
|
||||
(*jseq)[i]++;
|
||||
while (i >= 0 && (*jseq)[i] == levpts[i]) {
|
||||
(*jseq)[i] = 0;
|
||||
i--;
|
||||
if (i >= 0)
|
||||
(*jseq)[i]++;
|
||||
}
|
||||
sig->signalAfter(std::max(i,0));
|
||||
|
||||
if (i < 0)
|
||||
isummand++;
|
||||
|
||||
if (isummand < smolq->numSummands())
|
||||
setPointAndWeight();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@ Here we set the point coordinates according to |jseq| and
|
||||
|isummand|. Also the weight is set here.
|
||||
|
||||
@<|smolpit::setPointAndWeight| code@>=
|
||||
void smolpit::setPointAndWeight()
|
||||
{
|
||||
// todo: raise if |smolq==NULL| or |jseq==NULL| or |sig==NULL| or
|
||||
// |p==NULL| or |isummand>=smolq->numSummands()|
|
||||
int l = smolq->level;
|
||||
int d = smolq->dimen();
|
||||
int sumk = (smolq->levels[isummand]).sum();
|
||||
int m1exp = l + d - sumk - 1;
|
||||
w = (2*(m1exp/2)==m1exp)? 1.0 : -1.0;
|
||||
w *= smolq->psc.noverk(d-1, sumk-l);
|
||||
for (int i = 0; i < d; i++) {
|
||||
int ki = (smolq->levels[isummand])[i];
|
||||
(*p)[i] = (smolq->uquad).point(ki, (*jseq)[i]);
|
||||
w *= (smolq->uquad).weight(ki, (*jseq)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ Debug print.
|
||||
@<|smolpit::print| code@>=
|
||||
void smolpit::print() const
|
||||
{
|
||||
printf("isum=%-3d: [", isummand);
|
||||
for (int i = 0; i < smolq->dimen(); i++)
|
||||
printf("%2d ", (smolq->levels[isummand])[i]);
|
||||
printf("] j=[");
|
||||
for (int i = 0; i < smolq->dimen(); i++)
|
||||
printf("%2d ", (*jseq)[i]);
|
||||
printf("] %+4.3f*(",w);
|
||||
for (int i = 0; i < smolq->dimen()-1; i++)
|
||||
printf("%+4.3f ", (*p)[i]);
|
||||
printf("%+4.3f)\n",(*p)[smolq->dimen()-1]);
|
||||
}
|
||||
|
||||
@ Here is the constructor of |SmolyakQuadrature|. We have to setup
|
||||
|levels|, |levpoints| and |cumevals|. We have to go through all
|
||||
$d$-dimensional sequences $k$, such that $l\leq \vert k\vert\leq
|
||||
l+d-1$ and all $k_i$ are positive integers. This is equivalent to
|
||||
going through all $k$ such that $l-d\leq\vert k\vert\leq l-1$ and all
|
||||
$k_i$ are non-negative integers. This is equivalent to going through
|
||||
$d+1$ dimensional sequences $(k,x)$ such that $\vert(k,x)\vert =l-1$
|
||||
and $x=0,\ldots,d-1$. The resulting sequence of positive integers is
|
||||
obtained by adding $1$ to all $k_i$.
|
||||
|
||||
@<|SmolyakQuadrature| constructor@>=
|
||||
SmolyakQuadrature::SmolyakQuadrature(int d, int l, const OneDQuadrature& uq)
|
||||
: QuadratureImpl<smolpit>(d), level(l), uquad(uq), psc(d-1,d-1)
|
||||
{
|
||||
// todo: check |l>1|, |l>=d|
|
||||
// todo: check |l>=uquad.miLevel()|, |l<=uquad.maxLevel()|
|
||||
int cum = 0;
|
||||
SymmetrySet ss(l-1, d+1);
|
||||
for (symiterator si(ss); !si.isEnd(); ++si) {
|
||||
if ((*si)[d] <= d-1) {
|
||||
IntSequence lev((const IntSequence&)*si, 0, d);
|
||||
lev.add(1);
|
||||
levels.push_back(lev);
|
||||
IntSequence levpts(d);
|
||||
for (int i = 0; i < d; i++)
|
||||
levpts[i] = uquad.numPoints(lev[i]);
|
||||
levpoints.push_back(levpts);
|
||||
cum += levpts.mult();
|
||||
cumevals.push_back(cum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ Here we return a number of evalutions of the quadrature for the
|
||||
given level. If the given level is the current one, we simply return
|
||||
the maximum cumulative number of evaluations. Otherwise we call costly
|
||||
|calcNumEvaluations| method.
|
||||
|
||||
@<|SmolyakQuadrature::numEvals| code@>=
|
||||
int SmolyakQuadrature::numEvals(int l) const
|
||||
{
|
||||
if (l != level)
|
||||
return calcNumEvaluations(l);
|
||||
else
|
||||
return cumevals[numSummands()-1];
|
||||
}
|
||||
|
||||
|
||||
@ This divides all the evaluations to |tn| approximately equal groups,
|
||||
and returns the beginning of the specified group |ti|. The granularity
|
||||
of divisions are summands as listed by |levels|.
|
||||
|
||||
@<|SmolyakQuadrature::begin| code@>=
|
||||
smolpit SmolyakQuadrature::begin(int ti, int tn, int l) const
|
||||
{
|
||||
// todo: raise is |level!=l|
|
||||
if (ti == tn)
|
||||
return smolpit(*this, numSummands());
|
||||
|
||||
int totevals = cumevals[numSummands()-1];
|
||||
int evals = (totevals*ti)/tn;
|
||||
unsigned int isum = 0;
|
||||
while (isum+1 < numSummands() && cumevals[isum+1] < evals)
|
||||
isum++;
|
||||
return smolpit(*this, isum);
|
||||
}
|
||||
|
||||
@ This is the same in a structure as |@<|SmolyakQuadrature| constructor@>|.
|
||||
We have to go through all summands and calculate
|
||||
a number of evaluations in each summand.
|
||||
|
||||
@<|SmolyakQuadrature::calcNumEvaluations| code@>=
|
||||
int SmolyakQuadrature::calcNumEvaluations(int lev) const
|
||||
{
|
||||
int cum = 0;
|
||||
SymmetrySet ss(lev-1, dim+1);
|
||||
for (symiterator si(ss); !si.isEnd(); ++si) {
|
||||
if ((*si)[dim] <= dim-1) {
|
||||
IntSequence lev((const IntSequence&)*si, 0, dim);
|
||||
lev.add(1);
|
||||
IntSequence levpts(dim);
|
||||
for (int i = 0; i < dim; i++)
|
||||
levpts[i] = uquad.numPoints(lev[i]);
|
||||
cum += levpts.mult();
|
||||
}
|
||||
}
|
||||
return cum;
|
||||
}
|
||||
|
||||
@ This returns a maximum level such that the number of evaluations is
|
||||
less than the given number.
|
||||
|
||||
@<|SmolyakQuadrature::designLevelForEvals| code@>=
|
||||
void SmolyakQuadrature::designLevelForEvals(int max_evals, int& lev, int& evals) const
|
||||
{
|
||||
int last_evals;
|
||||
evals = 1;
|
||||
lev = 1;
|
||||
do {
|
||||
lev++;
|
||||
last_evals = evals;
|
||||
evals = calcNumEvaluations(lev);
|
||||
} while (lev < uquad.numLevels() && evals <= max_evals);
|
||||
lev--;
|
||||
evals = last_evals;
|
||||
}
|
||||
|
||||
|
||||
@ End of {\tt smolyak.cpp} file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Smolyak quadrature.
|
||||
|
||||
/* This file defines Smolyak (sparse grid) multidimensional quadrature for
|
||||
non-nested underlying one dimensional quadrature. Let Q¹ₗ denote the one
|
||||
dimensional quadrature of l level. Let nₗ denote a number of points in the l
|
||||
level. Than the Smolyak quadrature can be defined as
|
||||
|
||||
⎛ d−1 ⎞
|
||||
Qᵈf = ∑ (−1)^{l+d−|k|−1} ⎢ ⎥ (Q¹_k₁⊗…⊗Q¹_{k_d})f
|
||||
l≤|k|≤l+d−1 ⎝|k|−l⎠
|
||||
|
||||
where d is the dimension, k is d-dimensional sequence of integers, and |k|
|
||||
denotes the sum of the sequence.
|
||||
|
||||
Here we define smolpit as Smolyak iterator and SmolyakQuadrature. */
|
||||
|
||||
#ifndef SMOLYAK_H
|
||||
#define SMOLYAK_H
|
||||
|
||||
#include "int_sequence.hh"
|
||||
#include "tl_static.hh"
|
||||
#include "vector_function.hh"
|
||||
#include "quadrature.hh"
|
||||
#include "pascal_triangle.hh"
|
||||
|
||||
/* Here we define the Smolyak point iterator. The Smolyak formula can be broken
|
||||
to a sum of product quadratures with various combinations of levels. The
|
||||
iterator follows this pattern. It maintains an index to a summand and then a
|
||||
point coordinates within the summand (product quadrature). The array of
|
||||
summands to which the ‘isummand’ points is maintained by the
|
||||
SmolyakQuadrature class to which the object knows the pointer ‘smolq’.
|
||||
|
||||
We provide a constructor which points to the beginning of the given summand.
|
||||
This constructor is used in SmolyakQuadrature::begin() method which
|
||||
approximately divideds all the iterators to subsets of equal size. */
|
||||
|
||||
class SmolyakQuadrature;
|
||||
|
||||
class smolpit
|
||||
{
|
||||
protected:
|
||||
const SmolyakQuadrature &smolq;
|
||||
unsigned int isummand{0};
|
||||
IntSequence jseq;
|
||||
ParameterSignal sig;
|
||||
Vector p;
|
||||
double w;
|
||||
public:
|
||||
smolpit(const SmolyakQuadrature &q, unsigned int isum);
|
||||
smolpit(const smolpit &spit) = default;
|
||||
~smolpit() = default;
|
||||
bool operator==(const smolpit &spit) const;
|
||||
bool
|
||||
operator!=(const smolpit &spit) const
|
||||
{
|
||||
return !operator==(spit);
|
||||
}
|
||||
smolpit &operator=(const smolpit &spit) = delete;
|
||||
smolpit &operator++();
|
||||
const ParameterSignal &
|
||||
signal() const
|
||||
{
|
||||
return sig;
|
||||
}
|
||||
const Vector &
|
||||
point() const
|
||||
{
|
||||
return p;
|
||||
}
|
||||
double
|
||||
weight() const
|
||||
{
|
||||
return w;
|
||||
}
|
||||
void print() const;
|
||||
protected:
|
||||
void setPointAndWeight();
|
||||
};
|
||||
|
||||
/* Here we define the class SmolyakQuadrature. It maintains an array of
|
||||
summands of the Smolyak quadrature formula:
|
||||
|
||||
⎛ d−1 ⎞
|
||||
∑ (−1)^{l+d−|k|−1} ⎢ ⎥ (Q¹_k₁⊗…⊗Q¹_{k_d})f
|
||||
l≤|k|≤l+d−1 ⎝|k|−l⎠
|
||||
|
||||
Each summand is fully specified by sequence k. The summands are here
|
||||
represented (besides k) also by sequence of number of points in each level
|
||||
selected by k, and also by a cummulative number of evaluations. The latter
|
||||
two are added only for conveniency.
|
||||
|
||||
The summands in the code are given by ‘levels’, which is a vector of
|
||||
k sequences, further by ‘levpoints’ which is a vector of sequences
|
||||
of nuber of points in each level, and by ‘cumevals’ which is the
|
||||
cumulative number of points, this is:
|
||||
|
||||
d
|
||||
∑ ∏ n_kᵢ
|
||||
ᵏ ⁱ⁼¹
|
||||
|
||||
where the sum is done through all k before the current.
|
||||
|
||||
The ‘levels’ and ‘levpoints’ vectors are used by smolpit. */
|
||||
|
||||
class SmolyakQuadrature : public QuadratureImpl<smolpit>
|
||||
{
|
||||
friend class smolpit;
|
||||
int level;
|
||||
const OneDQuadrature &uquad;
|
||||
std::vector<IntSequence> levels;
|
||||
std::vector<IntSequence> levpoints;
|
||||
std::vector<int> cumevals;
|
||||
public:
|
||||
SmolyakQuadrature(int d, int l, const OneDQuadrature &uq);
|
||||
~SmolyakQuadrature() override = default;
|
||||
int numEvals(int level) const override;
|
||||
void designLevelForEvals(int max_eval, int &lev, int &evals) const;
|
||||
protected:
|
||||
smolpit begin(int ti, int tn, int level) const override;
|
||||
unsigned int
|
||||
numSummands() const
|
||||
{
|
||||
return levels.size();
|
||||
}
|
||||
private:
|
||||
int calcNumEvaluations(int level) const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,123 +0,0 @@
|
|||
@q $Id: smolyak.hweb 431 2005-08-16 15:41:01Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@*2 Smolyak quadrature. This is {\tt smolyak.h} file
|
||||
|
||||
This file defines Smolyak (sparse grid) multidimensional quadrature
|
||||
for non-nested underlying one dimensional quadrature. Let $Q^1_l$ denote
|
||||
the one dimensional quadrature of $l$ level. Let $n_l$ denote a
|
||||
number of points in the $l$ level. Than the Smolyak quadrature can be
|
||||
defined as
|
||||
$$Q^df=\sum_{l\leq\vert k\vert\leq l+d-1}(-1)^{l+d-\vert k\vert-1}\left(\matrix{d-1\cr
|
||||
\vert k\vert-l}\right)(Q_{k_1}^1\otimes\ldots\otimes Q_{k_d}^1)f,$$
|
||||
where $d$ is the dimension, $k$ is $d$-dimensional sequence of
|
||||
integers, and $\vert k\vert$ denotes a sum of the sequence.
|
||||
|
||||
Here we define |smolpit| as Smolyak iterator and |SmolyakQuadrature|.
|
||||
|
||||
@s smolpit int
|
||||
@s SmolyakQuadrature int
|
||||
@s PascalTriangle int
|
||||
@s SymmetrySet int
|
||||
@s symiterator int
|
||||
|
||||
@c
|
||||
#ifndef SMOLYAK_H
|
||||
#define SMOLYAK_H
|
||||
|
||||
#include "int_sequence.h"
|
||||
#include "tl_static.h"
|
||||
#include "vector_function.h"
|
||||
#include "quadrature.h"
|
||||
|
||||
@<|smolpit| class declaration@>;
|
||||
@<|SmolyakQuadrature| class declaration@>;
|
||||
|
||||
#endif
|
||||
|
||||
@ Here we define the Smolyak point iterator. The Smolyak formula can
|
||||
be broken to a sum of product quadratures with various combinations of
|
||||
levels. The iterator follows this pattern. It maintains an index to a
|
||||
summand and then a point coordinates within the summand (product
|
||||
quadrature). The array of summands to which the |isummand| points is
|
||||
maintained by the |SmolyakQuadrature| class to which the object knows
|
||||
the pointer |smolq|.
|
||||
|
||||
We provide a constructor which points to the beginning of the given
|
||||
summand. This constructor is used in |SmolyakQuadrature::begin| method
|
||||
which approximately divideds all the iterators to subsets of equal
|
||||
size.
|
||||
|
||||
@<|smolpit| class declaration@>=
|
||||
class SmolyakQuadrature;
|
||||
|
||||
class smolpit {
|
||||
protected:@;
|
||||
const SmolyakQuadrature* smolq;
|
||||
unsigned int isummand;
|
||||
IntSequence* jseq;
|
||||
ParameterSignal* sig;
|
||||
Vector* p;
|
||||
double w;
|
||||
public:@;
|
||||
smolpit();
|
||||
smolpit(const SmolyakQuadrature& q, unsigned int isum);
|
||||
smolpit(const smolpit& spit);
|
||||
~smolpit();
|
||||
bool operator==(const smolpit& spit) const;
|
||||
bool operator!=(const smolpit& spit) const
|
||||
{@+ return ! operator==(spit);@+}
|
||||
const smolpit& operator=(const smolpit& spit);
|
||||
smolpit& operator++();
|
||||
const ParameterSignal& signal() const
|
||||
{@+ return *sig;@+}
|
||||
const Vector& point() const
|
||||
{@+ return *p;@+}
|
||||
double weight() const
|
||||
{@+ return w;@+}
|
||||
void print() const;
|
||||
protected:@;
|
||||
void setPointAndWeight();
|
||||
};
|
||||
|
||||
@ Here we define the class |SmolyakQuadrature|. It maintains an array
|
||||
of summands of the Smolyak quadrature formula:
|
||||
$$\sum_{l\leq\vert k\vert\leq l+d-1}(-1)^{l+d-\vert
|
||||
k\vert-1}\left(\matrix{d-1\cr
|
||||
\vert k\vert-l}\right)(Q_{k_1}^1\otimes\ldots\otimes Q_{k_d}^1)f$$
|
||||
Each summand is fully specified by sequence $k$. The summands are here
|
||||
represented (besides $k$) also by sequence of number of points in each
|
||||
level selected by $k$, and also by a cummulative number of
|
||||
evaluations. The latter two are added only for conveniency.
|
||||
|
||||
The summands in the code are given by |levels|, which is a vector of
|
||||
$k$ sequences, further by |levpoints| which is a vector of sequences
|
||||
of nuber of points in each level, and by |cumevals| which is the
|
||||
cumulative number of points, this is $\sum_k\prod_{i=1}^dn_{k_i}$,
|
||||
where the sum is done through all $k$ before the current.
|
||||
|
||||
The |levels| and |levpoints| vectors are used by |smolpit|.
|
||||
|
||||
@<|SmolyakQuadrature| class declaration@>=
|
||||
class SmolyakQuadrature : public QuadratureImpl<smolpit> {
|
||||
friend class smolpit;
|
||||
int level;
|
||||
const OneDQuadrature& uquad;
|
||||
vector<IntSequence> levels;
|
||||
vector<IntSequence> levpoints;
|
||||
vector<int> cumevals;
|
||||
PascalTriangle psc;
|
||||
public:@;
|
||||
SmolyakQuadrature(int d, int l, const OneDQuadrature& uq);
|
||||
virtual ~SmolyakQuadrature()@+ {}
|
||||
virtual int numEvals(int level) const;
|
||||
void designLevelForEvals(int max_eval, int& lev, int& evals) const;
|
||||
protected:@;
|
||||
smolpit begin(int ti, int tn, int level) const;
|
||||
unsigned int numSummands() const
|
||||
{@+ return levels.size();@+}
|
||||
private:@;
|
||||
int calcNumEvaluations(int level) const;
|
||||
};
|
||||
|
||||
@ End of {\tt smolyak.h} file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "vector_function.hh"
|
||||
|
||||
#include <dynlapack.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
/* Just an easy constructor of sequence of booleans defaulting to change
|
||||
everywhere. */
|
||||
|
||||
ParameterSignal::ParameterSignal(int n)
|
||||
: data(n, true)
|
||||
{
|
||||
}
|
||||
|
||||
/* This sets ‘false’ (no change) before a given parameter, and ‘true’ (change)
|
||||
after the given parameter (including). */
|
||||
|
||||
void
|
||||
ParameterSignal::signalAfter(int l)
|
||||
{
|
||||
for (size_t i = 0; i < std::min(static_cast<size_t>(l), data.size()); i++)
|
||||
data[i] = false;
|
||||
for (size_t i = l; i < data.size(); i++)
|
||||
data[i] = true;
|
||||
}
|
||||
|
||||
/* This constructs a function set hardcopying also the first. */
|
||||
VectorFunctionSet::VectorFunctionSet(const VectorFunction &f, int n)
|
||||
: funcs(n)
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
func_copies.push_back(f.clone());
|
||||
funcs[i] = func_copies.back().get();
|
||||
}
|
||||
}
|
||||
|
||||
/* This constructs a function set with shallow copy in the first and hard
|
||||
copies in others. */
|
||||
VectorFunctionSet::VectorFunctionSet(VectorFunction &f, int n)
|
||||
: funcs(n)
|
||||
{
|
||||
if (n > 0)
|
||||
funcs[0] = &f;
|
||||
for (int i = 1; i < n; i++)
|
||||
{
|
||||
func_copies.push_back(f.clone());
|
||||
funcs[i] = func_copies.back().get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Here we construct the object from the given function f and given
|
||||
variance-covariance matrix Σ=vcov. The matrix A is calculated as lower
|
||||
triangular and yields Σ=AAᵀ. */
|
||||
|
||||
GaussConverterFunction::GaussConverterFunction(VectorFunction &f, const GeneralMatrix &vcov)
|
||||
: VectorFunction(f), func(&f), A(vcov.nrows(), vcov.nrows()),
|
||||
multiplier(calcMultiplier())
|
||||
{
|
||||
// TODO: raise if A.nrows() ≠ indim()
|
||||
calcCholeskyFactor(vcov);
|
||||
}
|
||||
|
||||
GaussConverterFunction::GaussConverterFunction(std::unique_ptr<VectorFunction> f, const GeneralMatrix &vcov)
|
||||
: VectorFunction(*f), func_storage{move(f)}, func{func_storage.get()}, A(vcov.nrows(), vcov.nrows()),
|
||||
multiplier(calcMultiplier())
|
||||
{
|
||||
// TODO: raise if A.nrows() ≠ indim()
|
||||
calcCholeskyFactor(vcov);
|
||||
}
|
||||
|
||||
GaussConverterFunction::GaussConverterFunction(const GaussConverterFunction &f)
|
||||
: VectorFunction(f), func_storage{f.func->clone()}, func{func_storage.get()}, A(f.A),
|
||||
multiplier(f.multiplier)
|
||||
{
|
||||
}
|
||||
|
||||
/* Here we evaluate the function
|
||||
|
||||
g(y) = 1/√(πⁿ) f(√2·Ay).
|
||||
|
||||
Since the matrix A is lower triangular, the change signal for the function f
|
||||
will look like (0,…,0,1,…,1) where the first 1 is in the same position as
|
||||
the first change in the given signal ‘sig’ of the input y=point. */
|
||||
|
||||
void
|
||||
GaussConverterFunction::eval(const Vector &point, const ParameterSignal &sig, Vector &out)
|
||||
{
|
||||
ParameterSignal s(sig);
|
||||
int i = 0;
|
||||
while (i < indim() && !sig[i])
|
||||
i++;
|
||||
s.signalAfter(i);
|
||||
|
||||
Vector x(indim());
|
||||
x.zeros();
|
||||
A.multaVec(x, point);
|
||||
x.mult(sqrt(2.0));
|
||||
|
||||
func->eval(x, s, out);
|
||||
|
||||
out.mult(multiplier);
|
||||
}
|
||||
|
||||
/* This returns 1/√(πⁿ). */
|
||||
|
||||
double
|
||||
GaussConverterFunction::calcMultiplier() const
|
||||
{
|
||||
return sqrt(pow(M_PI, -1*indim()));
|
||||
}
|
||||
|
||||
void
|
||||
GaussConverterFunction::calcCholeskyFactor(const GeneralMatrix &vcov)
|
||||
{
|
||||
A = vcov;
|
||||
|
||||
lapack_int rows = A.nrows(), lda = A.getLD();
|
||||
for (int i = 0; i < rows; i++)
|
||||
for (int j = i+1; j < rows; j++)
|
||||
A.get(i, j) = 0.0;
|
||||
|
||||
lapack_int info;
|
||||
dpotrf("L", &rows, A.base(), &lda, &info);
|
||||
// TODO: raise if info≠1
|
||||
}
|
|
@ -1,190 +0,0 @@
|
|||
@q $Id: vector_function.cweb 431 2005-08-16 15:41:01Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@ This is {\tt vector\_function.cpp} file
|
||||
|
||||
@c
|
||||
|
||||
#include "vector_function.h"
|
||||
|
||||
#include <dynlapack.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#define __CROSS_COMPILATION__
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW64__
|
||||
#define __CROSS_COMPILATION__
|
||||
#endif
|
||||
|
||||
#ifdef __CROSS_COMPILATION__
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
@<|ParameterSignal| constructor code@>;
|
||||
@<|ParameterSignal| copy constructor code@>;
|
||||
@<|ParameterSignal::signalAfter| code@>;
|
||||
@<|VectorFunctionSet| constructor 1 code@>;
|
||||
@<|VectorFunctionSet| constructor 2 code@>;
|
||||
@<|VectorFunctionSet| destructor code@>;
|
||||
@<|GaussConverterFunction| constructor code 1@>;
|
||||
@<|GaussConverterFunction| constructor code 2@>;
|
||||
@<|GaussConverterFunction| copy constructor code@>;
|
||||
@<|GaussConverterFunction::eval| code@>;
|
||||
@<|GaussConverterFunction::multiplier| code@>;
|
||||
@<|GaussConverterFunction::calcCholeskyFactor| code@>;
|
||||
|
||||
@ Just an easy constructor of sequence of booleans defaulting to
|
||||
change everywhere.
|
||||
|
||||
@<|ParameterSignal| constructor code@>=
|
||||
ParameterSignal::ParameterSignal(int n)
|
||||
: data(new bool[n]), num(n)
|
||||
{
|
||||
for (int i = 0; i < num; i++)
|
||||
data[i] = true;
|
||||
}
|
||||
|
||||
@
|
||||
@<|ParameterSignal| copy constructor code@>=
|
||||
ParameterSignal::ParameterSignal(const ParameterSignal& sig)
|
||||
: data(new bool[sig.num]), num(sig.num)
|
||||
{
|
||||
memcpy(data, sig.data, num);
|
||||
}
|
||||
|
||||
@ This sets |false| (no change) before a given parameter, and |true|
|
||||
(change) after the given parameter (including).
|
||||
|
||||
@<|ParameterSignal::signalAfter| code@>=
|
||||
void ParameterSignal::signalAfter(int l)
|
||||
{
|
||||
for (int i = 0; i < std::min(l,num); i++)
|
||||
data[i] = false;
|
||||
for (int i = l; i < num; i++)
|
||||
data[i] = true;
|
||||
}
|
||||
|
||||
@ This constructs a function set hardcopying also the first.
|
||||
@<|VectorFunctionSet| constructor 1 code@>=
|
||||
VectorFunctionSet::VectorFunctionSet(const VectorFunction& f, int n)
|
||||
: funcs(n), first_shallow(false)
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
funcs[i] = f.clone();
|
||||
}
|
||||
|
||||
@ This constructs a function set with shallow copy in the first and
|
||||
hard copies in others.
|
||||
|
||||
@<|VectorFunctionSet| constructor 2 code@>=
|
||||
VectorFunctionSet::VectorFunctionSet(VectorFunction& f, int n)
|
||||
: funcs(n), first_shallow(true)
|
||||
{
|
||||
if (n > 0)
|
||||
funcs[0] = &f;
|
||||
for (int i = 1; i < n; i++)
|
||||
funcs[i] = f.clone();
|
||||
}
|
||||
|
||||
@ This deletes the functions. The first is deleted only if it was not
|
||||
a shallow copy.
|
||||
|
||||
@<|VectorFunctionSet| destructor code@>=
|
||||
VectorFunctionSet::~VectorFunctionSet()
|
||||
{
|
||||
unsigned int start = first_shallow ? 1 : 0;
|
||||
for (unsigned int i = start; i < funcs.size(); i++)
|
||||
delete funcs[i];
|
||||
}
|
||||
|
||||
@ Here we construct the object from the given function $f$ and given
|
||||
variance-covariance matrix $\Sigma=$|vcov|. The matrix $A$ is
|
||||
calculated as lower triangular and yields $\Sigma=AA^T$.
|
||||
|
||||
@<|GaussConverterFunction| constructor code 1@>=
|
||||
GaussConverterFunction::GaussConverterFunction(VectorFunction& f, const GeneralMatrix& vcov)
|
||||
: VectorFunction(f), func(&f), delete_flag(false), A(vcov.numRows(), vcov.numRows()),
|
||||
multiplier(calcMultiplier())
|
||||
{
|
||||
// todo: raise if |A.numRows() != indim()|
|
||||
calcCholeskyFactor(vcov);
|
||||
}
|
||||
|
||||
@ Here we construct the object in the same way, however we mark the
|
||||
function as to be deleted.
|
||||
|
||||
@<|GaussConverterFunction| constructor code 2@>=
|
||||
GaussConverterFunction::GaussConverterFunction(VectorFunction* f, const GeneralMatrix& vcov)
|
||||
: VectorFunction(*f), func(f), delete_flag(true), A(vcov.numRows(), vcov.numRows()),
|
||||
multiplier(calcMultiplier())
|
||||
{
|
||||
// todo: raise if |A.numRows() != indim()|
|
||||
calcCholeskyFactor(vcov);
|
||||
}
|
||||
|
||||
|
||||
@
|
||||
@<|GaussConverterFunction| copy constructor code@>=
|
||||
GaussConverterFunction::GaussConverterFunction(const GaussConverterFunction& f)
|
||||
: VectorFunction(f), func(f.func->clone()), delete_flag(true), A(f.A),
|
||||
multiplier(f.multiplier)
|
||||
{
|
||||
}
|
||||
|
||||
@ Here we evaluate the function
|
||||
$g(y)={1\over\sqrt{\pi^n}}f\left(\sqrt{2}Ay\right)$. Since the matrix $A$ is lower
|
||||
triangular, the change signal for the function $f$ will look like
|
||||
$(0,\ldots,0,1,\ldots,1)$ where the first $1$ is in the same position
|
||||
as the first change in the given signal |sig| of the input
|
||||
$y=$|point|.
|
||||
|
||||
@<|GaussConverterFunction::eval| code@>=
|
||||
void GaussConverterFunction::eval(const Vector& point, const ParameterSignal& sig, Vector& out)
|
||||
{
|
||||
ParameterSignal s(sig);
|
||||
int i = 0;
|
||||
while (i < indim() && !sig[i])
|
||||
i++;
|
||||
s.signalAfter(i);
|
||||
|
||||
Vector x(indim());
|
||||
x.zeros();
|
||||
A.multaVec(x, point);
|
||||
x.mult(sqrt(2.0));
|
||||
|
||||
func->eval(x, s, out);
|
||||
|
||||
out.mult(multiplier);
|
||||
}
|
||||
|
||||
@ This returns $1\over\sqrt{\pi^n}$.
|
||||
@<|GaussConverterFunction::multiplier| code@>=
|
||||
double GaussConverterFunction::calcMultiplier() const
|
||||
{
|
||||
return sqrt(pow(M_PI, -1*indim()));
|
||||
}
|
||||
|
||||
@
|
||||
@<|GaussConverterFunction::calcCholeskyFactor| code@>=
|
||||
void GaussConverterFunction::calcCholeskyFactor(const GeneralMatrix& vcov)
|
||||
{
|
||||
A = vcov;
|
||||
|
||||
lapack_int rows = A.numRows();
|
||||
for (int i = 0; i < rows; i++)
|
||||
for (int j = i+1; j < rows; j++)
|
||||
A.get(i,j) = 0.0;
|
||||
|
||||
lapack_int info;
|
||||
dpotrf("L", &rows, A.base(), &rows, &info);
|
||||
// todo: raise if |info!=1|
|
||||
}
|
||||
|
||||
|
||||
@ End of {\tt vector\_function.cpp} file
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Vector function.
|
||||
|
||||
/* This file defines interface for functions taking a vector as an input and
|
||||
returning a vector (with a different size) as an output. We are also
|
||||
introducing a parameter signalling; it is a boolean vector which tracks
|
||||
parameters which were changed from the previous call. The VectorFunction
|
||||
implementation can exploit this information and evaluate the function more
|
||||
efficiently. The information can be completely ignored.
|
||||
|
||||
From the signalling reason, and from other reasons, the function evaluation
|
||||
is not const. */
|
||||
|
||||
#ifndef VECTOR_FUNCTION_H
|
||||
#define VECTOR_FUNCTION_H
|
||||
|
||||
#include "Vector.hh"
|
||||
#include "GeneralMatrix.hh"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
/* This is a simple class representing a vector of booleans. The items night be
|
||||
retrieved or changed, or can be set ‘true’ after some point. This is useful
|
||||
when we multiply the vector with lower triangular matrix.
|
||||
|
||||
‘true’ means that a parameter was changed. */
|
||||
|
||||
class ParameterSignal
|
||||
{
|
||||
protected:
|
||||
std::vector<bool> data;
|
||||
public:
|
||||
ParameterSignal(int n);
|
||||
ParameterSignal(const ParameterSignal &sig) = default;
|
||||
~ParameterSignal() = default;
|
||||
void signalAfter(int l);
|
||||
bool
|
||||
operator[](int i) const
|
||||
{
|
||||
return data[i];
|
||||
}
|
||||
std::vector<bool>::reference
|
||||
operator[](int i)
|
||||
{
|
||||
return data[i];
|
||||
}
|
||||
};
|
||||
|
||||
/* This is the abstract class for vector function. At this level of abstraction
|
||||
we only need to know size of input vector and a size of output vector.
|
||||
|
||||
The important thing here is a clone method, we will need to make hard copies
|
||||
of vector functions since the evaluations are not const. The hardcopies
|
||||
apply for parallelization. */
|
||||
|
||||
class VectorFunction
|
||||
{
|
||||
protected:
|
||||
int in_dim;
|
||||
int out_dim;
|
||||
public:
|
||||
VectorFunction(int idim, int odim)
|
||||
: in_dim(idim), out_dim(odim)
|
||||
{
|
||||
}
|
||||
VectorFunction(const VectorFunction &func) = default;
|
||||
virtual ~VectorFunction() = default;
|
||||
virtual std::unique_ptr<VectorFunction> clone() const = 0;
|
||||
virtual void eval(const Vector &point, const ParameterSignal &sig, Vector &out) = 0;
|
||||
int
|
||||
indim() const
|
||||
{
|
||||
return in_dim;
|
||||
}
|
||||
int
|
||||
outdim() const
|
||||
{
|
||||
return out_dim;
|
||||
}
|
||||
};
|
||||
|
||||
/* This makes ‘n’ copies of VectorFunction. The first constructor make exactly
|
||||
‘n’ new copies, the second constructor copies only the pointer to the first
|
||||
and others are hard (real) copies.
|
||||
|
||||
The class is useful for making a given number of copies at once, and this
|
||||
set can be reused many times if we need mupliple copis of the function (for
|
||||
example for paralelizing the code). */
|
||||
|
||||
class VectorFunctionSet
|
||||
{
|
||||
private:
|
||||
// Stores the hard copies made by the class
|
||||
std::vector<std::unique_ptr<VectorFunction>> func_copies;
|
||||
protected:
|
||||
std::vector<VectorFunction *> funcs;
|
||||
public:
|
||||
VectorFunctionSet(const VectorFunction &f, int n);
|
||||
VectorFunctionSet(VectorFunction &f, int n);
|
||||
~VectorFunctionSet() = default;
|
||||
VectorFunction &
|
||||
getFunc(int i)
|
||||
{
|
||||
return *(funcs[i]);
|
||||
}
|
||||
int
|
||||
getNum() const
|
||||
{
|
||||
return funcs.size();
|
||||
}
|
||||
};
|
||||
|
||||
/* This class wraps another VectorFunction to allow integration of a function
|
||||
through normally distributed inputs. Namely, if one wants to integrate
|
||||
|
||||
1
|
||||
─────────── ∫ f(x)e^{−½xᵀ|Σ|⁻¹x}dx
|
||||
√{(2π)ⁿ|Σ|}
|
||||
|
||||
then if we write Σ=AAᵀ and x=√2·Ay, we get integral
|
||||
|
||||
1 1
|
||||
─────────── ∫ f(√2·Ay)e^{−½yᵀy} √(2ⁿ)|A|dy = ───── ∫ f(√2·Ay)e^{−½yᵀy}dy
|
||||
√{(2π)ⁿ|Σ|} √(πⁿ)
|
||||
|
||||
which means that a given function f we have to wrap to yield a function
|
||||
|
||||
g(y) = 1/√(πⁿ) f(√2·Ay).
|
||||
|
||||
This is exactly what this class is doing. This transformation is useful
|
||||
since the Gauss-Hermite points and weights are defined for weighting
|
||||
function e^{−y²}, so this transformation allows using Gauss-Hermite
|
||||
quadratures seemlessly in a context of integration through normally
|
||||
distributed inputs.
|
||||
|
||||
The class maintains a pointer to the function f. When the object is
|
||||
constructed by the first constructor, the f is assumed to be owned by the
|
||||
caller. If the object of this class is copied, then f is copied and hence
|
||||
stored in a std::unique_ptr. The second constructor takes a smart pointer to
|
||||
the function and in that case the class takes ownership of f. */
|
||||
|
||||
class GaussConverterFunction : public VectorFunction
|
||||
{
|
||||
private:
|
||||
std::unique_ptr<VectorFunction> func_storage;
|
||||
protected:
|
||||
VectorFunction *func;
|
||||
GeneralMatrix A;
|
||||
double multiplier;
|
||||
public:
|
||||
GaussConverterFunction(VectorFunction &f, const GeneralMatrix &vcov);
|
||||
GaussConverterFunction(std::unique_ptr<VectorFunction> f, const GeneralMatrix &vcov);
|
||||
GaussConverterFunction(const GaussConverterFunction &f);
|
||||
~GaussConverterFunction() override = default;
|
||||
std::unique_ptr<VectorFunction>
|
||||
clone() const override
|
||||
{
|
||||
return std::make_unique<GaussConverterFunction>(*this);
|
||||
}
|
||||
void eval(const Vector &point, const ParameterSignal &sig, Vector &out) override;
|
||||
private:
|
||||
double calcMultiplier() const;
|
||||
void calcCholeskyFactor(const GeneralMatrix &vcov);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,156 +0,0 @@
|
|||
@q $Id: vector_function.hweb 431 2005-08-16 15:41:01Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@*2 Vector function. This is {\tt vector\_function.h} file
|
||||
|
||||
This file defines interface for functions taking a vector as an input
|
||||
and returning a vector (with a different size) as an output. We are
|
||||
also introducing a parameter signalling; it is a boolean vector which
|
||||
tracks parameters which were changed from the previous call. The
|
||||
|VectorFunction| implementation can exploit this information and
|
||||
evaluate the function more efficiently. The information can be
|
||||
completely ignored.
|
||||
|
||||
From the signalling reason, and from other reasons, the function
|
||||
evaluation is not |const|.
|
||||
|
||||
@s ParameterSignal int
|
||||
@s VectorFunction int
|
||||
@s VectorFunctionSet int
|
||||
@s GaussConverterFunction int
|
||||
|
||||
@c
|
||||
#ifndef VECTOR_FUNCTION_H
|
||||
#define VECTOR_FUNCTION_H
|
||||
|
||||
#include "Vector.h"
|
||||
#include "GeneralMatrix.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@<|ParameterSignal| class declaration@>;
|
||||
@<|VectorFunction| class declaration@>;
|
||||
@<|VectorFunctionSet| class declaration@>;
|
||||
@<|GaussConverterFunction| class declaration@>;
|
||||
|
||||
#endif
|
||||
|
||||
@ This is a simple class representing a vector of booleans. The items
|
||||
night be retrieved or changed, or can be set |true| after some
|
||||
point. This is useful when we multiply the vector with lower
|
||||
triangular matrix.
|
||||
|
||||
|true| means that a parameter was changed.
|
||||
|
||||
@<|ParameterSignal| class declaration@>=
|
||||
class ParameterSignal {
|
||||
protected:@;
|
||||
bool* data;
|
||||
int num;
|
||||
public:@;
|
||||
ParameterSignal(int n);
|
||||
ParameterSignal(const ParameterSignal& sig);
|
||||
~ParameterSignal()
|
||||
{@+ delete [] data;@+}
|
||||
void signalAfter(int l);
|
||||
const bool& operator[](int i) const
|
||||
{@+ return data[i];@+}
|
||||
bool& operator[](int i)
|
||||
{@+ return data[i];@+}
|
||||
};
|
||||
|
||||
@ This is the abstract class for vector function. At this level of
|
||||
abstraction we only need to know size of input vector and a size of
|
||||
output vector.
|
||||
|
||||
The important thing here is a clone method, we will need to make hard
|
||||
copies of vector functions since the evaluations are not |const|. The
|
||||
hardcopies apply for parallelization.
|
||||
|
||||
@<|VectorFunction| class declaration@>=
|
||||
class VectorFunction {
|
||||
protected:@;
|
||||
int in_dim;
|
||||
int out_dim;
|
||||
public:@;
|
||||
VectorFunction(int idim, int odim)
|
||||
: in_dim(idim), out_dim(odim)@+ {}
|
||||
VectorFunction(const VectorFunction& func)
|
||||
: in_dim(func.in_dim), out_dim(func.out_dim)@+ {}
|
||||
virtual ~VectorFunction()@+ {}
|
||||
virtual VectorFunction* clone() const =0;
|
||||
virtual void eval(const Vector& point, const ParameterSignal& sig, Vector& out) =0;
|
||||
int indim() const
|
||||
{@+ return in_dim;@+}
|
||||
int outdim() const
|
||||
{@+ return out_dim;@+}
|
||||
};
|
||||
|
||||
@ This makes |n| copies of |VectorFunction|. The first constructor
|
||||
make exactly |n| new copies, the second constructor copies only the
|
||||
pointer to the first and others are hard (real) copies.
|
||||
|
||||
The class is useful for making a given number of copies at once, and
|
||||
this set can be reused many times if we need mupliple copis of the
|
||||
function (for example for paralelizing the code).
|
||||
|
||||
@<|VectorFunctionSet| class declaration@>=
|
||||
class VectorFunctionSet {
|
||||
protected:@;
|
||||
std::vector<VectorFunction*> funcs;
|
||||
bool first_shallow;
|
||||
public:@;
|
||||
VectorFunctionSet(const VectorFunction& f, int n);
|
||||
VectorFunctionSet(VectorFunction& f, int n);
|
||||
~VectorFunctionSet();
|
||||
VectorFunction& getFunc(int i)
|
||||
{@+ return *(funcs[i]);@+}
|
||||
int getNum() const
|
||||
{@+ return funcs.size(); @+}
|
||||
};
|
||||
|
||||
@ This class wraps another |VectorFunction| to allow integration of a
|
||||
function through normally distributed inputs. Namely, if one wants to
|
||||
integrate
|
||||
$${1\over\sqrt{(2\pi)^n\vert\Sigma\vert}}\int f(x)e^{-{1\over2}x^T\Sigma^{-1}x}{\rm d}x$$
|
||||
then if we write $\Sigma=AA^T$ and $x=\sqrt{2}Ay$, we get integral
|
||||
$${1\over\sqrt{(2\pi)^n\vert\Sigma\vert}}
|
||||
\int f\left(\sqrt{2}Ay\right)e^{-y^Ty}\sqrt{2^n}\vert A\vert{\rm d}y=
|
||||
{1\over\sqrt{\pi^n}}\int f\left(\sqrt{2}Ay\right)e^{-y^Ty}{\rm d}y,$$
|
||||
which means that a given function $f$ we have to wrap to yield a function
|
||||
$$g(y)={1\over\sqrt{\pi^n}}f\left(\sqrt{2}Ay\right).$$
|
||||
This is exactly what this class is doing. This transformation is
|
||||
useful since the Gauss--Hermite points and weights are defined for
|
||||
weighting function $e^{-y^2}$, so this transformation allows using
|
||||
Gauss--Hermite quadratures seemlessly in a context of integration through
|
||||
normally distributed inputs.
|
||||
|
||||
The class maintains a pointer to the function $f$. When the object is
|
||||
constructed by the first constructor, the $f$ is not copied. If the
|
||||
object of this class is copied, then $f$ is copied and we need to
|
||||
remember to destroy it in the desctructor; hence |delete_flag|. The
|
||||
second constructor takes a pointer to the function and differs from
|
||||
the first only by setting |delete_flag| to |true|.
|
||||
|
||||
@<|GaussConverterFunction| class declaration@>=
|
||||
class GaussConverterFunction : public VectorFunction {
|
||||
protected:@;
|
||||
VectorFunction* func;
|
||||
bool delete_flag;
|
||||
GeneralMatrix A;
|
||||
double multiplier;
|
||||
public:@;
|
||||
GaussConverterFunction(VectorFunction& f, const GeneralMatrix& vcov);
|
||||
GaussConverterFunction(VectorFunction* f, const GeneralMatrix& vcov);
|
||||
GaussConverterFunction(const GaussConverterFunction& f);
|
||||
virtual ~GaussConverterFunction()
|
||||
{@+ if (delete_flag) delete func; @+}
|
||||
virtual VectorFunction* clone() const
|
||||
{@+ return new GaussConverterFunction(*this);@+}
|
||||
virtual void eval(const Vector& point, const ParameterSignal& sig, Vector& out);
|
||||
private:@;
|
||||
double calcMultiplier() const;
|
||||
void calcCholeskyFactor(const GeneralMatrix& vcov);
|
||||
};
|
||||
|
||||
@ End of {\tt vector\_function.h} file
|
|
@ -1,6 +1,6 @@
|
|||
noinst_PROGRAMS = quadrature-points
|
||||
|
||||
quadrature_points_SOURCES = quadrature-points.cpp
|
||||
quadrature_points_CPPFLAGS = -I../.. -I../../sylv/cc -I../../integ/cc -I../../tl/cc
|
||||
quadrature_points_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
|
||||
quadrature_points_LDADD = ../cc/libinteg.a ../../tl/cc/libtl.a ../../parser/cc/libparser.a ../../sylv/cc/libsylv.a ../../utils/cc/libutils.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(PTHREAD_LIBS)
|
||||
quadrature_points_SOURCES = quadrature-points.cc
|
||||
quadrature_points_CPPFLAGS = -I../.. -I../../sylv/cc -I../../integ/cc -I../../tl/cc -I../../utils/cc
|
||||
quadrature_points_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
|
||||
quadrature_points_LDADD = ../cc/libinteg.a ../../tl/cc/libtl.a ../../parser/cc/libparser.a ../../sylv/cc/libsylv.a ../../utils/cc/libutils.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS)
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* Copyright © 2008-2011 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "parser/cc/matrix_parser.hh"
|
||||
#include "utils/cc/exception.hh"
|
||||
#include "sylv/cc/GeneralMatrix.hh"
|
||||
#include "sylv/cc/Vector.hh"
|
||||
#include "sylv/cc/SymSchurDecomp.hh"
|
||||
#include "sylv/cc/SylvException.hh"
|
||||
#include "integ/cc/quadrature.hh"
|
||||
#include "integ/cc/smolyak.hh"
|
||||
#include "integ/cc/product.hh"
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
struct QuadParams
|
||||
{
|
||||
std::string outname;
|
||||
std::string vcovname;
|
||||
int max_level{3};
|
||||
double discard_weight{0.0};
|
||||
QuadParams(int argc, char **argv);
|
||||
void check_consistency() const;
|
||||
private:
|
||||
enum class opt {max_level, discard_weight, vcov};
|
||||
};
|
||||
|
||||
QuadParams::QuadParams(int argc, char **argv)
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
// Print the help and exit
|
||||
std::cerr << "Usage: " << argv[0] << " [--max-level INTEGER] [--discard-weight FLOAT] [--vcov FILENAME] OUTPUT_FILENAME" << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
outname = argv[argc-1];
|
||||
argc--;
|
||||
|
||||
struct option const opts [] = {
|
||||
{"max-level", required_argument, nullptr, static_cast<int>(opt::max_level)},
|
||||
{"discard-weight", required_argument, nullptr, static_cast<int>(opt::discard_weight)},
|
||||
{"vcov", required_argument, nullptr, static_cast<int>(opt::vcov)},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
};
|
||||
|
||||
int ret;
|
||||
int index;
|
||||
while (-1 != (ret = getopt_long(argc, argv, "", opts, &index)))
|
||||
{
|
||||
if (ret == '?')
|
||||
{
|
||||
std::cerr << "Unknown option, ignored\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (static_cast<opt>(ret))
|
||||
{
|
||||
case opt::max_level:
|
||||
try
|
||||
{
|
||||
max_level = std::stoi(optarg);
|
||||
}
|
||||
catch (const std::invalid_argument &e)
|
||||
{
|
||||
std::cerr << "Couldn't parse integer " << optarg << ", ignored" << std::endl;
|
||||
}
|
||||
break;
|
||||
case opt::discard_weight:
|
||||
try
|
||||
{
|
||||
discard_weight = std::stod(optarg);
|
||||
}
|
||||
catch (const std::invalid_argument &e)
|
||||
{
|
||||
std::cerr << "Couldn't parse float " << optarg << ", ignored" << std::endl;
|
||||
}
|
||||
break;
|
||||
case opt::vcov:
|
||||
vcovname = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
check_consistency();
|
||||
}
|
||||
|
||||
void
|
||||
QuadParams::check_consistency() const
|
||||
{
|
||||
if (outname.empty())
|
||||
{
|
||||
std::cerr << "Error: output name not set" << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (vcovname.empty())
|
||||
{
|
||||
std::cerr << "Error: vcov file name not set" << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
QuadParams params(argc, argv);
|
||||
|
||||
// Open output file for writing
|
||||
std::ofstream fout{params.outname, std::ios::out | std::ios::trunc};
|
||||
if (fout.fail())
|
||||
{
|
||||
std::cerr << "Could not open " << params.outname << " for writing" << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::ifstream f{params.vcovname};
|
||||
std::ostringstream buffer;
|
||||
buffer << f.rdbuf();
|
||||
std::string contents{buffer.str()};
|
||||
|
||||
// Parse the vcov matrix
|
||||
ogp::MatrixParser mp;
|
||||
mp.parse(contents);
|
||||
if (mp.nrows() != mp.ncols())
|
||||
throw ogu::Exception(__FILE__, __LINE__,
|
||||
"VCOV matrix not square");
|
||||
// And put to the GeneralMatrix
|
||||
GeneralMatrix vcov(mp.nrows(), mp.ncols());
|
||||
vcov.zeros();
|
||||
for (ogp::MPIterator it = mp.begin(); it != mp.end(); ++it)
|
||||
vcov.get(it.row(), it.col()) = *it;
|
||||
|
||||
// Calculate the factor A of vcov, so that A·Aᵀ=VCOV
|
||||
GeneralMatrix A(vcov.nrows(), vcov.nrows());
|
||||
SymSchurDecomp ssd(vcov);
|
||||
ssd.getFactor(A);
|
||||
|
||||
// Construct Gauss-Hermite quadrature
|
||||
GaussHermite ghq;
|
||||
// Construct Smolyak quadrature
|
||||
int level = params.max_level;
|
||||
SmolyakQuadrature sq(vcov.nrows(), level, ghq);
|
||||
|
||||
std::cout << "Dimension: " << vcov.nrows() << std::endl
|
||||
<< "Maximum level: " << level << std::endl
|
||||
<< "Total number of nodes: " << sq.numEvals(level) << std::endl;
|
||||
|
||||
// Put the points to the vector
|
||||
std::vector<std::unique_ptr<Vector>> points;
|
||||
for (smolpit qit = sq.start(level); qit != sq.end(level); ++qit)
|
||||
points.push_back(std::make_unique<Vector>(const_cast<const Vector &>(qit.point())));
|
||||
// Sort and uniq
|
||||
std::sort(points.begin(), points.end(), [](auto &a, auto &b) { return a.get() < b.get(); });
|
||||
auto new_end = std::unique(points.begin(), points.end());
|
||||
points.erase(new_end, points.end());
|
||||
|
||||
std::cout << "Duplicit nodes removed: " << static_cast<unsigned long>(sq.numEvals(level)-points.size())
|
||||
<< std::endl;
|
||||
|
||||
// Calculate weights and mass
|
||||
double mass = 0.0;
|
||||
std::vector<double> weights;
|
||||
for (auto & point : points)
|
||||
{
|
||||
weights.push_back(std::exp(-point->dot(*point)));
|
||||
mass += weights.back();
|
||||
}
|
||||
|
||||
// Calculate discarded mass
|
||||
double discard_mass = 0.0;
|
||||
for (double weight : weights)
|
||||
if (weight/mass < params.discard_weight)
|
||||
discard_mass += weight;
|
||||
|
||||
std::cout << "Total mass discarded: " << std::fixed << discard_mass/mass << std::endl;
|
||||
|
||||
// Dump the results
|
||||
int npoints = 0;
|
||||
double upscale_weight = 1/(mass-discard_mass);
|
||||
Vector x(vcov.nrows());
|
||||
fout << std::setprecision(16);
|
||||
for (int i = 0; i < static_cast<int>(weights.size()); i++)
|
||||
if (weights[i]/mass >= params.discard_weight)
|
||||
{
|
||||
// Print the upscaled weight
|
||||
fout << std::setw(20) << upscale_weight*weights[i];
|
||||
// Multiply point with the factor A and √2
|
||||
A.multVec(0.0, x, std::sqrt(2.), *(points[i]));
|
||||
// Print the coordinates
|
||||
for (int j = 0; j < x.length(); j++)
|
||||
fout << ' ' << std::setw(20) << x[j];
|
||||
fout << std::endl;
|
||||
npoints++;
|
||||
}
|
||||
|
||||
std::cout << "Final number of points: " << npoints << std::endl;
|
||||
|
||||
fout.close();
|
||||
}
|
||||
catch (const SylvException &e)
|
||||
{
|
||||
e.printMessage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (const ogu::Exception &e)
|
||||
{
|
||||
e.print();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,192 +0,0 @@
|
|||
// Copyright (C) 2008-2011, Ondra Kamenik
|
||||
|
||||
#include "parser/cc/matrix_parser.h"
|
||||
#include "utils/cc/memory_file.h"
|
||||
#include "utils/cc/exception.h"
|
||||
#include "sylv/cc/GeneralMatrix.h"
|
||||
#include "sylv/cc/Vector.h"
|
||||
#include "sylv/cc/SymSchurDecomp.h"
|
||||
#include "sylv/cc/SylvException.h"
|
||||
#include "integ/cc/quadrature.h"
|
||||
#include "integ/cc/smolyak.h"
|
||||
#include "integ/cc/product.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <cstdio>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
struct QuadParams {
|
||||
const char* outname;
|
||||
const char* vcovname;
|
||||
int max_level;
|
||||
double discard_weight;
|
||||
QuadParams(int argc, char** argv);
|
||||
void check_consistency() const;
|
||||
private:
|
||||
enum {opt_max_level, opt_discard_weight, opt_vcov};
|
||||
};
|
||||
|
||||
QuadParams::QuadParams(int argc, char** argv)
|
||||
: outname(NULL), vcovname(NULL), max_level(3), discard_weight(0.0)
|
||||
{
|
||||
if (argc == 1) {
|
||||
// print the help and exit
|
||||
exit(1);
|
||||
}
|
||||
|
||||
outname = argv[argc-1];
|
||||
argc--;
|
||||
|
||||
struct option const opts [] = {
|
||||
{"max-level", required_argument, NULL, opt_max_level},
|
||||
{"discard-weight", required_argument, NULL, opt_discard_weight},
|
||||
{"vcov", required_argument, NULL, opt_vcov},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
int ret;
|
||||
int index;
|
||||
while (-1 != (ret = getopt_long(argc, argv, "", opts, &index))) {
|
||||
switch (ret) {
|
||||
case opt_max_level:
|
||||
if (1 != sscanf(optarg, "%d", &max_level))
|
||||
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
|
||||
break;
|
||||
case opt_discard_weight:
|
||||
if (1 != sscanf(optarg, "%lf", &discard_weight))
|
||||
fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg);
|
||||
break;
|
||||
case opt_vcov:
|
||||
vcovname = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
check_consistency();
|
||||
}
|
||||
|
||||
void QuadParams::check_consistency() const
|
||||
{
|
||||
if (outname == NULL) {
|
||||
fprintf(stderr, "Error: output name not set\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (vcovname == NULL) {
|
||||
fprintf(stderr, "Error: vcov file name not set\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/** Utility class for ordering pointers to vectors according their
|
||||
* ordering. */
|
||||
struct OrderVec {
|
||||
bool operator()(const Vector* a, const Vector* b) const
|
||||
{return *a < *b;}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
QuadParams params(argc, argv);
|
||||
|
||||
// open output file for writing
|
||||
FILE* fout;
|
||||
if (NULL == (fout=fopen(params.outname, "w"))) {
|
||||
fprintf(stderr, "Could not open %s for writing\n", params.outname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// open memory file for vcov
|
||||
ogu::MemoryFile vcov_mf(params.vcovname);
|
||||
|
||||
// parse the vcov matrix
|
||||
ogp::MatrixParser mp;
|
||||
mp.parse(vcov_mf.length(), vcov_mf.base());
|
||||
if (mp.nrows() != mp.ncols())
|
||||
throw ogu::Exception(__FILE__,__LINE__,
|
||||
"VCOV matrix not square");
|
||||
// and put to the GeneralMatrix
|
||||
GeneralMatrix vcov(mp.nrows(), mp.ncols());
|
||||
vcov.zeros();
|
||||
for (ogp::MPIterator it = mp.begin(); it != mp.end(); ++it)
|
||||
vcov.get(it.row(), it.col()) = *it;
|
||||
|
||||
// calculate the factor A of vcov, so that A*A^T=VCOV
|
||||
GeneralMatrix A(vcov.numRows(), vcov.numRows());
|
||||
SymSchurDecomp ssd(vcov);
|
||||
ssd.getFactor(A);
|
||||
|
||||
// construct Gauss-Hermite quadrature
|
||||
GaussHermite ghq;
|
||||
// construct Smolyak quadrature
|
||||
int level = params.max_level;
|
||||
SmolyakQuadrature sq(vcov.numRows(), level, ghq);
|
||||
|
||||
printf("Dimension: %d\n", vcov.numRows());
|
||||
printf("Maximum level: %d\n", level);
|
||||
printf("Total number of nodes: %d\n", sq.numEvals(level));
|
||||
|
||||
// put the points to the vector
|
||||
std::vector<Vector*> points;
|
||||
for (smolpit qit = sq.start(level); qit != sq.end(level); ++qit)
|
||||
points.push_back(new Vector((const Vector&)qit.point()));
|
||||
// sort and uniq
|
||||
OrderVec ordvec;
|
||||
std::sort(points.begin(), points.end(), ordvec);
|
||||
std::vector<Vector*>::iterator new_end = std::unique(points.begin(), points.end());
|
||||
for (std::vector<Vector*>::iterator it = new_end; it != points.end(); ++it)
|
||||
delete *it;
|
||||
points.erase(new_end, points.end());
|
||||
|
||||
printf("Duplicit nodes removed: %lu\n", (unsigned long) (sq.numEvals(level)-points.size()));
|
||||
|
||||
// calculate weights and mass
|
||||
double mass = 0.0;
|
||||
std::vector<double> weights;
|
||||
for (int i = 0; i < (int)points.size(); i++) {
|
||||
weights.push_back(std::exp(-points[i]->dot(*(points[i]))));
|
||||
mass += weights.back();
|
||||
}
|
||||
|
||||
// calculate discarded mass
|
||||
double discard_mass = 0.0;
|
||||
for (int i = 0; i < (int)weights.size(); i++)
|
||||
if (weights[i]/mass < params.discard_weight)
|
||||
discard_mass += weights[i];
|
||||
|
||||
printf("Total mass discarded: %f\n", discard_mass/mass);
|
||||
|
||||
// dump the results
|
||||
int npoints = 0;
|
||||
double upscale_weight = 1/(mass-discard_mass);
|
||||
Vector x(vcov.numRows());
|
||||
for (int i = 0; i < (int)weights.size(); i++)
|
||||
if (weights[i]/mass >= params.discard_weight) {
|
||||
// print the upscaled weight
|
||||
fprintf(fout, "%20.16g", upscale_weight*weights[i]);
|
||||
// multiply point with the factor A and sqrt(2)
|
||||
A.multVec(0.0, x, std::sqrt(2.), *(points[i]));
|
||||
// print the coordinates
|
||||
for (int j = 0; j < x.length(); j++)
|
||||
fprintf(fout, " %20.16g", x[j]);
|
||||
fprintf(fout, "\n");
|
||||
npoints++;
|
||||
}
|
||||
|
||||
printf("Final number of points: %d\n", npoints);
|
||||
|
||||
fclose(fout);
|
||||
|
||||
} catch (const SylvException& e) {
|
||||
e.printMessage();
|
||||
return 1;
|
||||
} catch (const ogu::Exception& e) {
|
||||
e.print();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
check_PROGRAMS = tests
|
||||
|
||||
tests_SOURCES = tests.cpp
|
||||
tests_CPPFLAGS = -I../cc -I../../tl/cc -I../../sylv/cc -I$(top_srcdir)/mex/sources
|
||||
tests_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
|
||||
tests_SOURCES = tests.cc
|
||||
tests_CPPFLAGS = -I../cc -I../../tl/cc -I../../sylv/cc -I../../utils/cc -I$(top_srcdir)/mex/sources
|
||||
tests_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
|
||||
tests_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_MATIO)
|
||||
tests_LDADD = ../../tl/cc/libtl.a ../../sylv/cc/libsylv.a ../cc/libinteg.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(PTHREAD_LIBS) $(LIBADD_MATIO)
|
||||
tests_LDADD = ../../sylv/cc/libsylv.a ../cc/libinteg.a ../../tl/cc/libtl.a ../../utils/cc/libutils.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(LIBADD_MATIO)
|
||||
|
||||
check-local:
|
||||
./tests
|
||||
|
|
|
@ -0,0 +1,550 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "GeneralMatrix.hh"
|
||||
#include <dynlapack.h>
|
||||
#include "SylvException.hh"
|
||||
|
||||
#include "rfs_tensor.hh"
|
||||
#include "normal_moments.hh"
|
||||
|
||||
#include "vector_function.hh"
|
||||
#include "quadrature.hh"
|
||||
#include "smolyak.hh"
|
||||
#include "product.hh"
|
||||
#include "quasi_mcarlo.hh"
|
||||
|
||||
#include <iomanip>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <cstdlib>
|
||||
|
||||
/* Evaluates unfolded (Dx)ᵏ power, where x is a vector, D is a Cholesky factor
|
||||
(lower triangular) */
|
||||
class MomentFunction : public VectorFunction
|
||||
{
|
||||
GeneralMatrix D;
|
||||
int k;
|
||||
public:
|
||||
MomentFunction(const GeneralMatrix &inD, int kk)
|
||||
: VectorFunction(inD.nrows(), UFSTensor::calcMaxOffset(inD.nrows(), kk)),
|
||||
D(inD), k(kk)
|
||||
{
|
||||
}
|
||||
MomentFunction(const MomentFunction &func) = default;
|
||||
|
||||
std::unique_ptr<VectorFunction>
|
||||
clone() const override
|
||||
{
|
||||
return std::make_unique<MomentFunction>(*this);
|
||||
}
|
||||
void eval(const Vector &point, const ParameterSignal &sig, Vector &out) override;
|
||||
};
|
||||
|
||||
void
|
||||
MomentFunction::eval(const Vector &point, const ParameterSignal &sig, Vector &out)
|
||||
{
|
||||
if (point.length() != indim() || out.length() != outdim())
|
||||
{
|
||||
std::cerr << "Wrong length of vectors in MomentFunction::eval" << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
Vector y(point);
|
||||
y.zeros();
|
||||
D.multaVec(y, point);
|
||||
URSingleTensor ypow(y, k);
|
||||
out.zeros();
|
||||
out.add(1.0, ypow.getData());
|
||||
}
|
||||
|
||||
class TensorPower : public VectorFunction
|
||||
{
|
||||
int k;
|
||||
public:
|
||||
TensorPower(int nvar, int kk)
|
||||
: VectorFunction(nvar, UFSTensor::calcMaxOffset(nvar, kk)), k(kk)
|
||||
{
|
||||
}
|
||||
TensorPower(const TensorPower &func) = default;
|
||||
|
||||
std::unique_ptr<VectorFunction>
|
||||
clone() const override
|
||||
{
|
||||
return std::make_unique<TensorPower>(*this);
|
||||
}
|
||||
void eval(const Vector &point, const ParameterSignal &sig, Vector &out) override;
|
||||
};
|
||||
|
||||
void
|
||||
TensorPower::eval(const Vector &point, const ParameterSignal &sig, Vector &out)
|
||||
{
|
||||
if (point.length() != indim() || out.length() != outdim())
|
||||
{
|
||||
std::cerr << "Wrong length of vectors in TensorPower::eval" << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
URSingleTensor ypow(point, k);
|
||||
out.zeros();
|
||||
out.add(1.0, ypow.getData());
|
||||
}
|
||||
|
||||
/* Evaluates (1+1/d)ᵈ(x₁·…·x_d)^(1/d), its integral over [0,1]ᵈ
|
||||
is 1.0, and its variation grows exponentially */
|
||||
class Function1 : public VectorFunction
|
||||
{
|
||||
int dim;
|
||||
public:
|
||||
Function1(int d)
|
||||
: VectorFunction(d, 1), dim(d)
|
||||
{
|
||||
}
|
||||
Function1(const Function1 &f)
|
||||
: VectorFunction(f.indim(), f.outdim()), dim(f.dim)
|
||||
{
|
||||
}
|
||||
std::unique_ptr<VectorFunction>
|
||||
clone() const override
|
||||
{
|
||||
return std::make_unique<Function1>(*this);
|
||||
}
|
||||
void eval(const Vector &point, const ParameterSignal &sig, Vector &out) override;
|
||||
};
|
||||
|
||||
void
|
||||
Function1::eval(const Vector &point, const ParameterSignal &sig, Vector &out)
|
||||
{
|
||||
if (point.length() != dim || out.length() != 1)
|
||||
{
|
||||
std::cerr << "Wrong length of vectors in Function1::eval" << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
double r = 1;
|
||||
for (int i = 0; i < dim; i++)
|
||||
r *= point[i];
|
||||
r = pow(r, 1.0/dim);
|
||||
r *= pow(1.0 + 1.0/dim, static_cast<double>(dim));
|
||||
out[0] = r;
|
||||
}
|
||||
|
||||
// Evaluates Function1 but with transformation xᵢ=0.5(yᵢ+1)
|
||||
// This makes the new function integrate over [−1,1]ᵈ to 1.0
|
||||
class Function1Trans : public Function1
|
||||
{
|
||||
public:
|
||||
Function1Trans(int d)
|
||||
: Function1(d)
|
||||
{
|
||||
}
|
||||
Function1Trans(const Function1Trans &func) = default;
|
||||
|
||||
std::unique_ptr<VectorFunction>
|
||||
clone() const override
|
||||
{
|
||||
return std::make_unique<Function1Trans>(*this);
|
||||
}
|
||||
void eval(const Vector &point, const ParameterSignal &sig, Vector &out) override;
|
||||
};
|
||||
|
||||
void
|
||||
Function1Trans::eval(const Vector &point, const ParameterSignal &sig, Vector &out)
|
||||
{
|
||||
Vector p(point.length());
|
||||
for (int i = 0; i < p.length(); i++)
|
||||
p[i] = 0.5*(point[i]+1);
|
||||
Function1::eval(p, sig, out);
|
||||
out.mult(pow(0.5, indim()));
|
||||
}
|
||||
|
||||
/* WallTimer class. Constructor saves the wall time, destructor cancels the
|
||||
current time from the saved, and prints the message with time information */
|
||||
class WallTimer
|
||||
{
|
||||
std::string mes;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> start;
|
||||
bool new_line;
|
||||
public:
|
||||
WallTimer(std::string m, bool nl = true)
|
||||
: mes{m}, start{std::chrono::high_resolution_clock::now()}, new_line{nl}
|
||||
{
|
||||
}
|
||||
~WallTimer()
|
||||
{
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> duration = end - start;
|
||||
std::cout << mes << std::setw(8) << std::setprecision(4) << duration.count();
|
||||
if (new_line)
|
||||
std::cout << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
/****************************************************/
|
||||
/* declaration of TestRunnable class */
|
||||
/****************************************************/
|
||||
class TestRunnable
|
||||
{
|
||||
public:
|
||||
const std::string name;
|
||||
int dim; // dimension of the solved problem
|
||||
int nvar; // number of variables of the solved problem
|
||||
TestRunnable(std::string name_arg, int d, int nv)
|
||||
: name{move(name_arg)}, dim(d), nvar(nv)
|
||||
{
|
||||
}
|
||||
virtual ~TestRunnable() = default;
|
||||
bool test() const;
|
||||
virtual bool run() const = 0;
|
||||
protected:
|
||||
static bool smolyak_normal_moments(const GeneralMatrix &m, int imom, int level);
|
||||
static bool product_normal_moments(const GeneralMatrix &m, int imom, int level);
|
||||
static bool qmc_normal_moments(const GeneralMatrix &m, int imom, int level);
|
||||
static bool smolyak_product_cube(const VectorFunction &func, const Vector &res,
|
||||
double tol, int level);
|
||||
static bool qmc_cube(const VectorFunction &func, double res, double tol, int level);
|
||||
};
|
||||
|
||||
bool
|
||||
TestRunnable::test() const
|
||||
{
|
||||
std::cout << "Running test <" << name << ">" << std::endl;
|
||||
bool passed;
|
||||
{
|
||||
WallTimer tim("Wall clock time ", false);
|
||||
passed = run();
|
||||
}
|
||||
if (passed)
|
||||
{
|
||||
std::cout << "............................ passed" << std::endl << std::endl;
|
||||
return passed;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "............................ FAILED" << std::endl << std::endl;
|
||||
return passed;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************/
|
||||
/* definition of TestRunnable static methods */
|
||||
/****************************************************/
|
||||
bool
|
||||
TestRunnable::smolyak_normal_moments(const GeneralMatrix &m, int imom, int level)
|
||||
{
|
||||
// First make m·mᵀ and then Cholesky factor
|
||||
GeneralMatrix msq(m * transpose(m));
|
||||
|
||||
// Make vector function
|
||||
int dim = m.nrows();
|
||||
TensorPower tp(dim, imom);
|
||||
GaussConverterFunction func(tp, msq);
|
||||
|
||||
// Smolyak quadrature
|
||||
Vector smol_out(UFSTensor::calcMaxOffset(dim, imom));
|
||||
{
|
||||
WallTimer tim("\tSmolyak quadrature time: ");
|
||||
GaussHermite gs;
|
||||
SmolyakQuadrature quad(dim, level, gs);
|
||||
quad.integrate(func, level, sthread::detach_thread_group::max_parallel_threads, smol_out);
|
||||
std::cout << "\tNumber of Smolyak evaluations: " << quad.numEvals(level) << std::endl;
|
||||
}
|
||||
|
||||
// Check against theoretical moments
|
||||
UNormalMoments moments(imom, msq);
|
||||
smol_out.add(-1.0, moments.get(Symmetry{imom}).getData());
|
||||
std::cout << "\tError: " << std::setw(16) << std::setprecision(12) << smol_out.getMax() << std::endl;
|
||||
return smol_out.getMax() < 1.e-7;
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::product_normal_moments(const GeneralMatrix &m, int imom, int level)
|
||||
{
|
||||
// First make m·mᵀ and then Cholesky factor
|
||||
GeneralMatrix msq(m * transpose(m));
|
||||
|
||||
// Make vector function
|
||||
int dim = m.nrows();
|
||||
TensorPower tp(dim, imom);
|
||||
GaussConverterFunction func(tp, msq);
|
||||
|
||||
// Product quadrature
|
||||
Vector prod_out(UFSTensor::calcMaxOffset(dim, imom));
|
||||
{
|
||||
WallTimer tim("\tProduct quadrature time: ");
|
||||
GaussHermite gs;
|
||||
ProductQuadrature quad(dim, gs);
|
||||
quad.integrate(func, level, sthread::detach_thread_group::max_parallel_threads, prod_out);
|
||||
std::cout << "\tNumber of product evaluations: " << quad.numEvals(level) << std::endl;
|
||||
}
|
||||
|
||||
// Check against theoretical moments
|
||||
UNormalMoments moments(imom, msq);
|
||||
prod_out.add(-1.0, moments.get(Symmetry{imom}).getData());
|
||||
std::cout << "\tError: " << std::setw(16) << std::setprecision(12) << prod_out.getMax() << std::endl;
|
||||
return prod_out.getMax() < 1.e-7;
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::smolyak_product_cube(const VectorFunction &func, const Vector &res,
|
||||
double tol, int level)
|
||||
{
|
||||
if (res.length() != func.outdim())
|
||||
{
|
||||
std::cerr << "Incompatible dimensions of check value and function." << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
GaussLegendre glq;
|
||||
Vector out(func.outdim());
|
||||
double smol_error;
|
||||
double prod_error;
|
||||
{
|
||||
WallTimer tim("\tSmolyak quadrature time: ");
|
||||
SmolyakQuadrature quad(func.indim(), level, glq);
|
||||
quad.integrate(func, level, sthread::detach_thread_group::max_parallel_threads, out);
|
||||
out.add(-1.0, res);
|
||||
smol_error = out.getMax();
|
||||
std::cout << "\tNumber of Smolyak evaluations: " << quad.numEvals(level) << std::endl;
|
||||
std::cout << "\tError: " << std::setw(16) << std::setprecision(12) << smol_error << std::endl;
|
||||
}
|
||||
{
|
||||
WallTimer tim("\tProduct quadrature time: ");
|
||||
ProductQuadrature quad(func.indim(), glq);
|
||||
quad.integrate(func, level, sthread::detach_thread_group::max_parallel_threads, out);
|
||||
out.add(-1.0, res);
|
||||
prod_error = out.getMax();
|
||||
std::cout << "\tNumber of product evaluations: " << quad.numEvals(level) << std::endl;
|
||||
std::cout << "\tError: " << std::setw(16) << std::setprecision(12) << prod_error << std::endl;
|
||||
}
|
||||
|
||||
return smol_error < tol && prod_error < tol;
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::qmc_cube(const VectorFunction &func, double res, double tol, int level)
|
||||
{
|
||||
Vector r(1);
|
||||
double error1;
|
||||
{
|
||||
WallTimer tim("\tQuasi-Monte Carlo (Warnock scrambling) time: ");
|
||||
WarnockPerScheme wps;
|
||||
QMCarloCubeQuadrature qmc(func.indim(), level, wps);
|
||||
qmc.integrate(func, level, sthread::detach_thread_group::max_parallel_threads, r);
|
||||
error1 = std::max(res - r[0], r[0] - res);
|
||||
std::cout << "\tQuasi-Monte Carlo (Warnock scrambling) error: " << std::setw(16) << std::setprecision(12) << error1 << std::endl;
|
||||
}
|
||||
double error2;
|
||||
{
|
||||
WallTimer tim("\tQuasi-Monte Carlo (reverse scrambling) time: ");
|
||||
ReversePerScheme rps;
|
||||
QMCarloCubeQuadrature qmc(func.indim(), level, rps);
|
||||
qmc.integrate(func, level, sthread::detach_thread_group::max_parallel_threads, r);
|
||||
error2 = std::max(res - r[0], r[0] - res);
|
||||
std::cout << "\tQuasi-Monte Carlo (reverse scrambling) error: " << std::setw(16) << std::setprecision(12) << error2 << std::endl;
|
||||
}
|
||||
double error3;
|
||||
{
|
||||
WallTimer tim("\tQuasi-Monte Carlo (no scrambling) time: ");
|
||||
IdentityPerScheme ips;
|
||||
QMCarloCubeQuadrature qmc(func.indim(), level, ips);
|
||||
qmc.integrate(func, level, sthread::detach_thread_group::max_parallel_threads, r);
|
||||
error3 = std::max(res - r[0], r[0] - res);
|
||||
std::cout << "\tQuasi-Monte Carlo (no scrambling) error: " << std::setw(16) << std::setprecision(12) << error3 << std::endl;
|
||||
}
|
||||
|
||||
return error1 < tol && error2 < tol && error3 < tol;
|
||||
}
|
||||
|
||||
/****************************************************/
|
||||
/* definition of TestRunnable subclasses */
|
||||
/****************************************************/
|
||||
class SmolyakNormalMom1 : public TestRunnable
|
||||
{
|
||||
public:
|
||||
SmolyakNormalMom1()
|
||||
: TestRunnable("Smolyak normal moments (dim=2, level=4, order=4)", 4, 2)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
run() const override
|
||||
{
|
||||
GeneralMatrix m(2, 2);
|
||||
m.zeros();
|
||||
m.get(0, 0) = 1;
|
||||
m.get(1, 1) = 1;
|
||||
return smolyak_normal_moments(m, 4, 4);
|
||||
}
|
||||
};
|
||||
|
||||
class SmolyakNormalMom2 : public TestRunnable
|
||||
{
|
||||
public:
|
||||
SmolyakNormalMom2()
|
||||
: TestRunnable("Smolyak normal moments (dim=3, level=8, order=8)", 8, 3)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
run() const override
|
||||
{
|
||||
GeneralMatrix m(3, 3);
|
||||
m.zeros();
|
||||
m.get(0, 0) = 1;
|
||||
m.get(0, 2) = 0.5;
|
||||
m.get(1, 1) = 1;
|
||||
m.get(1, 0) = 0.5;
|
||||
m.get(2, 2) = 2;
|
||||
m.get(2, 1) = 4;
|
||||
return smolyak_normal_moments(m, 8, 8);
|
||||
}
|
||||
};
|
||||
|
||||
class ProductNormalMom1 : public TestRunnable
|
||||
{
|
||||
public:
|
||||
ProductNormalMom1()
|
||||
: TestRunnable("Product normal moments (dim=2, level=4, order=4)", 4, 2)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
run() const override
|
||||
{
|
||||
GeneralMatrix m(2, 2);
|
||||
m.zeros();
|
||||
m.get(0, 0) = 1;
|
||||
m.get(1, 1) = 1;
|
||||
return product_normal_moments(m, 4, 4);
|
||||
}
|
||||
};
|
||||
|
||||
class ProductNormalMom2 : public TestRunnable
|
||||
{
|
||||
public:
|
||||
ProductNormalMom2()
|
||||
: TestRunnable("Product normal moments (dim=3, level=8, order=8)", 8, 3)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
run() const override
|
||||
{
|
||||
GeneralMatrix m(3, 3);
|
||||
m.zeros();
|
||||
m.get(0, 0) = 1;
|
||||
m.get(0, 2) = 0.5;
|
||||
m.get(1, 1) = 1;
|
||||
m.get(1, 0) = 0.5;
|
||||
m.get(2, 2) = 2;
|
||||
m.get(2, 1) = 4;
|
||||
return product_normal_moments(m, 8, 8);
|
||||
}
|
||||
};
|
||||
|
||||
// Note that here we pass 1,1 to tls since smolyak has its own PascalTriangle
|
||||
class F1GaussLegendre : public TestRunnable
|
||||
{
|
||||
public:
|
||||
F1GaussLegendre()
|
||||
: TestRunnable("Function1 Gauss-Legendre (dim=6, level=13", 1, 1)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
run() const override
|
||||
{
|
||||
Function1Trans f1(6);
|
||||
Vector res(1);
|
||||
res[0] = 1.0;
|
||||
return smolyak_product_cube(f1, res, 1e-2, 13);
|
||||
}
|
||||
};
|
||||
|
||||
class F1QuasiMCarlo : public TestRunnable
|
||||
{
|
||||
public:
|
||||
F1QuasiMCarlo()
|
||||
: TestRunnable("Function1 Quasi-Monte Carlo (dim=6, level=1000000)", 1, 1)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
run() const override
|
||||
{
|
||||
Function1 f1(6);
|
||||
return qmc_cube(f1, 1.0, 1.e-4, 1000000);
|
||||
}
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
std::vector<std::unique_ptr<TestRunnable>> all_tests;
|
||||
// Fill in vector of all tests
|
||||
all_tests.push_back(std::make_unique<SmolyakNormalMom1>());
|
||||
all_tests.push_back(std::make_unique<SmolyakNormalMom2>());
|
||||
all_tests.push_back(std::make_unique<ProductNormalMom1>());
|
||||
all_tests.push_back(std::make_unique<ProductNormalMom2>());
|
||||
all_tests.push_back(std::make_unique<F1GaussLegendre>());
|
||||
all_tests.push_back(std::make_unique<F1QuasiMCarlo>());
|
||||
|
||||
// Find maximum dimension and maximum nvar
|
||||
int dmax = 0;
|
||||
int nvmax = 0;
|
||||
for (const auto &test : all_tests)
|
||||
{
|
||||
dmax = std::max(dmax, test->dim);
|
||||
nvmax = std::max(nvmax, test->nvar);
|
||||
}
|
||||
TLStatic::init(dmax, nvmax); // initialize library
|
||||
|
||||
// Launch the tests
|
||||
int success = 0;
|
||||
for (const auto &test : all_tests)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (test->test())
|
||||
success++;
|
||||
}
|
||||
catch (const TLException &e)
|
||||
{
|
||||
std::cout << "Caught TL exception in <" << test->name << ">:" << std::endl;
|
||||
e.print();
|
||||
}
|
||||
catch (SylvException &e)
|
||||
{
|
||||
std::cout << "Caught Sylv exception in <" << test->name << ">:" << std::endl;
|
||||
e.printMessage();
|
||||
}
|
||||
}
|
||||
|
||||
int nfailed = all_tests.size() - success;
|
||||
std::cout << "There were " << nfailed << " tests that failed out of "
|
||||
<< all_tests.size() << " tests run." << std::endl;
|
||||
|
||||
if (nfailed)
|
||||
return EXIT_FAILURE;
|
||||
else
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,544 +0,0 @@
|
|||
/* $Id: tests.cpp 431 2005-08-16 15:41:01Z kamenik $ */
|
||||
/* Copyright 2005, Ondra Kamenik */
|
||||
|
||||
#include "GeneralMatrix.h"
|
||||
#include <dynlapack.h>
|
||||
#include "SylvException.h"
|
||||
|
||||
#include "rfs_tensor.h"
|
||||
#include "normal_moments.h"
|
||||
|
||||
#include "vector_function.h"
|
||||
#include "quadrature.h"
|
||||
#include "smolyak.h"
|
||||
#include "product.h"
|
||||
#include "quasi_mcarlo.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <sys/time.h>
|
||||
#include <cmath>
|
||||
|
||||
const int num_threads = 2; // does nothing if DEBUG defined
|
||||
|
||||
// evaluates unfolded (Dx)^k power, where x is a vector, D is a
|
||||
// Cholesky factor (lower triangular)
|
||||
class MomentFunction : public VectorFunction {
|
||||
GeneralMatrix D;
|
||||
int k;
|
||||
public:
|
||||
MomentFunction(const GeneralMatrix& inD, int kk)
|
||||
: VectorFunction(inD.numRows(), UFSTensor::calcMaxOffset(inD.numRows(), kk)),
|
||||
D(inD), k(kk) {}
|
||||
MomentFunction(const MomentFunction& func)
|
||||
: VectorFunction(func), D(func.D), k(func.k) {}
|
||||
VectorFunction* clone() const
|
||||
{return new MomentFunction(*this);}
|
||||
void eval(const Vector& point, const ParameterSignal& sig, Vector& out);
|
||||
};
|
||||
|
||||
void MomentFunction::eval(const Vector& point, const ParameterSignal& sig, Vector& out)
|
||||
{
|
||||
if (point.length() != indim() || out.length() != outdim()) {
|
||||
printf("Wrong length of vectors in MomentFunction::eval\n");
|
||||
exit(1);
|
||||
}
|
||||
Vector y(point);
|
||||
y.zeros();
|
||||
D.multaVec(y, point);
|
||||
URSingleTensor ypow(y, k);
|
||||
out.zeros();
|
||||
out.add(1.0, ypow.getData());
|
||||
}
|
||||
|
||||
class TensorPower : public VectorFunction {
|
||||
int k;
|
||||
public:
|
||||
TensorPower(int nvar, int kk)
|
||||
: VectorFunction(nvar, UFSTensor::calcMaxOffset(nvar, kk)), k(kk) {}
|
||||
TensorPower(const TensorPower& func)
|
||||
: VectorFunction(func), k(func.k) {}
|
||||
VectorFunction* clone() const
|
||||
{return new TensorPower(*this);}
|
||||
void eval(const Vector& point, const ParameterSignal& sig, Vector& out);
|
||||
};
|
||||
|
||||
void TensorPower::eval(const Vector& point, const ParameterSignal& sig, Vector& out)
|
||||
{
|
||||
if (point.length() != indim() || out.length() != outdim()) {
|
||||
printf("Wrong length of vectors in TensorPower::eval\n");
|
||||
exit(1);
|
||||
}
|
||||
URSingleTensor ypow(point, k);
|
||||
out.zeros();
|
||||
out.add(1.0, ypow.getData());
|
||||
}
|
||||
|
||||
|
||||
// evaluates (1+1/d)^d*(x_1*...*x_d)^(1/d), its integral over <0,1>^d
|
||||
// is 1.0, and its variation grows exponetially
|
||||
// d = dim
|
||||
class Function1 : public VectorFunction {
|
||||
int dim;
|
||||
public:
|
||||
Function1(int d)
|
||||
: VectorFunction(d, 1), dim(d) {}
|
||||
Function1(const Function1& f)
|
||||
: VectorFunction(f.indim(), f.outdim()), dim(f.dim) {}
|
||||
VectorFunction* clone() const
|
||||
{return new Function1(*this);}
|
||||
virtual void eval(const Vector& point, const ParameterSignal& sig, Vector& out);
|
||||
};
|
||||
|
||||
void Function1::eval(const Vector& point, const ParameterSignal& sig, Vector& out)
|
||||
{
|
||||
if (point.length() != dim || out.length() != 1) {
|
||||
printf("Wrong length of vectors in Function1::eval\n");
|
||||
exit(1);
|
||||
}
|
||||
double r = 1;
|
||||
for (int i = 0; i < dim; i++)
|
||||
r *= point[i];
|
||||
r = pow(r, 1.0/dim);
|
||||
r *= pow(1.0 + 1.0/dim, (double)dim);
|
||||
out[0] = r;
|
||||
}
|
||||
|
||||
// evaluates Function1 but with transformation x_i=0.5(y_i+1)
|
||||
// this makes the new function integrate over <-1,1>^d to 1.0
|
||||
class Function1Trans : public Function1 {
|
||||
public:
|
||||
Function1Trans(int d)
|
||||
: Function1(d) {}
|
||||
Function1Trans(const Function1Trans& func)
|
||||
: Function1(func) {}
|
||||
VectorFunction* clone() const
|
||||
{return new Function1Trans(*this);}
|
||||
virtual void eval(const Vector& point, const ParameterSignal& sig, Vector& out);
|
||||
};
|
||||
|
||||
void Function1Trans::eval(const Vector& point, const ParameterSignal& sig, Vector& out)
|
||||
{
|
||||
Vector p(point.length());
|
||||
for (int i = 0; i < p.length(); i++)
|
||||
p[i] = 0.5*(point[i]+1);
|
||||
Function1::eval(p, sig, out);
|
||||
out.mult(pow(0.5,indim()));
|
||||
}
|
||||
|
||||
|
||||
// WallTimer class. Constructor saves the wall time, destructor
|
||||
// cancels the current time from the saved, and prints the message
|
||||
// with time information
|
||||
class WallTimer {
|
||||
char mes[100];
|
||||
struct timeval start;
|
||||
bool new_line;
|
||||
public:
|
||||
WallTimer(const char* m, bool nl = true)
|
||||
{strcpy(mes, m);new_line = nl; gettimeofday(&start, NULL);}
|
||||
~WallTimer()
|
||||
{
|
||||
struct timeval end;
|
||||
gettimeofday(&end, NULL);
|
||||
printf("%s%8.4g", mes,
|
||||
end.tv_sec-start.tv_sec + (end.tv_usec-start.tv_usec)*1.0e-6);
|
||||
if (new_line)
|
||||
printf("\n");
|
||||
}
|
||||
};
|
||||
|
||||
/****************************************************/
|
||||
/* declaration of TestRunnable class */
|
||||
/****************************************************/
|
||||
class TestRunnable {
|
||||
char name[100];
|
||||
public:
|
||||
int dim; // dimension of the solved problem
|
||||
int nvar; // number of variable of the solved problem
|
||||
TestRunnable(const char* n, int d, int nv)
|
||||
: dim(d), nvar(nv)
|
||||
{strncpy(name, n, 100);}
|
||||
bool test() const;
|
||||
virtual bool run() const =0;
|
||||
const char* getName() const
|
||||
{return name;}
|
||||
protected:
|
||||
static bool smolyak_normal_moments(const GeneralMatrix& m, int imom, int level);
|
||||
static bool product_normal_moments(const GeneralMatrix& m, int imom, int level);
|
||||
static bool qmc_normal_moments(const GeneralMatrix& m, int imom, int level);
|
||||
static bool smolyak_product_cube(const VectorFunction& func, const Vector& res,
|
||||
double tol, int level);
|
||||
static bool qmc_cube(const VectorFunction& func, double res, double tol, int level);
|
||||
};
|
||||
|
||||
bool TestRunnable::test() const
|
||||
{
|
||||
printf("Running test <%s>\n",name);
|
||||
bool passed;
|
||||
{
|
||||
WallTimer tim("Wall clock time ", false);
|
||||
passed = run();
|
||||
}
|
||||
if (passed) {
|
||||
printf("............................ passed\n\n");
|
||||
return passed;
|
||||
} else {
|
||||
printf("............................ FAILED\n\n");
|
||||
return passed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************/
|
||||
/* definition of TestRunnable static methods */
|
||||
/****************************************************/
|
||||
bool TestRunnable::smolyak_normal_moments(const GeneralMatrix& m, int imom, int level)
|
||||
{
|
||||
// first make m*m' and then Cholesky factor
|
||||
GeneralMatrix mtr(m, "transpose");
|
||||
GeneralMatrix msq(m, mtr);
|
||||
|
||||
// make vector function
|
||||
int dim = m.numRows();
|
||||
TensorPower tp(dim, imom);
|
||||
GaussConverterFunction func(tp, msq);
|
||||
|
||||
// smolyak quadrature
|
||||
Vector smol_out(UFSTensor::calcMaxOffset(dim, imom));
|
||||
{
|
||||
WallTimer tim("\tSmolyak quadrature time: ");
|
||||
GaussHermite gs;
|
||||
SmolyakQuadrature quad(dim, level, gs);
|
||||
quad.integrate(func, level, num_threads, smol_out);
|
||||
printf("\tNumber of Smolyak evaluations: %d\n", quad.numEvals(level));
|
||||
}
|
||||
|
||||
// check against theoretical moments
|
||||
UNormalMoments moments(imom, msq);
|
||||
smol_out.add(-1.0, (moments.get(Symmetry(imom)))->getData());
|
||||
printf("\tError: %16.12g\n", smol_out.getMax());
|
||||
return smol_out.getMax() < 1.e-7;
|
||||
}
|
||||
|
||||
bool TestRunnable::product_normal_moments(const GeneralMatrix& m, int imom, int level)
|
||||
{
|
||||
// first make m*m' and then Cholesky factor
|
||||
GeneralMatrix mtr(m, "transpose");
|
||||
GeneralMatrix msq(m, mtr);
|
||||
|
||||
// make vector function
|
||||
int dim = m.numRows();
|
||||
TensorPower tp(dim, imom);
|
||||
GaussConverterFunction func(tp, msq);
|
||||
|
||||
// product quadrature
|
||||
Vector prod_out(UFSTensor::calcMaxOffset(dim, imom));
|
||||
{
|
||||
WallTimer tim("\tProduct quadrature time: ");
|
||||
GaussHermite gs;
|
||||
ProductQuadrature quad(dim, gs);
|
||||
quad.integrate(func, level, num_threads, prod_out);
|
||||
printf("\tNumber of product evaluations: %d\n", quad.numEvals(level));
|
||||
}
|
||||
|
||||
// check against theoretical moments
|
||||
UNormalMoments moments(imom, msq);
|
||||
prod_out.add(-1.0, (moments.get(Symmetry(imom)))->getData());
|
||||
printf("\tError: %16.12g\n", prod_out.getMax());
|
||||
return prod_out.getMax() < 1.e-7;
|
||||
}
|
||||
|
||||
bool TestRunnable::qmc_normal_moments(const GeneralMatrix& m, int imom, int level)
|
||||
{
|
||||
// first make m*m' and then Cholesky factor
|
||||
GeneralMatrix mtr(m, "transpose");
|
||||
GeneralMatrix msq(m, mtr);
|
||||
GeneralMatrix mchol(msq);
|
||||
int rows = mchol.numRows();
|
||||
for (int i = 0; i < rows; i++)
|
||||
for (int j = i+1; j < rows; j++)
|
||||
mchol.get(i,j) = 0.0;
|
||||
int info;
|
||||
dpotrf("L", &rows, mchol.base(), &rows, &info);
|
||||
|
||||
// make vector function
|
||||
MomentFunction func(mchol, imom);
|
||||
|
||||
// permutation schemes
|
||||
WarnockPerScheme wps;
|
||||
ReversePerScheme rps;
|
||||
IdentityPerScheme ips;
|
||||
PermutationScheme* scheme[] = {&wps, &rps, &ips};
|
||||
const char* labs[] = {"Warnock", "Reverse", "Identity"};
|
||||
|
||||
// theoretical result
|
||||
int dim = mchol.numRows();
|
||||
UNormalMoments moments(imom, msq);
|
||||
Vector res((const Vector&)((moments.get(Symmetry(imom)))->getData()));
|
||||
|
||||
// quasi monte carlo normal quadrature
|
||||
double max_error = 0.0;
|
||||
Vector qmc_out(UFSTensor::calcMaxOffset(dim, imom));
|
||||
for (int i = 0; i < 3; i++) {
|
||||
{
|
||||
char mes[100];
|
||||
sprintf(mes, "\tQMC normal quadrature time %8s: ", labs[i]);
|
||||
WallTimer tim(mes);
|
||||
QMCarloNormalQuadrature quad(dim, level, *(scheme[i]));
|
||||
quad.integrate(func, level, num_threads, qmc_out);
|
||||
}
|
||||
qmc_out.add(-1.0, res);
|
||||
printf("\tError %8s: %16.12g\n", labs[i], qmc_out.getMax());
|
||||
if (qmc_out.getMax() > max_error) {
|
||||
max_error = qmc_out.getMax();
|
||||
}
|
||||
}
|
||||
|
||||
return max_error < 1.e-7;
|
||||
}
|
||||
|
||||
|
||||
bool TestRunnable::smolyak_product_cube(const VectorFunction& func, const Vector& res,
|
||||
double tol, int level)
|
||||
{
|
||||
if (res.length() != func.outdim()) {
|
||||
fprintf(stderr, "Incompatible dimensions of check value and function.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
GaussLegendre glq;
|
||||
Vector out(func.outdim());
|
||||
double smol_error;
|
||||
double prod_error;
|
||||
{
|
||||
WallTimer tim("\tSmolyak quadrature time: ");
|
||||
SmolyakQuadrature quad(func.indim(), level, glq);
|
||||
quad.integrate(func, level, num_threads, out);
|
||||
out.add(-1.0, res);
|
||||
smol_error = out.getMax();
|
||||
printf("\tNumber of Smolyak evaluations: %d\n", quad.numEvals(level));
|
||||
printf("\tError: %16.12g\n", smol_error);
|
||||
}
|
||||
{
|
||||
WallTimer tim("\tProduct quadrature time: ");
|
||||
ProductQuadrature quad(func.indim(), glq);
|
||||
quad.integrate(func, level, num_threads, out);
|
||||
out.add(-1.0, res);
|
||||
prod_error = out.getMax();
|
||||
printf("\tNumber of product evaluations: %d\n", quad.numEvals(level));
|
||||
printf("\tError: %16.12g\n", prod_error);
|
||||
}
|
||||
|
||||
return smol_error < tol && prod_error < tol;
|
||||
}
|
||||
|
||||
bool TestRunnable::qmc_cube(const VectorFunction& func, double res, double tol, int level)
|
||||
{
|
||||
Vector r(1);
|
||||
double error1;
|
||||
{
|
||||
WallTimer tim("\tQuasi-Monte Carlo (Warnock scrambling) time: ");
|
||||
WarnockPerScheme wps;
|
||||
QMCarloCubeQuadrature qmc(func.indim(), level, wps);
|
||||
// qmc.savePoints("warnock.txt", level);
|
||||
qmc.integrate(func, level, num_threads, r);
|
||||
error1 = std::max(res - r[0], r[0] - res);
|
||||
printf("\tQuasi-Monte Carlo (Warnock scrambling) error: %16.12g\n",
|
||||
error1);
|
||||
}
|
||||
double error2;
|
||||
{
|
||||
WallTimer tim("\tQuasi-Monte Carlo (reverse scrambling) time: ");
|
||||
ReversePerScheme rps;
|
||||
QMCarloCubeQuadrature qmc(func.indim(), level, rps);
|
||||
// qmc.savePoints("reverse.txt", level);
|
||||
qmc.integrate(func, level, num_threads, r);
|
||||
error2 = std::max(res - r[0], r[0] - res);
|
||||
printf("\tQuasi-Monte Carlo (reverse scrambling) error: %16.12g\n",
|
||||
error2);
|
||||
}
|
||||
double error3;
|
||||
{
|
||||
WallTimer tim("\tQuasi-Monte Carlo (no scrambling) time: ");
|
||||
IdentityPerScheme ips;
|
||||
QMCarloCubeQuadrature qmc(func.indim(), level, ips);
|
||||
// qmc.savePoints("identity.txt", level);
|
||||
qmc.integrate(func, level, num_threads, r);
|
||||
error3 = std::max(res - r[0], r[0] - res);
|
||||
printf("\tQuasi-Monte Carlo (no scrambling) error: %16.12g\n",
|
||||
error3);
|
||||
}
|
||||
|
||||
|
||||
return error1 < tol && error2 < tol && error3 < tol;
|
||||
}
|
||||
|
||||
/****************************************************/
|
||||
/* definition of TestRunnable subclasses */
|
||||
/****************************************************/
|
||||
class SmolyakNormalMom1 : public TestRunnable {
|
||||
public:
|
||||
SmolyakNormalMom1()
|
||||
: TestRunnable("Smolyak normal moments (dim=2, level=4, order=4)", 4, 2) {}
|
||||
|
||||
bool run() const
|
||||
{
|
||||
GeneralMatrix m(2,2);
|
||||
m.zeros(); m.get(0,0)=1; m.get(1,1)=1;
|
||||
return smolyak_normal_moments(m, 4, 4);
|
||||
}
|
||||
};
|
||||
|
||||
class SmolyakNormalMom2 : public TestRunnable {
|
||||
public:
|
||||
SmolyakNormalMom2()
|
||||
: TestRunnable("Smolyak normal moments (dim=3, level=8, order=8)", 8, 3) {}
|
||||
|
||||
bool run() const
|
||||
{
|
||||
GeneralMatrix m(3,3);
|
||||
m.zeros();
|
||||
m.get(0,0)=1; m.get(0,2)=0.5; m.get(1,1)=1;
|
||||
m.get(1,0)=0.5;m.get(2,2)=2;m.get(2,1)=4;
|
||||
return smolyak_normal_moments(m, 8, 8);
|
||||
}
|
||||
};
|
||||
|
||||
class ProductNormalMom1 : public TestRunnable {
|
||||
public:
|
||||
ProductNormalMom1()
|
||||
: TestRunnable("Product normal moments (dim=2, level=4, order=4)", 4, 2) {}
|
||||
|
||||
bool run() const
|
||||
{
|
||||
GeneralMatrix m(2,2);
|
||||
m.zeros(); m.get(0,0)=1; m.get(1,1)=1;
|
||||
return product_normal_moments(m, 4, 4);
|
||||
}
|
||||
};
|
||||
|
||||
class ProductNormalMom2 : public TestRunnable {
|
||||
public:
|
||||
ProductNormalMom2()
|
||||
: TestRunnable("Product normal moments (dim=3, level=8, order=8)", 8, 3) {}
|
||||
|
||||
bool run() const
|
||||
{
|
||||
GeneralMatrix m(3,3);
|
||||
m.zeros();
|
||||
m.get(0,0)=1; m.get(0,2)=0.5; m.get(1,1)=1;
|
||||
m.get(1,0)=0.5;m.get(2,2)=2;m.get(2,1)=4;
|
||||
return product_normal_moments(m, 8, 8);
|
||||
}
|
||||
};
|
||||
|
||||
class QMCNormalMom1 : public TestRunnable {
|
||||
public:
|
||||
QMCNormalMom1()
|
||||
: TestRunnable("QMC normal moments (dim=2, level=1000, order=4)", 4, 2) {}
|
||||
|
||||
bool run() const
|
||||
{
|
||||
GeneralMatrix m(2,2);
|
||||
m.zeros(); m.get(0,0)=1; m.get(1,1)=1;
|
||||
return qmc_normal_moments(m, 4, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
class QMCNormalMom2 : public TestRunnable {
|
||||
public:
|
||||
QMCNormalMom2()
|
||||
: TestRunnable("QMC normal moments (dim=3, level=10000, order=8)", 8, 3) {}
|
||||
|
||||
bool run() const
|
||||
{
|
||||
GeneralMatrix m(3,3);
|
||||
m.zeros();
|
||||
m.get(0,0)=1; m.get(0,2)=0.5; m.get(1,1)=1;
|
||||
m.get(1,0)=0.5;m.get(2,2)=2;m.get(2,1)=4;
|
||||
return qmc_normal_moments(m, 8, 10000);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// note that here we pass 1,1 to tls since smolyak has its own PascalTriangle
|
||||
class F1GaussLegendre : public TestRunnable {
|
||||
public:
|
||||
F1GaussLegendre()
|
||||
: TestRunnable("Function1 Gauss-Legendre (dim=6, level=13", 1, 1) {}
|
||||
|
||||
bool run() const
|
||||
{
|
||||
Function1Trans f1(6);
|
||||
Vector res(1); res[0] = 1.0;
|
||||
return smolyak_product_cube(f1, res, 1e-2, 13);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class F1QuasiMCarlo : public TestRunnable {
|
||||
public:
|
||||
F1QuasiMCarlo()
|
||||
: TestRunnable("Function1 Quasi-Monte Carlo (dim=6, level=1000000)", 1, 1) {}
|
||||
|
||||
bool run() const
|
||||
{
|
||||
Function1 f1(6);
|
||||
return qmc_cube(f1, 1.0, 1.e-4, 1000000);
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
TestRunnable* all_tests[50];
|
||||
// fill in vector of all tests
|
||||
int num_tests = 0;
|
||||
all_tests[num_tests++] = new SmolyakNormalMom1();
|
||||
all_tests[num_tests++] = new SmolyakNormalMom2();
|
||||
all_tests[num_tests++] = new ProductNormalMom1();
|
||||
all_tests[num_tests++] = new ProductNormalMom2();
|
||||
all_tests[num_tests++] = new QMCNormalMom1();
|
||||
all_tests[num_tests++] = new QMCNormalMom2();
|
||||
/*
|
||||
all_tests[num_tests++] = new F1GaussLegendre();
|
||||
all_tests[num_tests++] = new F1QuasiMCarlo();
|
||||
*/
|
||||
// find maximum dimension and maximum nvar
|
||||
int dmax=0;
|
||||
int nvmax = 0;
|
||||
for (int i = 0; i < num_tests; i++) {
|
||||
if (dmax < all_tests[i]->dim)
|
||||
dmax = all_tests[i]->dim;
|
||||
if (nvmax < all_tests[i]->nvar)
|
||||
nvmax = all_tests[i]->nvar;
|
||||
}
|
||||
tls.init(dmax, nvmax); // initialize library
|
||||
THREAD_GROUP::max_parallel_threads = num_threads;
|
||||
|
||||
// launch the tests
|
||||
int success = 0;
|
||||
for (int i = 0; i < num_tests; i++) {
|
||||
try {
|
||||
if (all_tests[i]->test())
|
||||
success++;
|
||||
} catch (const TLException& e) {
|
||||
printf("Caugth TL exception in <%s>:\n", all_tests[i]->getName());
|
||||
e.print();
|
||||
} catch (SylvException& e) {
|
||||
printf("Caught Sylv exception in <%s>:\n", all_tests[i]->getName());
|
||||
e.printMessage();
|
||||
}
|
||||
}
|
||||
|
||||
printf("There were %d tests that failed out of %d tests run.\n",
|
||||
num_tests - success, num_tests);
|
||||
|
||||
// destroy
|
||||
for (int i = 0; i < num_tests; i++) {
|
||||
delete all_tests[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,93 +1,42 @@
|
|||
CWEBSRC = \
|
||||
faa_di_bruno.cweb \
|
||||
korder_stoch.cweb \
|
||||
journal.cweb \
|
||||
decision_rule.cweb \
|
||||
dynamic_model.cweb \
|
||||
random.cweb \
|
||||
first_order.cweb \
|
||||
normal_conjugate.cweb \
|
||||
approximation.cweb \
|
||||
global_check.cweb \
|
||||
korder.cweb \
|
||||
kord_exception.hweb \
|
||||
random.hweb \
|
||||
journal.hweb \
|
||||
approximation.hweb \
|
||||
korder_stoch.hweb \
|
||||
dynamic_model.hweb \
|
||||
decision_rule.hweb \
|
||||
korder.hweb \
|
||||
normal_conjugate.hweb \
|
||||
first_order.hweb \
|
||||
mersenne_twister.hweb \
|
||||
global_check.hweb \
|
||||
faa_di_bruno.hweb
|
||||
|
||||
GENERATED_FILES = \
|
||||
faa_di_bruno.cpp \
|
||||
korder_stoch.cpp \
|
||||
journal.cpp \
|
||||
decision_rule.cpp \
|
||||
dynamic_model.cpp \
|
||||
random.cpp \
|
||||
first_order.cpp \
|
||||
normal_conjugate.cpp \
|
||||
approximation.cpp \
|
||||
global_check.cpp \
|
||||
korder.cpp \
|
||||
kord_exception.h \
|
||||
random.h \
|
||||
journal.h \
|
||||
approximation.h \
|
||||
korder_stoch.h \
|
||||
dynamic_model.h \
|
||||
decision_rule.h \
|
||||
korder.h \
|
||||
normal_conjugate.h \
|
||||
first_order.h \
|
||||
mersenne_twister.h \
|
||||
global_check.h \
|
||||
faa_di_bruno.h
|
||||
|
||||
noinst_LIBRARIES = libkord.a
|
||||
|
||||
libkord_a_SOURCES = $(CWEBSRC) $(GENERATED_FILES)
|
||||
libkord_a_CPPFLAGS = -I../sylv/cc -I../tl/cc -I../integ/cc -I$(top_srcdir)/mex/sources $(CPPFLAGS_MATIO)
|
||||
libkord_a_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
|
||||
libkord_a_SOURCES = \
|
||||
approximation.cc \
|
||||
approximation.hh \
|
||||
decision_rule.cc \
|
||||
decision_rule.hh \
|
||||
dynamic_model.cc \
|
||||
dynamic_model.hh \
|
||||
faa_di_bruno.cc \
|
||||
faa_di_bruno.hh \
|
||||
first_order.cc \
|
||||
first_order.hh \
|
||||
global_check.cc \
|
||||
global_check.hh \
|
||||
kord_exception.hh \
|
||||
korder.cc \
|
||||
korder.hh \
|
||||
korder_stoch.cc \
|
||||
korder_stoch.hh \
|
||||
journal.cc \
|
||||
journal.hh \
|
||||
normal_conjugate.cc \
|
||||
normal_conjugate.hh \
|
||||
seed_generator.cc \
|
||||
seed_generator.hh
|
||||
|
||||
BUILT_SOURCES = $(GENERATED_FILES)
|
||||
|
||||
EXTRA_DIST = main.web dummy.ch
|
||||
libkord_a_CPPFLAGS = -I../sylv/cc -I../tl/cc -I../integ/cc -I../utils/cc -I$(top_srcdir)/mex/sources $(CPPFLAGS_MATIO) -DDYNVERSION=\"$(PACKAGE_VERSION)\"
|
||||
libkord_a_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
|
||||
|
||||
check_PROGRAMS = tests
|
||||
|
||||
tests_SOURCES = tests.cpp
|
||||
tests_CPPFLAGS = -I../sylv/cc -I../tl/cc -I../integ/cc -I$(top_srcdir)/mex/sources
|
||||
tests_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
|
||||
tests_SOURCES = tests.cc
|
||||
tests_CPPFLAGS = -I../sylv/cc -I../tl/cc -I../integ/cc -I../utils/cc -I$(top_srcdir)/mex/sources
|
||||
tests_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
|
||||
tests_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_MATIO)
|
||||
tests_LDADD = libkord.a ../tl/cc/libtl.a ../sylv/cc/libsylv.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(PTHREAD_LIBS) $(LIBADD_MATIO)
|
||||
tests_LDADD = libkord.a ../tl/cc/libtl.a ../sylv/cc/libsylv.a ../utils/cc/libutils.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(LIBADD_MATIO)
|
||||
|
||||
check-local:
|
||||
./tests
|
||||
|
||||
%.cpp: %.cweb dummy.ch
|
||||
$(CTANGLE) -bhp $< dummy.ch $@
|
||||
|
||||
%.h: %.hweb dummy.ch
|
||||
$(CTANGLE) -bhp $< dummy.ch $@
|
||||
|
||||
if HAVE_CWEAVE
|
||||
if HAVE_PDFTEX
|
||||
if HAVE_EPLAIN
|
||||
pdf-local: kord.pdf
|
||||
|
||||
kord.pdf: main.web $(CWEBSRC)
|
||||
$(CWEAVE) -bhp main.web
|
||||
$(PDFTEX) main
|
||||
mv main.pdf kord.pdf
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
CLEANFILES = kord.pdf main.idx main.log main.scn main.tex main.toc out.txt
|
||||
CLEANFILES = out.txt
|
||||
|
|
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "kord_exception.hh"
|
||||
#include "approximation.hh"
|
||||
#include "first_order.hh"
|
||||
#include "korder_stoch.hh"
|
||||
|
||||
ZAuxContainer::ZAuxContainer(const _Ctype *gss, int ngss, int ng, int ny, int nu)
|
||||
: StackContainer<FGSTensor>(4, 1)
|
||||
{
|
||||
stack_sizes = { ngss, ng, ny, nu };
|
||||
conts[0] = gss;
|
||||
calculateOffsets();
|
||||
}
|
||||
|
||||
/* The getType() method corresponds to f(g**(y*,u′,σ),0,0,0). For the first
|
||||
argument we return ‘matrix’, for other three we return ‘zero’. */
|
||||
|
||||
ZAuxContainer::itype
|
||||
ZAuxContainer::getType(int i, const Symmetry &s) const
|
||||
{
|
||||
if (i == 0)
|
||||
if (s[2] > 0)
|
||||
return itype::zero;
|
||||
else
|
||||
return itype::matrix;
|
||||
return itype::zero;
|
||||
}
|
||||
|
||||
Approximation::Approximation(DynamicModel &m, Journal &j, int ns, bool dr_centr, double qz_crit)
|
||||
: model(m), journal(j),
|
||||
ypart(model.nstat(), model.npred(), model.nboth(), model.nforw()),
|
||||
mom(UNormalMoments(model.order(), model.getVcov())),
|
||||
nvs{ypart.nys(), model.nexog(), model.nexog(), 1 },
|
||||
steps(ns),
|
||||
dr_centralize(dr_centr), qz_criterium(qz_crit), ss(ypart.ny(), steps+1)
|
||||
{
|
||||
ss.nans();
|
||||
}
|
||||
|
||||
/* This just returns ‘fdr’ with a check that it is created. */
|
||||
const FoldDecisionRule &
|
||||
Approximation::getFoldDecisionRule() const
|
||||
{
|
||||
KORD_RAISE_IF(!fdr,
|
||||
"Folded decision rule has not been created in Approximation::getFoldDecisionRule");
|
||||
return *fdr;
|
||||
}
|
||||
|
||||
/* This just returns ‘udr’ with a check that it is created. */
|
||||
const UnfoldDecisionRule &
|
||||
Approximation::getUnfoldDecisionRule() const
|
||||
{
|
||||
KORD_RAISE_IF(!udr,
|
||||
"Unfolded decision rule has not been created in Approximation::getUnfoldDecisionRule");
|
||||
return *udr;
|
||||
}
|
||||
|
||||
/* This methods assumes that the deterministic steady state is
|
||||
model.getSteady(). It makes an approximation about it and stores the
|
||||
derivatives to ‘rule_ders’ and ‘rule_ders_ss’. Also it runs a check() for
|
||||
σ=0. */
|
||||
void
|
||||
Approximation::approxAtSteady()
|
||||
{
|
||||
model.calcDerivativesAtSteady();
|
||||
FirstOrder fo(model.nstat(), model.npred(), model.nboth(), model.nforw(),
|
||||
model.nexog(), model.getModelDerivatives().get(Symmetry{1}),
|
||||
journal, qz_criterium);
|
||||
KORD_RAISE_IF_X(!fo.isStable(),
|
||||
"The model is not Blanchard-Kahn stable",
|
||||
KORD_MD_NOT_STABLE);
|
||||
|
||||
if (model.order() >= 2)
|
||||
{
|
||||
KOrder korder(model.nstat(), model.npred(), model.nboth(), model.nforw(),
|
||||
model.getModelDerivatives(), fo.getGy(), fo.getGu(),
|
||||
model.getVcov(), journal);
|
||||
korder.switchToFolded();
|
||||
for (int k = 2; k <= model.order(); k++)
|
||||
korder.performStep<Storage::fold>(k);
|
||||
|
||||
saveRuleDerivs(korder.getFoldDers());
|
||||
}
|
||||
else
|
||||
{
|
||||
FirstOrderDerivs<Storage::fold> fo_ders(fo);
|
||||
saveRuleDerivs(fo_ders);
|
||||
}
|
||||
check(0.0);
|
||||
}
|
||||
|
||||
/* This is the core routine of Approximation class.
|
||||
|
||||
First we solve for the approximation about the deterministic steady state.
|
||||
Then we perform ‘steps’ cycles toward the stochastic steady state. Each
|
||||
cycle moves the size of shocks by dsigma=1.0/steps. At the end of a cycle,
|
||||
we have ‘rule_ders’ being the derivatives at stochastic steady state for
|
||||
σ=sigma_so_far+dsigma and model.getSteady() being the steady state.
|
||||
|
||||
If the number of ‘steps’ is zero, the decision rule ‘dr’ at the bottom is
|
||||
created from derivatives about deterministic steady state, with size of σ=1.
|
||||
Otherwise, the ‘dr’ is created from the approximation about stochastic
|
||||
steady state with σ=0.
|
||||
|
||||
Within each cycle, we first make a backup of the last steady (from
|
||||
initialization or from a previous cycle), then we calculate the fix point of
|
||||
the last rule with σ=dsigma. This becomes a new steady state at the
|
||||
σ=sigma_so_far+dsigma. We calculate expectations of g**(y,σ ηₜ₊₁,σ)
|
||||
expressed as a Taylor expansion around the new σ and the new steady state.
|
||||
Then we solve for the decision rule with explicit g** at t+1 and save the
|
||||
rule.
|
||||
|
||||
After we reached σ=1, the decision rule is formed.
|
||||
|
||||
The biproduct of this method is the matrix ‘ss’, whose columns are steady
|
||||
states for subsequent σ’s. The first column is the deterministic steady
|
||||
state, the last column is the stochastic steady state for a full size of
|
||||
shocks (σ=1). There are ‘steps+1’ columns. */
|
||||
|
||||
void
|
||||
Approximation::walkStochSteady()
|
||||
{
|
||||
// initial approximation at deterministic steady
|
||||
/* Here we solve for the deterministic steady state, calculate
|
||||
approximation at the deterministic steady and save the steady state
|
||||
to ‘ss’. */
|
||||
model.solveDeterministicSteady();
|
||||
approxAtSteady();
|
||||
Vector steady0{ss.getCol(0)};
|
||||
steady0 = model.getSteady();
|
||||
|
||||
double sigma_so_far = 0.0;
|
||||
double dsigma = (steps == 0) ? 0.0 : 1.0/steps;
|
||||
for (int i = 1; i <= steps; i++)
|
||||
{
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Approximation about stochastic steady for sigma=" << sigma_so_far+dsigma << endrec;
|
||||
|
||||
Vector last_steady(model.getSteady());
|
||||
|
||||
// calculate fix-point of the last rule for ‘dsigma’
|
||||
/* We form the DRFixPoint object from the last rule with σ=dsigma. Then
|
||||
we save the steady state to ‘ss’. The new steady is also put to
|
||||
model.getSteady(). */
|
||||
DRFixPoint<Storage::fold> fp(*rule_ders, ypart, model.getSteady(), dsigma);
|
||||
bool converged = fp.calcFixPoint(DecisionRule::emethod::horner, model.getSteady());
|
||||
JournalRecord rec(journal);
|
||||
rec << "Fix point calcs: iter=" << fp.getNumIter() << ", newton_iter="
|
||||
<< fp.getNewtonTotalIter() << ", last_newton_iter=" << fp.getNewtonLastIter() << ".";
|
||||
if (converged)
|
||||
rec << " Converged." << endrec;
|
||||
else
|
||||
{
|
||||
rec << " Not converged!!" << endrec;
|
||||
KORD_RAISE_X("Fix point calculation not converged", KORD_FP_NOT_CONV);
|
||||
}
|
||||
Vector steadyi{ss.getCol(i)};
|
||||
steadyi = model.getSteady();
|
||||
|
||||
// calculate ‘hh’ as expectations of the last g**
|
||||
/* We form the steady state shift ‘dy’, which is the new steady state
|
||||
minus the old steady state. Then we create StochForwardDerivs object,
|
||||
which calculates the derivatives of g** expectations at new sigma and
|
||||
new steady. */
|
||||
Vector dy(model.getSteady());
|
||||
dy.add(-1.0, last_steady);
|
||||
|
||||
StochForwardDerivs<Storage::fold> hh(ypart, model.nexog(), *rule_ders_ss, mom, dy,
|
||||
dsigma, sigma_so_far);
|
||||
JournalRecord rec1(journal);
|
||||
rec1 << "Calculation of g** expectations done" << endrec;
|
||||
|
||||
// form KOrderStoch, solve and save
|
||||
/* We calculate derivatives of the model at the new steady, form
|
||||
KOrderStoch object and solve, and save the rule. */
|
||||
model.calcDerivativesAtSteady();
|
||||
KOrderStoch korder_stoch(ypart, model.nexog(), model.getModelDerivatives(),
|
||||
hh, journal);
|
||||
for (int d = 1; d <= model.order(); d++)
|
||||
korder_stoch.performStep<Storage::fold>(d);
|
||||
|
||||
saveRuleDerivs(korder_stoch.getFoldDers());
|
||||
|
||||
check(sigma_so_far+dsigma);
|
||||
sigma_so_far += dsigma;
|
||||
}
|
||||
|
||||
// construct the resulting decision rules
|
||||
udr.reset();
|
||||
fdr = std::make_unique<FoldDecisionRule>(*rule_ders, ypart, model.nexog(),
|
||||
model.getSteady(), 1.0-sigma_so_far);
|
||||
if (steps == 0 && dr_centralize)
|
||||
{
|
||||
// centralize decision rule for zero steps
|
||||
DRFixPoint<Storage::fold> fp(*rule_ders, ypart, model.getSteady(), 1.0);
|
||||
bool converged = fp.calcFixPoint(DecisionRule::emethod::horner, model.getSteady());
|
||||
JournalRecord rec(journal);
|
||||
rec << "Fix point calcs: iter=" << fp.getNumIter() << ", newton_iter="
|
||||
<< fp.getNewtonTotalIter() << ", last_newton_iter=" << fp.getNewtonLastIter() << ".";
|
||||
if (converged)
|
||||
rec << " Converged." << endrec;
|
||||
else
|
||||
{
|
||||
rec << " Not converged!!" << endrec;
|
||||
KORD_RAISE_X("Fix point calculation not converged", KORD_FP_NOT_CONV);
|
||||
}
|
||||
|
||||
{
|
||||
JournalRecordPair recp(journal);
|
||||
recp << "Centralizing about fix-point." << endrec;
|
||||
fdr = std::make_unique<FoldDecisionRule>(*fdr, model.getSteady());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Here we simply make a new hardcopy of the given rule ‘rule_ders’,
|
||||
and make a new container of in-place subtensors of the derivatives
|
||||
corresponding to forward looking variables. The given container comes
|
||||
from a temporary object and will be destroyed. */
|
||||
|
||||
void
|
||||
Approximation::saveRuleDerivs(const FGSContainer &g)
|
||||
{
|
||||
rule_ders = std::make_unique<FGSContainer>(g);
|
||||
rule_ders_ss = std::make_unique<FGSContainer>(4);
|
||||
for (auto &run : *rule_ders)
|
||||
{
|
||||
auto ten = std::make_unique<FGSTensor>(ypart.nstat+ypart.npred, ypart.nyss(), *(run.second));
|
||||
rule_ders_ss->insert(std::move(ten));
|
||||
}
|
||||
}
|
||||
|
||||
/* This method calculates a shift of the system equations due to integrating
|
||||
shocks at a given σ and current steady state. More precisely, if
|
||||
|
||||
F(y,u,u′,σ)=f(g**(g*(y,u,σ),u′,σ),g(y,u,σ),y,u)
|
||||
|
||||
then the method returns a vector
|
||||
|
||||
σᵈ
|
||||
∑ ── [F_u′ᵈ]_α₁…α_d Σ^α₁…α_d
|
||||
d=1 d!
|
||||
|
||||
For a calculation of [F_u′ᵈ] we use ZAuxContainer, so we create its object.
|
||||
In each cycle we calculate [F_u′ᵈ], and then multiply with the shocks, and
|
||||
add the σᵈ/d! multiple to the result. */
|
||||
|
||||
void
|
||||
Approximation::calcStochShift(Vector &out, double at_sigma) const
|
||||
{
|
||||
KORD_RAISE_IF(out.length() != ypart.ny(),
|
||||
"Wrong length of output vector for Approximation::calcStochShift");
|
||||
out.zeros();
|
||||
|
||||
ZAuxContainer zaux(rule_ders_ss.get(), ypart.nyss(), ypart.ny(),
|
||||
ypart.nys(), model.nexog());
|
||||
|
||||
int dfac = 1;
|
||||
for (int d = 1; d <= rule_ders->getMaxDim(); d++, dfac *= d)
|
||||
{
|
||||
if (KOrder::is_even(d))
|
||||
{
|
||||
Symmetry sym{0, d, 0, 0};
|
||||
|
||||
// calculate F_u′ᵈ via ZAuxContainer
|
||||
auto ten = std::make_unique<FGSTensor>(ypart.ny(), TensorDimens(sym, nvs));
|
||||
ten->zeros();
|
||||
for (int l = 1; l <= d; l++)
|
||||
{
|
||||
const FSSparseTensor &f = model.getModelDerivatives().get(Symmetry{l});
|
||||
zaux.multAndAdd(f, *ten);
|
||||
}
|
||||
|
||||
// multiply with shocks and add to result
|
||||
auto tmp = std::make_unique<FGSTensor>(ypart.ny(), TensorDimens(Symmetry{0, 0, 0, 0}, nvs));
|
||||
tmp->zeros();
|
||||
ten->contractAndAdd(1, *tmp, mom.get(Symmetry{d}));
|
||||
|
||||
out.add(pow(at_sigma, d)/dfac, tmp->getData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This method calculates and reports
|
||||
|
||||
σᵈ
|
||||
f(ȳ) + ∑ ── [F_u′ᵈ]_α₁…α_d Σ^α₁…α_d
|
||||
d=1 d!
|
||||
|
||||
at ȳ, zero shocks and σ. This number should be zero.
|
||||
|
||||
We evaluate the error both at a given σ and σ=1.0. */
|
||||
|
||||
void
|
||||
Approximation::check(double at_sigma) const
|
||||
{
|
||||
Vector stoch_shift(ypart.ny());
|
||||
Vector system_resid(ypart.ny());
|
||||
Vector xx(model.nexog());
|
||||
xx.zeros();
|
||||
model.evaluateSystem(system_resid, model.getSteady(), xx);
|
||||
calcStochShift(stoch_shift, at_sigma);
|
||||
stoch_shift.add(1.0, system_resid);
|
||||
JournalRecord rec1(journal);
|
||||
rec1 << "Error of current approximation for shocks at sigma " << at_sigma
|
||||
<< " is " << stoch_shift.getMax() << endrec;
|
||||
calcStochShift(stoch_shift, 1.0);
|
||||
stoch_shift.add(1.0, system_resid);
|
||||
JournalRecord rec2(journal);
|
||||
rec2 << "Error of current approximation for full shocks is " << stoch_shift.getMax() << endrec;
|
||||
}
|
||||
|
||||
/* The method returns unconditional variance of endogenous variables
|
||||
based on the first order. The first order approximation looks like
|
||||
|
||||
ŷₜ = g_y* ŷ*ₜ₋₁ + gᵤ uₜ
|
||||
|
||||
where ŷ denotes a deviation from the steady state. It can be written as
|
||||
|
||||
ŷₜ = (0 g_y* 0) ŷₜ₋₁ + gᵤ uₜ
|
||||
|
||||
which yields unconditional covariance V for which
|
||||
|
||||
V = GVGᵀ + gᵤ Σ gᵤᵀ
|
||||
|
||||
where G=(0 g_y* 0) and Σ is the covariance of the shocks.
|
||||
|
||||
For solving this Lyapunov equation we use the Sylvester module, which
|
||||
solves equation of the type
|
||||
|
||||
AX + BX(C⊗…⊗C) = D
|
||||
|
||||
So we invoke the Sylvester solver for the first dimension with A = I,
|
||||
B = −G, C = Gᵀ and D = gᵤ Σ gᵤᵀ. */
|
||||
|
||||
TwoDMatrix
|
||||
Approximation::calcYCov() const
|
||||
{
|
||||
const TwoDMatrix &gy = rule_ders->get(Symmetry{1, 0, 0, 0});
|
||||
const TwoDMatrix &gu = rule_ders->get(Symmetry{0, 1, 0, 0});
|
||||
TwoDMatrix G(model.numeq(), model.numeq());
|
||||
G.zeros();
|
||||
G.place(gy, 0, model.nstat());
|
||||
TwoDMatrix B(const_cast<const TwoDMatrix &>(G));
|
||||
B.mult(-1.0);
|
||||
TwoDMatrix C(transpose(G));
|
||||
TwoDMatrix A(model.numeq(), model.numeq());
|
||||
A.zeros();
|
||||
for (int i = 0; i < model.numeq(); i++)
|
||||
A.get(i, i) = 1.0;
|
||||
|
||||
TwoDMatrix X((gu * model.getVcov()) * transpose(gu));
|
||||
|
||||
GeneralSylvester gs(1, model.numeq(), model.numeq(), 0,
|
||||
A.getData(), B.getData(), C.getData(), X.getData());
|
||||
gs.solve();
|
||||
|
||||
return X;
|
||||
}
|
|
@ -1,421 +0,0 @@
|
|||
@q $Id: approximation.cweb 2344 2009-02-09 20:36:08Z michel $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@ Start of {\tt approximation.cpp} file.
|
||||
|
||||
@c
|
||||
#include "kord_exception.h"
|
||||
#include "approximation.h"
|
||||
#include "first_order.h"
|
||||
#include "korder_stoch.h"
|
||||
|
||||
@<|ZAuxContainer| constructor code@>;
|
||||
@<|ZAuxContainer::getType| code@>;
|
||||
@<|Approximation| constructor code@>;
|
||||
@<|Approximation| destructor code@>;
|
||||
@<|Approximation::getFoldDecisionRule| code@>;
|
||||
@<|Approximation::getUnfoldDecisionRule| code@>;
|
||||
@<|Approximation::approxAtSteady| code@>;
|
||||
@<|Approximation::walkStochSteady| code@>;
|
||||
@<|Approximation::saveRuleDerivs| code@>;
|
||||
@<|Approximation::calcStochShift| code@>;
|
||||
@<|Approximation::check| code@>;
|
||||
@<|Approximation::calcYCov| code@>;
|
||||
|
||||
@
|
||||
@<|ZAuxContainer| constructor code@>=
|
||||
ZAuxContainer::ZAuxContainer(const _Ctype* gss, int ngss, int ng, int ny, int nu)
|
||||
: StackContainer<FGSTensor>(4,1)
|
||||
{
|
||||
stack_sizes[0] = ngss; stack_sizes[1] = ng;
|
||||
stack_sizes[2] = ny; stack_sizes[3] = nu;
|
||||
conts[0] = gss;
|
||||
calculateOffsets();
|
||||
}
|
||||
|
||||
|
||||
@ The |getType| method corresponds to
|
||||
$f(g^{**}(y^*,u',\sigma),0,0,0)$. For the first argument we return
|
||||
|matrix|, for other three we return |zero|.
|
||||
|
||||
@<|ZAuxContainer::getType| code@>=
|
||||
ZAuxContainer::itype ZAuxContainer::getType(int i, const Symmetry& s) const
|
||||
{
|
||||
if (i == 0)
|
||||
if (s[2] > 0)
|
||||
return zero;
|
||||
else
|
||||
return matrix;
|
||||
return zero;
|
||||
}
|
||||
|
||||
|
||||
@
|
||||
@<|Approximation| constructor code@>=
|
||||
Approximation::Approximation(DynamicModel& m, Journal& j, int ns, bool dr_centr, double qz_crit)
|
||||
: model(m), journal(j), rule_ders(NULL), rule_ders_ss(NULL), fdr(NULL), udr(NULL),
|
||||
ypart(model.nstat(), model.npred(), model.nboth(), model.nforw()),
|
||||
mom(UNormalMoments(model.order(), model.getVcov())), nvs(4), steps(ns),
|
||||
dr_centralize(dr_centr), qz_criterium(qz_crit), ss(ypart.ny(), steps+1)
|
||||
{
|
||||
nvs[0] = ypart.nys(); nvs[1] = model.nexog();
|
||||
nvs[2] = model.nexog(); nvs[3] = 1;
|
||||
|
||||
ss.nans();
|
||||
}
|
||||
|
||||
@
|
||||
@<|Approximation| destructor code@>=
|
||||
Approximation::~Approximation()
|
||||
{
|
||||
if (rule_ders_ss) delete rule_ders_ss;
|
||||
if (rule_ders) delete rule_ders;
|
||||
if (fdr) delete fdr;
|
||||
if (udr) delete udr;
|
||||
}
|
||||
|
||||
@ This just returns |fdr| with a check that it is created.
|
||||
@<|Approximation::getFoldDecisionRule| code@>=
|
||||
const FoldDecisionRule& Approximation::getFoldDecisionRule() const
|
||||
{
|
||||
KORD_RAISE_IF(fdr == NULL,
|
||||
"Folded decision rule has not been created in Approximation::getFoldDecisionRule");
|
||||
return *fdr;
|
||||
}
|
||||
|
||||
|
||||
@ This just returns |udr| with a check that it is created.
|
||||
@<|Approximation::getUnfoldDecisionRule| code@>=
|
||||
const UnfoldDecisionRule& Approximation::getUnfoldDecisionRule() const
|
||||
{
|
||||
KORD_RAISE_IF(udr == NULL,
|
||||
"Unfolded decision rule has not been created in Approximation::getUnfoldDecisionRule");
|
||||
return *udr;
|
||||
}
|
||||
|
||||
|
||||
@ This methods assumes that the deterministic steady state is
|
||||
|model.getSteady()|. It makes an approximation about it and stores the
|
||||
derivatives to |rule_ders| and |rule_ders_ss|. Also it runs a |check|
|
||||
for $\sigma=0$.
|
||||
|
||||
@<|Approximation::approxAtSteady| code@>=
|
||||
void Approximation::approxAtSteady()
|
||||
{
|
||||
model.calcDerivativesAtSteady();
|
||||
FirstOrder fo(model.nstat(), model.npred(), model.nboth(), model.nforw(),
|
||||
model.nexog(), *(model.getModelDerivatives().get(Symmetry(1))),
|
||||
journal, qz_criterium);
|
||||
KORD_RAISE_IF_X(! fo.isStable(),
|
||||
"The model is not Blanchard-Kahn stable",
|
||||
KORD_MD_NOT_STABLE);
|
||||
|
||||
if (model.order() >= 2) {
|
||||
KOrder korder(model.nstat(), model.npred(), model.nboth(), model.nforw(),
|
||||
model.getModelDerivatives(), fo.getGy(), fo.getGu(),
|
||||
model.getVcov(), journal);
|
||||
korder.switchToFolded();
|
||||
for (int k = 2; k <= model.order(); k++)
|
||||
korder.performStep<KOrder::fold>(k);
|
||||
|
||||
saveRuleDerivs(korder.getFoldDers());
|
||||
} else {
|
||||
FirstOrderDerivs<KOrder::fold> fo_ders(fo);
|
||||
saveRuleDerivs(fo_ders);
|
||||
}
|
||||
check(0.0);
|
||||
}
|
||||
|
||||
@ This is the core routine of |Approximation| class.
|
||||
|
||||
First we solve for the approximation about the deterministic steady
|
||||
state. Then we perform |steps| cycles toward the stochastic steady
|
||||
state. Each cycle moves the size of shocks by |dsigma=1.0/steps|. At
|
||||
the end of a cycle, we have |rule_ders| being the derivatives at
|
||||
stochastic steady state for $\sigma=sigma\_so\_far+dsigma$ and
|
||||
|model.getSteady()| being the steady state.
|
||||
|
||||
If the number of |steps| is zero, the decision rule |dr| at the bottom
|
||||
is created from derivatives about deterministic steady state, with
|
||||
size of $\sigma=1$. Otherwise, the |dr| is created from the
|
||||
approximation about stochastic steady state with $\sigma=0$.
|
||||
|
||||
Within each cycle, we first make a backup of the last steady (from
|
||||
initialization or from a previous cycle), then we calculate the fix
|
||||
point of the last rule with $\sigma=dsigma$. This becomes a new steady
|
||||
state at the $\sigma=sigma\_so\_far+dsigma$. We calculate expectations
|
||||
of $g^{**}(y,\sigma\eta_{t+1},\sigma$ expressed as a Taylor expansion
|
||||
around the new $\sigma$ and the new steady state. Then we solve for
|
||||
the decision rule with explicit $g^{**}$ at $t+1$ and save the rule.
|
||||
|
||||
After we reached $\sigma=1$, the decision rule is formed.
|
||||
|
||||
The biproduct of this method is the matrix |ss|, whose columns are
|
||||
steady states for subsequent $\sigma$s. The first column is the
|
||||
deterministic steady state, the last column is the stochastic steady
|
||||
state for a full size of shocks ($\sigma=1$). There are |steps+1|
|
||||
columns.
|
||||
|
||||
@<|Approximation::walkStochSteady| code@>=
|
||||
void Approximation::walkStochSteady()
|
||||
{
|
||||
@<initial approximation at deterministic steady@>;
|
||||
double sigma_so_far = 0.0;
|
||||
double dsigma = (steps == 0)? 0.0 : 1.0/steps;
|
||||
for (int i = 1; i <= steps; i++) {
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Approximation about stochastic steady for sigma=" << sigma_so_far+dsigma << endrec;
|
||||
|
||||
Vector last_steady((const Vector&)model.getSteady());
|
||||
|
||||
@<calculate fix-point of the last rule for |dsigma|@>;
|
||||
@<calculate |hh| as expectations of the last $g^{**}$@>;
|
||||
@<form |KOrderStoch|, solve and save@>;
|
||||
|
||||
check(sigma_so_far+dsigma);
|
||||
sigma_so_far += dsigma;
|
||||
}
|
||||
|
||||
@<construct the resulting decision rules@>;
|
||||
}
|
||||
|
||||
@ Here we solve for the deterministic steady state, calculate
|
||||
approximation at the deterministic steady and save the steady state
|
||||
to |ss|.
|
||||
|
||||
@<initial approximation at deterministic steady@>=
|
||||
model.solveDeterministicSteady();
|
||||
approxAtSteady();
|
||||
Vector steady0(ss, 0);
|
||||
steady0 = (const Vector&)model.getSteady();
|
||||
|
||||
@ We form the |DRFixPoint| object from the last rule with
|
||||
$\sigma=dsigma$. Then we save the steady state to |ss|. The new steady
|
||||
is also put to |model.getSteady()|.
|
||||
|
||||
@<calculate fix-point of the last rule for |dsigma|@>=
|
||||
DRFixPoint<KOrder::fold> fp(*rule_ders, ypart, model.getSteady(), dsigma);
|
||||
bool converged = fp.calcFixPoint(DecisionRule::horner, model.getSteady());
|
||||
JournalRecord rec(journal);
|
||||
rec << "Fix point calcs: iter=" << fp.getNumIter() << ", newton_iter="
|
||||
<< fp.getNewtonTotalIter() << ", last_newton_iter=" << fp.getNewtonLastIter() << ".";
|
||||
if (converged)
|
||||
rec << " Converged." << endrec;
|
||||
else {
|
||||
rec << " Not converged!!" << endrec;
|
||||
KORD_RAISE_X("Fix point calculation not converged", KORD_FP_NOT_CONV);
|
||||
}
|
||||
Vector steadyi(ss, i);
|
||||
steadyi = (const Vector&)model.getSteady();
|
||||
|
||||
@ We form the steady state shift |dy|, which is the new steady state
|
||||
minus the old steady state. Then we create |StochForwardDerivs|
|
||||
object, which calculates the derivatives of $g^{**}$ expectations at
|
||||
new sigma and new steady.
|
||||
|
||||
@<calculate |hh| as expectations of the last $g^{**}$@>=
|
||||
Vector dy((const Vector&)model.getSteady());
|
||||
dy.add(-1.0, last_steady);
|
||||
|
||||
StochForwardDerivs<KOrder::fold> hh(ypart, model.nexog(), *rule_ders_ss, mom, dy,
|
||||
dsigma, sigma_so_far);
|
||||
JournalRecord rec1(journal);
|
||||
rec1 << "Calculation of g** expectations done" << endrec;
|
||||
|
||||
|
||||
@ We calculate derivatives of the model at the new steady, form
|
||||
|KOrderStoch| object and solve, and save the rule.
|
||||
|
||||
@<form |KOrderStoch|, solve and save@>=
|
||||
model.calcDerivativesAtSteady();
|
||||
KOrderStoch korder_stoch(ypart, model.nexog(), model.getModelDerivatives(),
|
||||
hh, journal);
|
||||
for (int d = 1; d <= model.order(); d++) {
|
||||
korder_stoch.performStep<KOrder::fold>(d);
|
||||
}
|
||||
saveRuleDerivs(korder_stoch.getFoldDers());
|
||||
|
||||
|
||||
@
|
||||
@<construct the resulting decision rules@>=
|
||||
if (fdr) {
|
||||
delete fdr;
|
||||
fdr = NULL;
|
||||
}
|
||||
if (udr) {
|
||||
delete udr;
|
||||
udr = NULL;
|
||||
}
|
||||
|
||||
fdr = new FoldDecisionRule(*rule_ders, ypart, model.nexog(),
|
||||
model.getSteady(), 1.0-sigma_so_far);
|
||||
if (steps == 0 && dr_centralize) {
|
||||
@<centralize decision rule for zero steps@>;
|
||||
}
|
||||
|
||||
|
||||
@
|
||||
@<centralize decision rule for zero steps@>=
|
||||
DRFixPoint<KOrder::fold> fp(*rule_ders, ypart, model.getSteady(), 1.0);
|
||||
bool converged = fp.calcFixPoint(DecisionRule::horner, model.getSteady());
|
||||
JournalRecord rec(journal);
|
||||
rec << "Fix point calcs: iter=" << fp.getNumIter() << ", newton_iter="
|
||||
<< fp.getNewtonTotalIter() << ", last_newton_iter=" << fp.getNewtonLastIter() << ".";
|
||||
if (converged)
|
||||
rec << " Converged." << endrec;
|
||||
else {
|
||||
rec << " Not converged!!" << endrec;
|
||||
KORD_RAISE_X("Fix point calculation not converged", KORD_FP_NOT_CONV);
|
||||
}
|
||||
|
||||
{
|
||||
JournalRecordPair recp(journal);
|
||||
recp << "Centralizing about fix-point." << endrec;
|
||||
FoldDecisionRule* dr_backup = fdr;
|
||||
fdr = new FoldDecisionRule(*dr_backup, model.getSteady());
|
||||
delete dr_backup;
|
||||
}
|
||||
|
||||
|
||||
@ Here we simply make a new hardcopy of the given rule |rule_ders|,
|
||||
and make a new container of in-place subtensors of the derivatives
|
||||
corresponding to forward looking variables. The given container comes
|
||||
from a temporary object and will be destroyed.
|
||||
|
||||
@<|Approximation::saveRuleDerivs| code@>=
|
||||
void Approximation::saveRuleDerivs(const FGSContainer& g)
|
||||
{
|
||||
if (rule_ders) {
|
||||
delete rule_ders;
|
||||
delete rule_ders_ss;
|
||||
}
|
||||
rule_ders = new FGSContainer(g);
|
||||
rule_ders_ss = new FGSContainer(4);
|
||||
for (FGSContainer::iterator run = (*rule_ders).begin(); run != (*rule_ders).end(); ++run) {
|
||||
FGSTensor* ten = new FGSTensor(ypart.nstat+ypart.npred, ypart.nyss(), *((*run).second));
|
||||
rule_ders_ss->insert(ten);
|
||||
}
|
||||
}
|
||||
|
||||
@ This method calculates a shift of the system equations due to
|
||||
integrating shocks at a given $\sigma$ and current steady state. More precisely, if
|
||||
$$F(y,u,u',\sigma)=f(g^{**}(g^*(y,u,\sigma),u',\sigma),g(y,u,\sigma),y,u)$$
|
||||
then the method returns a vector
|
||||
$$\sum_{d=1}{1\over d!}\sigma^d\left[F_{u'^d}\right]_{\alpha_1\ldots\alpha_d}
|
||||
\Sigma^{\alpha_1\ldots\alpha_d}$$
|
||||
|
||||
For a calculation of $\left[F_{u'^d}\right]$ we use |@<|ZAuxContainer|
|
||||
class declaration@>|, so we create its object. In each cycle we
|
||||
calculate $\left[F_{u'^d}\right]$@q'@>, and then multiply with the shocks,
|
||||
and add the ${\sigma^d\over d!}$ multiple to the result.
|
||||
|
||||
@<|Approximation::calcStochShift| code@>=
|
||||
void Approximation::calcStochShift(Vector& out, double at_sigma) const
|
||||
{
|
||||
KORD_RAISE_IF(out.length() != ypart.ny(),
|
||||
"Wrong length of output vector for Approximation::calcStochShift");
|
||||
out.zeros();
|
||||
|
||||
ZAuxContainer zaux(rule_ders_ss, ypart.nyss(), ypart.ny(),
|
||||
ypart.nys(), model.nexog());
|
||||
|
||||
int dfac = 1;
|
||||
for (int d = 1; d <= rule_ders->getMaxDim(); d++, dfac*=d) {
|
||||
if ( KOrder::is_even(d)) {
|
||||
Symmetry sym(0,d,0,0);
|
||||
@<calculate $F_{u'^d}$ via |ZAuxContainer|@>;@q'@>
|
||||
@<multiply with shocks and add to result@>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<calculate $F_{u'^d}$ via |ZAuxContainer|@>=
|
||||
FGSTensor* ten = new FGSTensor(ypart.ny(), TensorDimens(sym, nvs));
|
||||
ten->zeros();
|
||||
for (int l = 1; l <= d; l++) {
|
||||
const FSSparseTensor* f = model.getModelDerivatives().get(Symmetry(l));
|
||||
zaux.multAndAdd(*f, *ten);
|
||||
}
|
||||
|
||||
@
|
||||
@<multiply with shocks and add to result@>=
|
||||
FGSTensor* tmp = new FGSTensor(ypart.ny(), TensorDimens(Symmetry(0,0,0,0), nvs));
|
||||
tmp->zeros();
|
||||
ten->contractAndAdd(1, *tmp, *(mom.get(Symmetry(d))));
|
||||
|
||||
out.add(pow(at_sigma,d)/dfac, tmp->getData());
|
||||
delete ten;
|
||||
delete tmp;
|
||||
|
||||
|
||||
@ This method calculates and reports
|
||||
$$f(\bar y)+\sum_{d=1}{1\over d!}\sigma^d\left[F_{u'^d}\right]_{\alpha_1\ldots\alpha_d}
|
||||
\Sigma^{\alpha_1\ldots\alpha_d}$$
|
||||
at $\bar y$, zero shocks and $\sigma$. This number should be zero.
|
||||
|
||||
We evaluate the error both at a given $\sigma$ and $\sigma=1.0$.
|
||||
|
||||
@<|Approximation::check| code@>=
|
||||
void Approximation::check(double at_sigma) const
|
||||
{
|
||||
Vector stoch_shift(ypart.ny());
|
||||
Vector system_resid(ypart.ny());
|
||||
Vector xx(model.nexog());
|
||||
xx.zeros();
|
||||
model.evaluateSystem(system_resid, model.getSteady(), xx);
|
||||
calcStochShift(stoch_shift, at_sigma);
|
||||
stoch_shift.add(1.0, system_resid);
|
||||
JournalRecord rec1(journal);
|
||||
rec1 << "Error of current approximation for shocks at sigma " << at_sigma
|
||||
<< " is " << stoch_shift.getMax() << endrec;
|
||||
calcStochShift(stoch_shift, 1.0);
|
||||
stoch_shift.add(1.0, system_resid);
|
||||
JournalRecord rec2(journal);
|
||||
rec2 << "Error of current approximation for full shocks is " << stoch_shift.getMax() << endrec;
|
||||
}
|
||||
|
||||
@ The method returns unconditional variance of endogenous variables
|
||||
based on the first order. The first order approximation looks like
|
||||
$$\hat y_t=g_{y^*}\hat y^*_{t-1}+g_uu_t$$
|
||||
where $\hat y$ denotes a deviation from the steady state. It can be written as
|
||||
$$\hat y_t=\left[0\, g_{y^*}\, 0\right]\hat y_{t-1}+g_uu_t$$
|
||||
which yields unconditional covariance $V$ for which
|
||||
$$V=GVG^T + g_u\Sigma g_u^T,$$
|
||||
where $G=[0\, g_{y^*}\, 0]$ and $\Sigma$ is the covariance of the shocks.
|
||||
|
||||
For solving this Lyapunov equation we use the Sylvester module, which
|
||||
solves equation of the type
|
||||
$$AX+BX(C\otimes\cdots\otimes C)=D$$
|
||||
So we invoke the Sylvester solver for the first dimension with $A=I$,
|
||||
$B=-G$, $C=G^T$ and $D=g_u\Sigma g_u^T$.
|
||||
|
||||
|
||||
@<|Approximation::calcYCov| code@>=
|
||||
TwoDMatrix* Approximation::calcYCov() const
|
||||
{
|
||||
const TwoDMatrix& gy = *(rule_ders->get(Symmetry(1,0,0,0)));
|
||||
const TwoDMatrix& gu = *(rule_ders->get(Symmetry(0,1,0,0)));
|
||||
TwoDMatrix G(model.numeq(), model.numeq());
|
||||
G.zeros();
|
||||
G.place(gy, 0, model.nstat());
|
||||
TwoDMatrix B((const TwoDMatrix&)G);
|
||||
B.mult(-1.0);
|
||||
TwoDMatrix C(G, "transpose");
|
||||
TwoDMatrix A(model.numeq(), model.numeq());
|
||||
A.zeros();
|
||||
for (int i = 0; i < model.numeq(); i++)
|
||||
A.get( i,i) = 1.0;
|
||||
|
||||
TwoDMatrix guSigma(gu, model.getVcov());
|
||||
TwoDMatrix guTrans(gu, "transpose");
|
||||
TwoDMatrix* X = new TwoDMatrix(guSigma, guTrans);
|
||||
|
||||
GeneralSylvester gs(1, model.numeq(), model.numeq(), 0,
|
||||
A.base(), B.base(), C.base(), X->base());
|
||||
gs.solve();
|
||||
|
||||
return X;
|
||||
}
|
||||
|
||||
@ End of {\tt approximation.cpp} file.
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Approximating model solution
|
||||
|
||||
/* The class Approximation in this file is a main interface to the
|
||||
algorithms calculating approximations to the decision rule about
|
||||
deterministic and stochastic steady states.
|
||||
|
||||
The approximation about a deterministic steady state is solved by classes
|
||||
FirstOrder and KOrder. The approximation around the stochastic steady state
|
||||
is computed by class KOrderStoch together with a method of Approximation
|
||||
class.
|
||||
|
||||
The approximation around the stochastic steady state is done with an
|
||||
explicit expression of forward derivatives of g**. More formally,
|
||||
we have to solve the decision rule g from the implicit system:
|
||||
|
||||
𝔼ₜ(f(g**(g*(y*,uₜ,σ),uₜ₊₁,σ),g(y*,uₜ,σ),yₜ,uₜ)) = 0
|
||||
|
||||
The term within the expectations can be Taylor expanded, and the expectation
|
||||
can be driven into the formula. However, when doing this at σ≠0, the term
|
||||
g** at σ≠0 is dependent on uₜ₊₁ and thus the integral of its approximation
|
||||
includes all derivatives w.r.t. u of g**. Note that for σ=0, the derivatives
|
||||
of g** in this context are constant. This is the main difference between the
|
||||
approximation at deterministic steady (σ=0), and stochastic steady (σ≠0).
|
||||
This means that the k-order derivative of the above equation at σ≠0 depends
|
||||
on all derivatives of g** (including those with order greater than k).
|
||||
|
||||
The explicit expression of the forward g** means that the derivatives of g
|
||||
are not solved simultaneously, but that the forward derivatives of g** are
|
||||
calculated as an extrapolation based on the approximation at lower σ. This
|
||||
is exactly what does Approximation::walkStochSteady(). It starts at the
|
||||
deterministic steady state, and in a few steps it adds to σ explicitly
|
||||
expressing forward g** from a previous step.
|
||||
|
||||
Further details on the both solution methods are given in (todo: put
|
||||
references here when they exist).
|
||||
|
||||
Very important note: all classes here used for calculation of decision
|
||||
rule approximation are folded. For the time being, it seems that Faà
|
||||
Di Bruno formula is quicker for folded tensors, and that is why we
|
||||
stick to folded tensors here. However, when the calcs are done, we
|
||||
calculate also its unfolded versions, to be available for simulations
|
||||
and so on. */
|
||||
|
||||
#ifndef APPROXIMATION_H
|
||||
#define APPROXIMATION_H
|
||||
|
||||
#include "dynamic_model.hh"
|
||||
#include "decision_rule.hh"
|
||||
#include "korder.hh"
|
||||
#include "journal.hh"
|
||||
|
||||
#include <memory>
|
||||
|
||||
/* This class is used to calculate derivatives by Faà Di Bruno of
|
||||
f(g**(g*(y*,u,σ),u′,σ),g(y*,u,σ),y*,u) with respect to u′. In order to keep
|
||||
it as simple as possible, the class represents an equivalent (with respect
|
||||
to u′) container for f(g**(y*,u′,σ),0,0,0). The class is used only for
|
||||
evaluation of approximation error in Approximation class, which is
|
||||
calculated in Approximation::calcStochShift().
|
||||
|
||||
Since it is a folded version, we inherit from StackContainer<FGSTensor> and
|
||||
FoldedStackContainer. To construct it, we need only the g** container and
|
||||
size of stacks. */
|
||||
|
||||
class ZAuxContainer : public StackContainer<FGSTensor>, public FoldedStackContainer
|
||||
{
|
||||
public:
|
||||
using _Ctype = StackContainer<FGSTensor>::_Ctype;
|
||||
using itype = StackContainer<FGSTensor>::itype;
|
||||
ZAuxContainer(const _Ctype *gss, int ngss, int ng, int ny, int nu);
|
||||
itype getType(int i, const Symmetry &s) const override;
|
||||
};
|
||||
|
||||
/* This class provides an interface to approximation algorithms. The core
|
||||
method is walkStochSteady() which calculates the approximation about
|
||||
stochastic steady state in a given number of steps. The number is given as a
|
||||
parameter ‘ns’ of the constructor. If the number is equal to zero, the
|
||||
resulted approximation is about the deterministic steady state.
|
||||
|
||||
An object is constructed from the DynamicModel, and the number of steps
|
||||
‘ns’. Also, we pass a reference to journal. That's all. The result of the
|
||||
core method walkStochSteady() is a decision rule ‘dr’ and a matrix ‘ss’
|
||||
whose columns are steady states for increasing σ during the walk. Both can
|
||||
be retrived by public methods. The first column of the matrix is the
|
||||
deterministic steady state, the last is the stochastic steady state for the
|
||||
full size shocks.
|
||||
|
||||
The method walkStochSteady() calls the following methods: approxAtSteady()
|
||||
calculates an initial approximation about the deterministic steady,
|
||||
saveRuleDerivs() saves derivatives of a rule for the following step in
|
||||
‘rule_ders’ and ‘rule_ders_ss’ (see Approximation::saveRuleDerivs() for
|
||||
their description), check() reports an error of the current approximation
|
||||
and calcStochShift() (called from check()) calculates a shift of the system
|
||||
equations due to uncertainity.
|
||||
|
||||
‘dr_centralize’ is a new option. Dynare++ was automatically expressing
|
||||
results around the fixed point instead of the deterministic steady state.
|
||||
‘dr_centralize’ controls this behavior. */
|
||||
|
||||
class Approximation
|
||||
{
|
||||
DynamicModel &model;
|
||||
Journal &journal;
|
||||
std::unique_ptr<FGSContainer> rule_ders;
|
||||
std::unique_ptr<FGSContainer> rule_ders_ss;
|
||||
std::unique_ptr<FoldDecisionRule> fdr;
|
||||
std::unique_ptr<UnfoldDecisionRule> udr;
|
||||
const PartitionY ypart;
|
||||
const FNormalMoments mom;
|
||||
IntSequence nvs;
|
||||
int steps;
|
||||
bool dr_centralize;
|
||||
double qz_criterium;
|
||||
TwoDMatrix ss;
|
||||
public:
|
||||
Approximation(DynamicModel &m, Journal &j, int ns, bool dr_centr, double qz_crit);
|
||||
|
||||
const FoldDecisionRule &getFoldDecisionRule() const;
|
||||
const UnfoldDecisionRule &getUnfoldDecisionRule() const;
|
||||
const TwoDMatrix &
|
||||
getSS() const
|
||||
{
|
||||
return ss;
|
||||
}
|
||||
const DynamicModel &
|
||||
getModel() const
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
void walkStochSteady();
|
||||
TwoDMatrix calcYCov() const;
|
||||
const FGSContainer &
|
||||
get_rule_ders() const
|
||||
{
|
||||
return *rule_ders;
|
||||
}
|
||||
const FGSContainer &
|
||||
get_rule_ders_ss() const
|
||||
{
|
||||
return *rule_ders_ss;
|
||||
}
|
||||
protected:
|
||||
void approxAtSteady();
|
||||
void calcStochShift(Vector &out, double at_sigma) const;
|
||||
void saveRuleDerivs(const FGSContainer &g);
|
||||
void check(double at_sigma) const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,161 +0,0 @@
|
|||
@q $Id: approximation.hweb 2352 2009-09-03 19:18:15Z michel $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@*2 Approximating model solution. Start of {\tt approximation.h} file.
|
||||
|
||||
The class |Approximation| in this file is a main interface to the
|
||||
algorithms calculating approximations to the decision rule about
|
||||
deterministic and stochastic steady states.
|
||||
|
||||
The approximation about a deterministic steady state is solved by
|
||||
classes |@<|FirstOrder| class declaration@>| and |@<|KOrder| class
|
||||
declaration@>|. The approximation about the stochastic steady state is
|
||||
solved by class |@<|KOrderStoch| class declaration@>| together with a
|
||||
method of |Approximation| class |@<|Approximation::walkStochSteady|
|
||||
code@>|.
|
||||
|
||||
The approximation about the stochastic steady state is done with
|
||||
explicit expression of forward derivatives of $g^{**}$. More formally,
|
||||
we have to solve the decision rule $g$ from the implicit system:
|
||||
$$E_t(f(g^{**}(g^*(y^*,u_t,\sigma),u_{t+1},\sigma),g(y^*,u_t,\sigma),y_t,u_t))=0$$
|
||||
The term within the expectations can be Taylor expanded, and the
|
||||
expectation can be driven into the formula. However, when doing this
|
||||
at $\sigma\not=0$, the term $g^{**}$ at $\sigma\not=0$ is dependent on
|
||||
$u_{t+1}$ and thus the integral of its approximation includes all
|
||||
derivatives wrt. $u$ of $g^{**}$. Note that for $\sigma=0$, the
|
||||
derivatives of $g^{**}$ in this context are constant. This is the main
|
||||
difference between the approximation at deterministic steady
|
||||
($\sigma=0$), and stochastic steady ($\sigma\not=0$). This means that
|
||||
$k$-order derivative of the above equation at $\sigma\not=0$ depends of
|
||||
all derivatives of $g^**$ (including those with order greater than
|
||||
$k$).
|
||||
|
||||
The explicit expression of the forward $g^{**}$ means that the
|
||||
derivatives of $g$ are not solved simultaneously, but that the forward
|
||||
derivatives of $g^{**}$ are calculated as an extrapolation based on
|
||||
the approximation at lower $\sigma$. This is exactly what does the
|
||||
|@<|Approximation::walkStochSteady| code@>|. It starts at the
|
||||
deterministic steady state, and in a few steps it adds to $\sigma$
|
||||
explicitly expressing forward $g^{**}$ from a previous step.
|
||||
|
||||
Further details on the both solution methods are given in (todo: put
|
||||
references here when they exist).
|
||||
|
||||
Very important note: all classes here used for calculation of decision
|
||||
rule approximation are folded. For the time being, it seems that faa
|
||||
Di Bruno formula is quicker for folded tensors, and that is why we
|
||||
stick to folded tensors here. However, when the calcs are done, we
|
||||
calculate also its unfolded versions, to be available for simulations
|
||||
and so on.
|
||||
|
||||
@s ZAuxContainer int
|
||||
@s Approximation int
|
||||
@c
|
||||
#ifndef APPROXIMATION_H
|
||||
#define APPROXIMATION_H
|
||||
|
||||
#include "dynamic_model.h"
|
||||
#include "decision_rule.h"
|
||||
#include "korder.h"
|
||||
#include "journal.h"
|
||||
|
||||
@<|ZAuxContainer| class declaration@>;
|
||||
@<|Approximation| class declaration@>;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ This class is used to calculate derivatives by faa Di Bruno of the
|
||||
$$f(g^{**}(g^*(y^*,u,\sigma),u',\sigma),g(y^*,u,\sigma),y^*,u)$$ with
|
||||
respect $u'$. In order to keep it as simple as possible, the class
|
||||
represents an equivalent (with respect to $u'$) container for
|
||||
$f(g^{**}(y^*,u',\sigma),0,0,0)$. The class is used only for
|
||||
evaluation of approximation error in |Approximation| class, which is
|
||||
calculated in |Approximation::calcStochShift| method.
|
||||
|
||||
Since it is a folded version, we inherit from
|
||||
|StackContainer<FGSTensor>| and |FoldedStackContainer|. To construct
|
||||
it, we need only the $g^{**}$ container and size of stacks.
|
||||
|
||||
@<|ZAuxContainer| class declaration@>=
|
||||
class ZAuxContainer : public StackContainer<FGSTensor>, public FoldedStackContainer {
|
||||
public:@;
|
||||
typedef StackContainer<FGSTensor>::_Ctype _Ctype;
|
||||
typedef StackContainer<FGSTensor>::itype itype;
|
||||
ZAuxContainer(const _Ctype* gss, int ngss, int ng, int ny, int nu);
|
||||
itype getType(int i, const Symmetry& s) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ This class provides an interface to approximation algorithms. The
|
||||
core method is |walkStochSteady| which calculates the approximation
|
||||
about stochastic steady state in a given number of steps. The number
|
||||
is given as a parameter |ns| of the constructor. If the number is
|
||||
equal to zero, the resulted approximation is about the deterministic
|
||||
steady state.
|
||||
|
||||
An object is constructed from the |DynamicModel|, and the number of
|
||||
steps |ns|. Also, we pass a reference to journal. That's all. The
|
||||
result of the core method |walkStochSteady| is a decision rule |dr|
|
||||
and a matrix |ss| whose columns are steady states for increasing
|
||||
$\sigma$ during the walk. Both can be retrived by public methods. The
|
||||
first column of the matrix is the deterministic steady state, the last
|
||||
is the stochastic steady state for the full size shocks.
|
||||
|
||||
The method |walkStochSteady| calls the following methods:
|
||||
|approxAtSteady| calculates an initial approximation about the
|
||||
deterministic steady, |saveRuleDerivs| saves derivatives of a rule for
|
||||
the following step in |rule_ders| and |rule_ders_ss| (see
|
||||
|@<|Approximation::saveRuleDerivs| code@>| for their description),
|
||||
|check| reports an error of the current approximation and
|
||||
|calcStochShift| (called from |check|) calculates a shift of the
|
||||
system equations due to uncertainity.
|
||||
|
||||
dr\_centralize is a new option. dynare++ was automatically expressing
|
||||
results around the fixed point instead of the deterministic steady
|
||||
state. dr\_centralize controls this behavior.
|
||||
|
||||
|
||||
@<|Approximation| class declaration@>=
|
||||
class Approximation {
|
||||
DynamicModel& model;
|
||||
Journal& journal;
|
||||
FGSContainer* rule_ders;
|
||||
FGSContainer* rule_ders_ss;
|
||||
FoldDecisionRule* fdr;
|
||||
UnfoldDecisionRule* udr;
|
||||
const PartitionY ypart;
|
||||
const FNormalMoments mom;
|
||||
IntSequence nvs;
|
||||
int steps;
|
||||
bool dr_centralize;
|
||||
double qz_criterium;
|
||||
TwoDMatrix ss;
|
||||
public:@;
|
||||
Approximation(DynamicModel& m, Journal& j, int ns, bool dr_centr, double qz_crit);
|
||||
virtual ~Approximation();
|
||||
|
||||
const FoldDecisionRule& getFoldDecisionRule() const;
|
||||
const UnfoldDecisionRule& getUnfoldDecisionRule() const;
|
||||
const TwoDMatrix& getSS() const
|
||||
{@+ return ss;@+}
|
||||
const DynamicModel& getModel() const
|
||||
{@+ return model;@+}
|
||||
|
||||
void walkStochSteady();
|
||||
TwoDMatrix* calcYCov() const;
|
||||
const FGSContainer* get_rule_ders() const
|
||||
{@+ return rule_ders;@+}
|
||||
const FGSContainer* get_rule_ders_ss() const
|
||||
{@+ return rule_ders;@+}
|
||||
protected:@;
|
||||
void approxAtSteady();
|
||||
void calcStochShift(Vector& out, double at_sigma) const;
|
||||
void saveRuleDerivs(const FGSContainer& g);
|
||||
void check(double at_sigma) const;
|
||||
};
|
||||
|
||||
|
||||
@ End of {\tt approximation.h} file.
|
||||
|
|
@ -0,0 +1,586 @@
|
|||
/*
|
||||
* Copyright © 2004 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "kord_exception.hh"
|
||||
#include "decision_rule.hh"
|
||||
#include "dynamic_model.hh"
|
||||
#include "seed_generator.hh"
|
||||
|
||||
#include "SymSchurDecomp.hh"
|
||||
|
||||
#include <dynlapack.h>
|
||||
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
// FoldDecisionRule conversion from UnfoldDecisionRule
|
||||
FoldDecisionRule::FoldDecisionRule(const UnfoldDecisionRule &udr)
|
||||
: DecisionRuleImpl<Storage::fold>(ctraits<Storage::fold>::Tpol(udr.nrows(), udr.nvars()),
|
||||
udr.ypart, udr.nu, udr.ysteady)
|
||||
{
|
||||
for (const auto &it : udr)
|
||||
insert(std::make_unique<ctraits<Storage::fold>::Ttensym>(*(it.second)));
|
||||
}
|
||||
|
||||
// UnfoldDecisionRule conversion from FoldDecisionRule
|
||||
UnfoldDecisionRule::UnfoldDecisionRule(const FoldDecisionRule &fdr)
|
||||
: DecisionRuleImpl<Storage::unfold>(ctraits<Storage::unfold>::Tpol(fdr.nrows(), fdr.nvars()),
|
||||
fdr.ypart, fdr.nu, fdr.ysteady)
|
||||
{
|
||||
for (const auto &it : fdr)
|
||||
insert(std::make_unique<ctraits<Storage::unfold>::Ttensym>(*(it.second)));
|
||||
}
|
||||
|
||||
/* This runs simulations with an output to journal file. Note that we
|
||||
report how many simulations had to be thrown out due to Nan or Inf. */
|
||||
|
||||
void
|
||||
SimResults::simulate(int num_sim, const DecisionRule &dr, const Vector &start,
|
||||
const TwoDMatrix &vcov, Journal &journal)
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Performing " << num_sim << " stochastic simulations for "
|
||||
<< num_per << " periods burning " << num_burn << " initial periods" << endrec;
|
||||
simulate(num_sim, dr, start, vcov);
|
||||
int thrown = num_sim - data.size();
|
||||
if (thrown > 0)
|
||||
{
|
||||
JournalRecord rec(journal);
|
||||
rec << "I had to throw " << thrown << " simulations away due to Nan or Inf" << endrec;
|
||||
}
|
||||
}
|
||||
|
||||
/* This runs a given number of simulations by creating
|
||||
SimulationWorker for each simulation and inserting them to the
|
||||
thread group. */
|
||||
|
||||
void
|
||||
SimResults::simulate(int num_sim, const DecisionRule &dr, const Vector &start,
|
||||
const TwoDMatrix &vcov)
|
||||
{
|
||||
std::vector<RandomShockRealization> rsrs;
|
||||
rsrs.reserve(num_sim);
|
||||
|
||||
sthread::detach_thread_group gr;
|
||||
for (int i = 0; i < num_sim; i++)
|
||||
{
|
||||
RandomShockRealization sr(vcov, seed_generator::get_new_seed());
|
||||
rsrs.push_back(sr);
|
||||
gr.insert(std::make_unique<SimulationWorker>(*this, dr, DecisionRule::emethod::horner,
|
||||
num_per+num_burn, start, rsrs.back()));
|
||||
}
|
||||
gr.run();
|
||||
}
|
||||
|
||||
/* This adds the data with the realized shocks. It takes only periods
|
||||
which are not to be burnt. If the data is not finite, the both data
|
||||
and shocks are thrown away. */
|
||||
|
||||
bool
|
||||
SimResults::addDataSet(const TwoDMatrix &d, const ExplicitShockRealization &sr, const ConstVector &st)
|
||||
{
|
||||
KORD_RAISE_IF(d.nrows() != num_y,
|
||||
"Incompatible number of rows for SimResults::addDataSets");
|
||||
KORD_RAISE_IF(d.ncols() != num_per+num_burn,
|
||||
"Incompatible number of cols for SimResults::addDataSets");
|
||||
bool ret = false;
|
||||
if (d.isFinite())
|
||||
{
|
||||
data.emplace_back(d, num_burn, num_per);
|
||||
shocks.emplace_back(ConstTwoDMatrix(sr.getShocks(), num_burn, num_per));
|
||||
if (num_burn == 0)
|
||||
start.emplace_back(st);
|
||||
else
|
||||
start.emplace_back(d.getCol(num_burn-1));
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
SimResults::writeMat(const std::string &base, const std::string &lname) const
|
||||
{
|
||||
std::string matfile_name = base + ".mat";
|
||||
mat_t *matfd = Mat_Create(matfile_name.c_str(), nullptr);
|
||||
if (matfd)
|
||||
{
|
||||
writeMat(matfd, lname);
|
||||
Mat_Close(matfd);
|
||||
}
|
||||
}
|
||||
|
||||
/* This save the results as matrices with given prefix and with index
|
||||
appended. If there is only one matrix, the index is not appended. */
|
||||
|
||||
void
|
||||
SimResults::writeMat(mat_t *fd, const std::string &lname) const
|
||||
{
|
||||
for (int i = 0; i < getNumSets(); i++)
|
||||
{
|
||||
std::string tmp = lname + "_data";
|
||||
if (getNumSets() > 1)
|
||||
tmp += std::to_string(i+1);
|
||||
data[i].writeMat(fd, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SimResultsStats::simulate(int num_sim, const DecisionRule &dr,
|
||||
const Vector &start,
|
||||
const TwoDMatrix &vcov, Journal &journal)
|
||||
{
|
||||
SimResults::simulate(num_sim, dr, start, vcov, journal);
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Calculating means from the simulations." << endrec;
|
||||
calcMean();
|
||||
}
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Calculating covariances from the simulations." << endrec;
|
||||
calcVcov();
|
||||
}
|
||||
}
|
||||
|
||||
/* Here we do not save the data itself, we save only mean and vcov. */
|
||||
void
|
||||
SimResultsStats::writeMat(mat_t *fd, const std::string &lname) const
|
||||
{
|
||||
ConstTwoDMatrix(num_y, 1, mean).writeMat(fd, lname + "_mean");;
|
||||
vcov.writeMat(fd, lname + "_vcov");
|
||||
}
|
||||
|
||||
void
|
||||
SimResultsStats::calcMean()
|
||||
{
|
||||
mean.zeros();
|
||||
if (data.size()*num_per > 0)
|
||||
{
|
||||
double mult = 1.0/data.size()/num_per;
|
||||
for (const auto &i : data)
|
||||
{
|
||||
for (int j = 0; j < num_per; j++)
|
||||
{
|
||||
ConstVector col{i.getCol(j)};
|
||||
mean.add(mult, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SimResultsStats::calcVcov()
|
||||
{
|
||||
if (data.size()*num_per > 1)
|
||||
{
|
||||
vcov.zeros();
|
||||
double mult = 1.0/(data.size()*num_per - 1);
|
||||
for (const auto &d : data)
|
||||
for (int j = 0; j < num_per; j++)
|
||||
for (int m = 0; m < num_y; m++)
|
||||
for (int n = m; n < num_y; n++)
|
||||
{
|
||||
double s = (d.get(m, j)-mean[m])*(d.get(n, j)-mean[n]);
|
||||
vcov.get(m, n) += mult*s;
|
||||
if (m != n)
|
||||
vcov.get(n, m) += mult*s;
|
||||
}
|
||||
}
|
||||
else
|
||||
vcov.infs();
|
||||
}
|
||||
|
||||
void
|
||||
SimResultsDynamicStats::simulate(int num_sim, const DecisionRule &dr,
|
||||
const Vector &start,
|
||||
const TwoDMatrix &vcov, Journal &journal)
|
||||
{
|
||||
SimResults::simulate(num_sim, dr, start, vcov, journal);
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Calculating means of the conditional simulations." << endrec;
|
||||
calcMean();
|
||||
}
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Calculating variances of the conditional simulations." << endrec;
|
||||
calcVariance();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SimResultsDynamicStats::writeMat(mat_t *fd, const std::string &lname) const
|
||||
{
|
||||
mean.writeMat(fd, lname + "_cond_mean");
|
||||
variance.writeMat(fd, lname + "_cond_variance");
|
||||
}
|
||||
|
||||
void
|
||||
SimResultsDynamicStats::calcMean()
|
||||
{
|
||||
mean.zeros();
|
||||
if (data.size() > 0)
|
||||
{
|
||||
double mult = 1.0/data.size();
|
||||
for (int j = 0; j < num_per; j++)
|
||||
{
|
||||
Vector meanj{mean.getCol(j)};
|
||||
for (const auto &i : data)
|
||||
{
|
||||
ConstVector col{i.getCol(j)};
|
||||
meanj.add(mult, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SimResultsDynamicStats::calcVariance()
|
||||
{
|
||||
if (data.size() > 1)
|
||||
{
|
||||
variance.zeros();
|
||||
double mult = 1.0/(data.size()-1);
|
||||
for (int j = 0; j < num_per; j++)
|
||||
{
|
||||
ConstVector meanj{mean.getCol(j)};
|
||||
Vector varj{variance.getCol(j)};
|
||||
for (const auto &i : data)
|
||||
{
|
||||
Vector col{i.getCol(j)};
|
||||
col.add(-1.0, meanj);
|
||||
for (int k = 0; k < col.length(); k++)
|
||||
col[k] = col[k]*col[k];
|
||||
varj.add(mult, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
variance.infs();
|
||||
}
|
||||
|
||||
void
|
||||
SimResultsIRF::simulate(const DecisionRule &dr, Journal &journal)
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Performing " << control.getNumSets() << " IRF simulations for "
|
||||
<< num_per << " periods; shock=" << ishock << ", impulse=" << imp << endrec;
|
||||
simulate(dr);
|
||||
int thrown = control.getNumSets() - data.size();
|
||||
if (thrown > 0)
|
||||
{
|
||||
JournalRecord rec(journal);
|
||||
rec << "I had to throw " << thrown
|
||||
<< " simulations away due to Nan or Inf" << endrec;
|
||||
}
|
||||
calcMeans();
|
||||
calcVariances();
|
||||
}
|
||||
|
||||
void
|
||||
SimResultsIRF::simulate(const DecisionRule &dr)
|
||||
{
|
||||
sthread::detach_thread_group gr;
|
||||
for (int idata = 0; idata < control.getNumSets(); idata++)
|
||||
gr.insert(std::make_unique<SimulationIRFWorker>(*this, dr, DecisionRule::emethod::horner,
|
||||
num_per, idata, ishock, imp));
|
||||
gr.run();
|
||||
}
|
||||
|
||||
void
|
||||
SimResultsIRF::calcMeans()
|
||||
{
|
||||
means.zeros();
|
||||
if (data.size() > 0)
|
||||
{
|
||||
for (const auto &i : data)
|
||||
means.add(1.0, i);
|
||||
means.mult(1.0/data.size());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SimResultsIRF::calcVariances()
|
||||
{
|
||||
if (data.size() > 1)
|
||||
{
|
||||
variances.zeros();
|
||||
for (const auto &i : data)
|
||||
{
|
||||
TwoDMatrix d(i);
|
||||
d.add(-1.0, means);
|
||||
for (int j = 0; j < d.nrows(); j++)
|
||||
for (int k = 0; k < d.ncols(); k++)
|
||||
variances.get(j, k) += d.get(j, k)*d.get(j, k);
|
||||
d.mult(1.0/(data.size()-1));
|
||||
}
|
||||
}
|
||||
else
|
||||
variances.infs();
|
||||
}
|
||||
|
||||
void
|
||||
SimResultsIRF::writeMat(mat_t *fd, const std::string &lname) const
|
||||
{
|
||||
means.writeMat(fd, lname + "_mean");
|
||||
variances.writeMat(fd, lname + "_var");
|
||||
}
|
||||
|
||||
void
|
||||
RTSimResultsStats::simulate(int num_sim, const DecisionRule &dr, const Vector &start,
|
||||
const TwoDMatrix &v, Journal &journal)
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Performing " << num_sim << " real-time stochastic simulations for "
|
||||
<< num_per << " periods" << endrec;
|
||||
simulate(num_sim, dr, start, v);
|
||||
mean = nc.getMean();
|
||||
mean.add(1.0, dr.getSteady());
|
||||
nc.getVariance(vcov);
|
||||
if (thrown_periods > 0)
|
||||
{
|
||||
JournalRecord rec(journal);
|
||||
rec << "I had to throw " << thrown_periods << " periods away due to Nan or Inf" << endrec;
|
||||
JournalRecord rec1(journal);
|
||||
rec1 << "This affected " << incomplete_simulations << " out of "
|
||||
<< num_sim << " simulations" << endrec;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RTSimResultsStats::simulate(int num_sim, const DecisionRule &dr, const Vector &start,
|
||||
const TwoDMatrix &vcov)
|
||||
{
|
||||
std::vector<RandomShockRealization> rsrs;
|
||||
rsrs.reserve(num_sim);
|
||||
|
||||
sthread::detach_thread_group gr;
|
||||
for (int i = 0; i < num_sim; i++)
|
||||
{
|
||||
RandomShockRealization sr(vcov, seed_generator::get_new_seed());
|
||||
rsrs.push_back(sr);
|
||||
gr.insert(std::make_unique<RTSimulationWorker>(*this, dr, DecisionRule::emethod::horner,
|
||||
num_per, start, rsrs.back()));
|
||||
}
|
||||
gr.run();
|
||||
}
|
||||
|
||||
void
|
||||
RTSimResultsStats::writeMat(mat_t *fd, const std::string &lname)
|
||||
{
|
||||
ConstTwoDMatrix(nc.getDim(), 1, mean).writeMat(fd, lname + "_rt_mean");
|
||||
vcov.writeMat(fd, lname + "_rt_vcov");
|
||||
}
|
||||
|
||||
IRFResults::IRFResults(const DynamicModel &mod, const DecisionRule &dr,
|
||||
const SimResults &control, std::vector<int> ili,
|
||||
Journal &journal)
|
||||
: model(mod), irf_list_ind(std::move(ili))
|
||||
{
|
||||
int num_per = control.getNumPer();
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Calculating IRFs against control for " << static_cast<int>(irf_list_ind.size()) << " shocks and for "
|
||||
<< num_per << " periods" << endrec;
|
||||
const TwoDMatrix &vcov = mod.getVcov();
|
||||
for (int ishock : irf_list_ind)
|
||||
{
|
||||
double stderror = sqrt(vcov.get(ishock, ishock));
|
||||
irf_res.emplace_back(control, model.numeq(), num_per,
|
||||
ishock, stderror);
|
||||
irf_res.emplace_back(control, model.numeq(), num_per,
|
||||
ishock, -stderror);
|
||||
}
|
||||
|
||||
for (unsigned int ii = 0; ii < irf_list_ind.size(); ii++)
|
||||
{
|
||||
irf_res[2*ii].simulate(dr, journal);
|
||||
irf_res[2*ii+1].simulate(dr, journal);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IRFResults::writeMat(mat_t *fd, const std::string &prefix) const
|
||||
{
|
||||
for (unsigned int i = 0; i < irf_list_ind.size(); i++)
|
||||
{
|
||||
int ishock = irf_list_ind[i];
|
||||
auto shockname = model.getExogNames().getName(ishock);
|
||||
irf_res[2*i].writeMat(fd, prefix + "_irfp_" + shockname);
|
||||
irf_res[2*i+1].writeMat(fd, prefix + "_irfm_" + shockname);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SimulationWorker::operator()(std::mutex &mut)
|
||||
{
|
||||
ExplicitShockRealization esr(sr, np);
|
||||
TwoDMatrix m{dr.simulate(em, np, st, esr)};
|
||||
{
|
||||
std::unique_lock<std::mutex> lk{mut};
|
||||
res.addDataSet(m, esr, st);
|
||||
}
|
||||
}
|
||||
|
||||
/* Here we create a new instance of ExplicitShockRealization of the
|
||||
corresponding control, add the impulse, and simulate. */
|
||||
|
||||
void
|
||||
SimulationIRFWorker::operator()(std::mutex &mut)
|
||||
{
|
||||
ExplicitShockRealization esr(res.control.getShocks(idata));
|
||||
esr.addToShock(ishock, 0, imp);
|
||||
TwoDMatrix m{dr.simulate(em, np, res.control.getStart(idata), esr)};
|
||||
m.add(-1.0, res.control.getData(idata));
|
||||
{
|
||||
std::unique_lock<std::mutex> lk{mut};
|
||||
res.addDataSet(m, esr, res.control.getStart(idata));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RTSimulationWorker::operator()(std::mutex &mut)
|
||||
{
|
||||
NormalConj nc(res.nc.getDim());
|
||||
const PartitionY &ypart = dr.getYPart();
|
||||
int nu = dr.nexog();
|
||||
const Vector &ysteady = dr.getSteady();
|
||||
|
||||
// initialize vectors and subvectors for simulation
|
||||
Vector dyu(ypart.nys()+nu);
|
||||
ConstVector ystart_pred(ystart, ypart.nstat, ypart.nys());
|
||||
ConstVector ysteady_pred(ysteady, ypart.nstat, ypart.nys());
|
||||
Vector dy(dyu, 0, ypart.nys());
|
||||
Vector u(dyu, ypart.nys(), nu);
|
||||
Vector y(nc.getDim());
|
||||
ConstVector ypred(y, ypart.nstat, ypart.nys());
|
||||
|
||||
// simulate the first real-time period
|
||||
int ip = 0;
|
||||
dy = ystart_pred;
|
||||
dy.add(-1.0, ysteady_pred);
|
||||
sr.get(ip, u);
|
||||
dr.eval(em, y, dyu);
|
||||
if (ip >= res.num_burn)
|
||||
nc.update(y);
|
||||
|
||||
// simulate other real-time periods
|
||||
while (y.isFinite() && ip < res.num_burn + res.num_per)
|
||||
{
|
||||
ip++;
|
||||
dy = ypred;
|
||||
sr.get(ip, u);
|
||||
dr.eval(em, y, dyu);
|
||||
if (ip >= res.num_burn)
|
||||
nc.update(y);
|
||||
}
|
||||
{
|
||||
std::unique_lock<std::mutex> lk{mut};
|
||||
res.nc.update(nc);
|
||||
if (res.num_per-ip > 0)
|
||||
{
|
||||
res.incomplete_simulations++;
|
||||
res.thrown_periods += res.num_per-ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This calculates factorization FFᵀ=V in the Cholesky way. It does
|
||||
not work for semidefinite matrices. */
|
||||
|
||||
void
|
||||
RandomShockRealization::choleskyFactor(const ConstTwoDMatrix &v)
|
||||
{
|
||||
factor = v;
|
||||
lapack_int rows = factor.nrows(), lda = factor.getLD();
|
||||
for (int i = 0; i < rows; i++)
|
||||
for (int j = i+1; j < rows; j++)
|
||||
factor.get(i, j) = 0.0;
|
||||
lapack_int info;
|
||||
|
||||
dpotrf("L", &rows, factor.base(), &lda, &info);
|
||||
KORD_RAISE_IF(info != 0,
|
||||
"Info!=0 in RandomShockRealization::choleskyFactor");
|
||||
}
|
||||
|
||||
/* This calculates FFᵀ=V factorization by symmetric Schur
|
||||
decomposition. It works for semidefinite matrices. */
|
||||
|
||||
void
|
||||
RandomShockRealization::schurFactor(const ConstTwoDMatrix &v)
|
||||
{
|
||||
SymSchurDecomp(v).getFactor(factor);
|
||||
}
|
||||
|
||||
void
|
||||
RandomShockRealization::get(int n, Vector &out)
|
||||
{
|
||||
KORD_RAISE_IF(out.length() != numShocks(),
|
||||
"Wrong length of out vector in RandomShockRealization::get");
|
||||
Vector d(out.length());
|
||||
for (int i = 0; i < d.length(); i++)
|
||||
d[i] = dis(mtwister);
|
||||
out.zeros();
|
||||
factor.multaVec(out, ConstVector(d));
|
||||
}
|
||||
|
||||
ExplicitShockRealization::ExplicitShockRealization(ShockRealization &sr,
|
||||
int num_per)
|
||||
: shocks(sr.numShocks(), num_per)
|
||||
{
|
||||
for (int j = 0; j < num_per; j++)
|
||||
{
|
||||
Vector jcol{shocks.getCol(j)};
|
||||
sr.get(j, jcol);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ExplicitShockRealization::get(int n, Vector &out)
|
||||
{
|
||||
KORD_RAISE_IF(out.length() != numShocks(),
|
||||
"Wrong length of out vector in ExplicitShockRealization::get");
|
||||
int i = n % shocks.ncols();
|
||||
ConstVector icol{shocks.getCol(i)};
|
||||
out = icol;
|
||||
}
|
||||
|
||||
void
|
||||
ExplicitShockRealization::addToShock(int ishock, int iper, double val)
|
||||
{
|
||||
KORD_RAISE_IF(ishock < 0 || ishock > numShocks(),
|
||||
"Wrong index of shock in ExplicitShockRealization::addToShock");
|
||||
int j = iper % shocks.ncols();
|
||||
shocks.get(ishock, j) += val;
|
||||
}
|
||||
|
||||
void
|
||||
GenShockRealization::get(int n, Vector &out)
|
||||
{
|
||||
KORD_RAISE_IF(out.length() != numShocks(),
|
||||
"Wrong length of out vector in GenShockRealization::get");
|
||||
ExplicitShockRealization::get(n, out);
|
||||
Vector r(numShocks());
|
||||
RandomShockRealization::get(n, r);
|
||||
for (int j = 0; j < numShocks(); j++)
|
||||
if (!std::isfinite(out[j]))
|
||||
out[j] = r[j];
|
||||
}
|
|
@ -1,697 +0,0 @@
|
|||
@q $Id: decision_rule.cweb 1896 2008-06-24 04:01:05Z kamenik $ @>
|
||||
@q Copyright 2004, Ondra Kamenik @>
|
||||
|
||||
@ Start of {\tt decision\_rule.cpp} file.
|
||||
@c
|
||||
|
||||
#include "kord_exception.h"
|
||||
#include "decision_rule.h"
|
||||
#include "dynamic_model.h"
|
||||
|
||||
#include "SymSchurDecomp.h"
|
||||
|
||||
#include <dynlapack.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
template <>
|
||||
int DRFixPoint<KOrder::fold>::max_iter = 10000;
|
||||
template <>
|
||||
int DRFixPoint<KOrder::unfold>::max_iter = 10000;
|
||||
template <>
|
||||
double DRFixPoint<KOrder::fold>::tol = 1.e-10;
|
||||
template <>
|
||||
double DRFixPoint<KOrder::unfold>::tol = 1.e-10;
|
||||
template <>
|
||||
int DRFixPoint<KOrder::fold>::max_newton_iter = 50;
|
||||
template <>
|
||||
int DRFixPoint<KOrder::unfold>::max_newton_iter = 50;
|
||||
template <>
|
||||
int DRFixPoint<KOrder::fold>::newton_pause = 100;
|
||||
template <>
|
||||
int DRFixPoint<KOrder::unfold>::newton_pause = 100;
|
||||
@#
|
||||
@<|FoldDecisionRule| conversion from |UnfoldDecisionRule|@>;
|
||||
@<|UnfoldDecisionRule| conversion from |FoldDecisionRule|@>;
|
||||
@<|SimResults| destructor@>;
|
||||
@<|SimResults::simulate| code1@>;
|
||||
@<|SimResults::simulate| code2@>;
|
||||
@<|SimResults::addDataSet| code@>;
|
||||
@<|SimResults::writeMat| code1@>;
|
||||
@<|SimResults::writeMat| code2@>;
|
||||
@<|SimResultsStats::simulate| code@>;
|
||||
@<|SimResultsStats::writeMat| code@>;
|
||||
@<|SimResultsStats::calcMean| code@>;
|
||||
@<|SimResultsStats::calcVcov| code@>;
|
||||
@<|SimResultsDynamicStats::simulate| code@>;
|
||||
@<|SimResultsDynamicStats::writeMat| code@>;
|
||||
@<|SimResultsDynamicStats::calcMean| code@>;
|
||||
@<|SimResultsDynamicStats::calcVariance| code@>;
|
||||
@<|SimResultsIRF::simulate| code1@>;
|
||||
@<|SimResultsIRF::simulate| code2@>;
|
||||
@<|SimResultsIRF::calcMeans| code@>;
|
||||
@<|SimResultsIRF::calcVariances| code@>;
|
||||
@<|SimResultsIRF::writeMat| code@>;
|
||||
@<|RTSimResultsStats::simulate| code1@>;
|
||||
@<|RTSimResultsStats::simulate| code2@>;
|
||||
@<|RTSimResultsStats::writeMat| code@>;
|
||||
@<|IRFResults| constructor@>;
|
||||
@<|IRFResults| destructor@>;
|
||||
@<|IRFResults::writeMat| code@>;
|
||||
@<|SimulationWorker::operator()()| code@>;
|
||||
@<|SimulationIRFWorker::operator()()| code@>;
|
||||
@<|RTSimulationWorker::operator()()| code@>;
|
||||
@<|RandomShockRealization::choleskyFactor| code@>;
|
||||
@<|RandomShockRealization::schurFactor| code@>;
|
||||
@<|RandomShockRealization::get| code@>;
|
||||
@<|ExplicitShockRealization| constructor code@>;
|
||||
@<|ExplicitShockRealization::get| code@>;
|
||||
@<|ExplicitShockRealization::addToShock| code@>;
|
||||
@<|GenShockRealization::get| code@>;
|
||||
|
||||
@
|
||||
@<|FoldDecisionRule| conversion from |UnfoldDecisionRule|@>=
|
||||
FoldDecisionRule::FoldDecisionRule(const UnfoldDecisionRule& udr)
|
||||
: DecisionRuleImpl<KOrder::fold>(ctraits<KOrder::fold>::Tpol(udr.nrows(), udr.nvars()),
|
||||
udr.ypart, udr.nu, udr.ysteady)
|
||||
{
|
||||
for (ctraits<KOrder::unfold>::Tpol::const_iterator it = udr.begin();
|
||||
it != udr.end(); ++it) {
|
||||
insert(new ctraits<KOrder::fold>::Ttensym(*((*it).second)));
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|UnfoldDecisionRule| conversion from |FoldDecisionRule|@>=
|
||||
UnfoldDecisionRule::UnfoldDecisionRule(const FoldDecisionRule& fdr)
|
||||
: DecisionRuleImpl<KOrder::unfold>(ctraits<KOrder::unfold>::Tpol(fdr.nrows(), fdr.nvars()),
|
||||
fdr.ypart, fdr.nu, fdr.ysteady)
|
||||
{
|
||||
for (ctraits<KOrder::fold>::Tpol::const_iterator it = fdr.begin();
|
||||
it != fdr.end(); ++it) {
|
||||
insert(new ctraits<KOrder::unfold>::Ttensym(*((*it).second)));
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResults| destructor@>=
|
||||
SimResults::~SimResults()
|
||||
{
|
||||
for (int i = 0; i < getNumSets(); i++) {
|
||||
delete data[i];
|
||||
delete shocks[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ This runs simulations with an output to journal file. Note that we
|
||||
report how many simulations had to be thrown out due to Nan or Inf.
|
||||
|
||||
@<|SimResults::simulate| code1@>=
|
||||
void SimResults::simulate(int num_sim, const DecisionRule& dr, const Vector& start,
|
||||
const TwoDMatrix& vcov, Journal& journal)
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Performing " << num_sim << " stochastic simulations for "
|
||||
<< num_per << " periods burning " << num_burn << " initial periods" << endrec;
|
||||
simulate(num_sim, dr, start, vcov);
|
||||
int thrown = num_sim - data.size();
|
||||
if (thrown > 0) {
|
||||
JournalRecord rec(journal);
|
||||
rec << "I had to throw " << thrown << " simulations away due to Nan or Inf" << endrec;
|
||||
}
|
||||
}
|
||||
|
||||
@ This runs a given number of simulations by creating
|
||||
|SimulationWorker| for each simulation and inserting them to the
|
||||
thread group.
|
||||
|
||||
@<|SimResults::simulate| code2@>=
|
||||
void SimResults::simulate(int num_sim, const DecisionRule& dr, const Vector& start,
|
||||
const TwoDMatrix& vcov)
|
||||
{
|
||||
std::vector<RandomShockRealization> rsrs;
|
||||
rsrs.reserve(num_sim);
|
||||
|
||||
THREAD_GROUP gr;
|
||||
for (int i = 0; i < num_sim; i++) {
|
||||
RandomShockRealization sr(vcov, system_random_generator.int_uniform());
|
||||
rsrs.push_back(sr);
|
||||
THREAD* worker = new
|
||||
SimulationWorker(*this, dr, DecisionRule::horner,
|
||||
num_per+num_burn, start, rsrs.back());
|
||||
gr.insert(worker);
|
||||
}
|
||||
gr.run();
|
||||
}
|
||||
|
||||
@ This adds the data with the realized shocks. It takes only periods
|
||||
which are not to be burnt. If the data is not finite, the both data
|
||||
and shocks are thrown away.
|
||||
|
||||
@<|SimResults::addDataSet| code@>=
|
||||
bool SimResults::addDataSet(TwoDMatrix* d, ExplicitShockRealization* sr)
|
||||
{
|
||||
KORD_RAISE_IF(d->nrows() != num_y,
|
||||
"Incompatible number of rows for SimResults::addDataSets");
|
||||
KORD_RAISE_IF(d->ncols() != num_per+num_burn,
|
||||
"Incompatible number of cols for SimResults::addDataSets");
|
||||
bool ret = false;
|
||||
if (d->isFinite()) {
|
||||
data.push_back(new TwoDMatrix((const TwoDMatrix&)(*d),num_burn,num_per));
|
||||
shocks.push_back(new ExplicitShockRealization(
|
||||
ConstTwoDMatrix(sr->getShocks(),num_burn,num_per)));
|
||||
ret = true;
|
||||
}
|
||||
|
||||
delete d;
|
||||
delete sr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResults::writeMat| code1@>=
|
||||
void SimResults::writeMat(const char* base, const char* lname) const
|
||||
{
|
||||
char matfile_name[100];
|
||||
sprintf(matfile_name, "%s.mat", base);
|
||||
mat_t* matfd = Mat_Create(matfile_name, NULL);
|
||||
if (matfd != NULL) {
|
||||
writeMat(matfd, lname);
|
||||
Mat_Close(matfd);
|
||||
}
|
||||
}
|
||||
|
||||
@ This save the results as matrices with given prefix and with index
|
||||
appended. If there is only one matrix, the index is not appended.
|
||||
|
||||
@<|SimResults::writeMat| code2@>=
|
||||
void SimResults::writeMat(mat_t* fd, const char* lname) const
|
||||
{
|
||||
char tmp[100];
|
||||
for (int i = 0; i < getNumSets(); i++) {
|
||||
if (getNumSets() > 1)
|
||||
sprintf(tmp, "%s_data%d", lname, i+1);
|
||||
else
|
||||
sprintf(tmp, "%s_data", lname);
|
||||
ConstTwoDMatrix m(*(data[i]));
|
||||
m.writeMat(fd, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResultsStats::simulate| code@>=
|
||||
void SimResultsStats::simulate(int num_sim, const DecisionRule& dr,
|
||||
const Vector& start,
|
||||
const TwoDMatrix& vcov, Journal& journal)
|
||||
{
|
||||
SimResults::simulate(num_sim, dr, start, vcov, journal);
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Calculating means from the simulations." << endrec;
|
||||
calcMean();
|
||||
}
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Calculating covariances from the simulations." << endrec;
|
||||
calcVcov();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ Here we do not save the data itself, we save only mean and vcov.
|
||||
@<|SimResultsStats::writeMat| code@>=
|
||||
void SimResultsStats::writeMat(mat_t* fd, const char* lname) const
|
||||
{
|
||||
char tmp[100];
|
||||
sprintf(tmp, "%s_mean", lname);
|
||||
ConstTwoDMatrix m(num_y, 1, mean.base());
|
||||
m.writeMat(fd, tmp);
|
||||
sprintf(tmp, "%s_vcov", lname);
|
||||
ConstTwoDMatrix(vcov).writeMat(fd, tmp);
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResultsStats::calcMean| code@>=
|
||||
void SimResultsStats::calcMean()
|
||||
{
|
||||
mean.zeros();
|
||||
if (data.size()*num_per > 0) {
|
||||
double mult = 1.0/data.size()/num_per;
|
||||
for (unsigned int i = 0; i < data.size(); i++) {
|
||||
for (int j = 0; j < num_per; j++) {
|
||||
ConstVector col(*data[i], j);
|
||||
mean.add(mult, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResultsStats::calcVcov| code@>=
|
||||
void SimResultsStats::calcVcov()
|
||||
{
|
||||
if (data.size()*num_per > 1) {
|
||||
vcov.zeros();
|
||||
double mult = 1.0/(data.size()*num_per - 1);
|
||||
for (unsigned int i = 0; i < data.size(); i++) {
|
||||
const TwoDMatrix& d = *(data[i]);
|
||||
for (int j = 0; j < num_per; j++) {
|
||||
for (int m = 0; m < num_y; m++) {
|
||||
for (int n = m; n < num_y; n++) {
|
||||
double s = (d.get(m,j)-mean[m])*(d.get(n,j)-mean[n]);
|
||||
vcov.get(m,n) += mult*s;
|
||||
if (m != n)
|
||||
vcov.get(n,m) += mult*s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vcov.infs();
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResultsDynamicStats::simulate| code@>=
|
||||
void SimResultsDynamicStats::simulate(int num_sim, const DecisionRule& dr,
|
||||
const Vector& start,
|
||||
const TwoDMatrix& vcov, Journal& journal)
|
||||
{
|
||||
SimResults::simulate(num_sim, dr, start, vcov, journal);
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Calculating means of the conditional simulations." << endrec;
|
||||
calcMean();
|
||||
}
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Calculating variances of the conditional simulations." << endrec;
|
||||
calcVariance();
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResultsDynamicStats::writeMat| code@>=
|
||||
void SimResultsDynamicStats::writeMat(mat_t* fd, const char* lname) const
|
||||
{
|
||||
char tmp[100];
|
||||
sprintf(tmp, "%s_cond_mean", lname);
|
||||
ConstTwoDMatrix(mean).writeMat(fd, tmp);
|
||||
sprintf(tmp, "%s_cond_variance", lname);
|
||||
ConstTwoDMatrix(variance).writeMat(fd, tmp);
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResultsDynamicStats::calcMean| code@>=
|
||||
void SimResultsDynamicStats::calcMean()
|
||||
{
|
||||
mean.zeros();
|
||||
if (data.size() > 0) {
|
||||
double mult = 1.0/data.size();
|
||||
for (int j = 0; j < num_per; j++) {
|
||||
Vector meanj(mean, j);
|
||||
for (unsigned int i = 0; i < data.size(); i++) {
|
||||
ConstVector col(*data[i], j);
|
||||
meanj.add(mult, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResultsDynamicStats::calcVariance| code@>=
|
||||
void SimResultsDynamicStats::calcVariance()
|
||||
{
|
||||
if (data.size() > 1) {
|
||||
variance.zeros();
|
||||
double mult = 1.0/(data.size()-1);
|
||||
for (int j = 0; j < num_per; j++) {
|
||||
ConstVector meanj(mean, j);
|
||||
Vector varj(variance, j);
|
||||
for (int i = 0; i < (int)data.size(); i++) {
|
||||
Vector col(ConstVector((*data[i]), j));
|
||||
col.add(-1.0, meanj);
|
||||
for (int k = 0; k < col.length(); k++)
|
||||
col[k] = col[k]*col[k];
|
||||
varj.add(mult, col);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
variance.infs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@
|
||||
@<|SimResultsIRF::simulate| code1@>=
|
||||
void SimResultsIRF::simulate(const DecisionRule& dr, Journal& journal)
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Performing " << control.getNumSets() << " IRF simulations for "
|
||||
<< num_per << " periods; shock=" << ishock << ", impulse=" << imp << endrec;
|
||||
simulate(dr);
|
||||
int thrown = control.getNumSets() - data.size();
|
||||
if (thrown > 0) {
|
||||
JournalRecord rec(journal);
|
||||
rec << "I had to throw " << thrown
|
||||
<< " simulations away due to Nan or Inf" << endrec;
|
||||
}
|
||||
calcMeans();
|
||||
calcVariances();
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResultsIRF::simulate| code2@>=
|
||||
void SimResultsIRF::simulate(const DecisionRule& dr)
|
||||
{
|
||||
THREAD_GROUP gr;
|
||||
for (int idata = 0; idata < control.getNumSets(); idata++) {
|
||||
THREAD* worker = new
|
||||
SimulationIRFWorker(*this, dr, DecisionRule::horner,
|
||||
num_per, idata, ishock, imp);
|
||||
gr.insert(worker);
|
||||
}
|
||||
gr.run();
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResultsIRF::calcMeans| code@>=
|
||||
void SimResultsIRF::calcMeans()
|
||||
{
|
||||
means.zeros();
|
||||
if (data.size() > 0) {
|
||||
for (unsigned int i = 0; i < data.size(); i++)
|
||||
means.add(1.0, *(data[i]));
|
||||
means.mult(1.0/data.size());
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResultsIRF::calcVariances| code@>=
|
||||
void SimResultsIRF::calcVariances()
|
||||
{
|
||||
if (data.size() > 1) {
|
||||
variances.zeros();
|
||||
for (unsigned int i = 0; i < data.size(); i++) {
|
||||
TwoDMatrix d((const TwoDMatrix&)(*(data[i])));
|
||||
d.add(-1.0, means);
|
||||
for (int j = 0; j < d.nrows(); j++)
|
||||
for (int k = 0; k < d.ncols(); k++)
|
||||
variances.get(j,k) += d.get(j,k)*d.get(j,k);
|
||||
d.mult(1.0/(data.size()-1));
|
||||
}
|
||||
} else {
|
||||
variances.infs();
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimResultsIRF::writeMat| code@>=
|
||||
void SimResultsIRF::writeMat(mat_t* fd, const char* lname) const
|
||||
{
|
||||
char tmp[100];
|
||||
sprintf(tmp, "%s_mean", lname);
|
||||
means.writeMat(fd, tmp);
|
||||
sprintf(tmp, "%s_var", lname);
|
||||
variances.writeMat(fd, tmp);
|
||||
}
|
||||
|
||||
@
|
||||
@<|RTSimResultsStats::simulate| code1@>=
|
||||
void RTSimResultsStats::simulate(int num_sim, const DecisionRule& dr, const Vector& start,
|
||||
const TwoDMatrix& v, Journal& journal)
|
||||
{
|
||||
JournalRecordPair paa(journal);
|
||||
paa << "Performing " << num_sim << " real-time stochastic simulations for "
|
||||
<< num_per << " periods" << endrec;
|
||||
simulate(num_sim, dr, start, v);
|
||||
mean = nc.getMean();
|
||||
mean.add(1.0, dr.getSteady());
|
||||
nc.getVariance(vcov);
|
||||
if (thrown_periods > 0) {
|
||||
JournalRecord rec(journal);
|
||||
rec << "I had to throw " << thrown_periods << " periods away due to Nan or Inf" << endrec;
|
||||
JournalRecord rec1(journal);
|
||||
rec1 << "This affected " << incomplete_simulations << " out of "
|
||||
<< num_sim << " simulations" << endrec;
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|RTSimResultsStats::simulate| code2@>=
|
||||
void RTSimResultsStats::simulate(int num_sim, const DecisionRule& dr, const Vector& start,
|
||||
const TwoDMatrix& vcov)
|
||||
{
|
||||
std::vector<RandomShockRealization> rsrs;
|
||||
rsrs.reserve(num_sim);
|
||||
|
||||
THREAD_GROUP gr;
|
||||
for (int i = 0; i < num_sim; i++) {
|
||||
RandomShockRealization sr(vcov, system_random_generator.int_uniform());
|
||||
rsrs.push_back(sr);
|
||||
THREAD* worker = new
|
||||
RTSimulationWorker(*this, dr, DecisionRule::horner,
|
||||
num_per, start, rsrs.back());
|
||||
gr.insert(worker);
|
||||
}
|
||||
gr.run();
|
||||
}
|
||||
|
||||
@
|
||||
@<|RTSimResultsStats::writeMat| code@>=
|
||||
void RTSimResultsStats::writeMat(mat_t* fd, const char* lname)
|
||||
{
|
||||
char tmp[100];
|
||||
sprintf(tmp, "%s_rt_mean", lname);
|
||||
ConstTwoDMatrix m(nc.getDim(), 1, mean.base());
|
||||
m.writeMat(fd, tmp);
|
||||
sprintf(tmp, "%s_rt_vcov", lname);
|
||||
ConstTwoDMatrix(vcov).writeMat(fd, tmp);
|
||||
}
|
||||
|
||||
@
|
||||
@<|IRFResults| constructor@>=
|
||||
IRFResults::IRFResults(const DynamicModel& mod, const DecisionRule& dr,
|
||||
const SimResults& control, const vector<int>& ili,
|
||||
Journal& journal)
|
||||
: model(mod), irf_list_ind(ili)
|
||||
{
|
||||
int num_per = control.getNumPer();
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Calculating IRFs against control for " << (int)irf_list_ind.size() << " shocks and for "
|
||||
<< num_per << " periods" << endrec;
|
||||
const TwoDMatrix& vcov = mod.getVcov();
|
||||
for (unsigned int ii = 0; ii < irf_list_ind.size(); ii++) {
|
||||
int ishock = irf_list_ind[ii];
|
||||
double stderror = sqrt(vcov.get(ishock,ishock));
|
||||
irf_res.push_back(new SimResultsIRF(control, model.numeq(), num_per,
|
||||
ishock, stderror));
|
||||
irf_res.push_back(new SimResultsIRF(control, model.numeq(), num_per,
|
||||
ishock, -stderror));
|
||||
}
|
||||
|
||||
for (unsigned int ii = 0; ii < irf_list_ind.size(); ii++) {
|
||||
irf_res[2*ii]->simulate(dr, journal);
|
||||
irf_res[2*ii+1]->simulate(dr, journal);
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|IRFResults| destructor@>=
|
||||
IRFResults::~IRFResults()
|
||||
{
|
||||
for (unsigned int i = 0; i < irf_res.size(); i++)
|
||||
delete irf_res[i];
|
||||
}
|
||||
|
||||
@
|
||||
@<|IRFResults::writeMat| code@>=
|
||||
void IRFResults::writeMat(mat_t* fd, const char* prefix) const
|
||||
{
|
||||
for (unsigned int i = 0; i < irf_list_ind.size(); i++) {
|
||||
char tmp[100];
|
||||
int ishock = irf_list_ind[i];
|
||||
const char* shockname = model.getExogNames().getName(ishock);
|
||||
sprintf(tmp, "%s_irfp_%s", prefix, shockname);
|
||||
irf_res[2*i]->writeMat(fd, tmp);
|
||||
sprintf(tmp, "%s_irfm_%s", prefix, shockname);
|
||||
irf_res[2*i+1]->writeMat(fd, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|SimulationWorker::operator()()| code@>=
|
||||
void SimulationWorker::operator()()
|
||||
{
|
||||
ExplicitShockRealization* esr = new ExplicitShockRealization(sr, np);
|
||||
TwoDMatrix* m = dr.simulate(em, np, st, *esr);
|
||||
{
|
||||
SYNCHRO syn(&res, "simulation");
|
||||
res.addDataSet(m, esr);
|
||||
}
|
||||
}
|
||||
|
||||
@ Here we create a new instance of |ExplicitShockRealization| of the
|
||||
corresponding control, add the impulse, and simulate.
|
||||
|
||||
@<|SimulationIRFWorker::operator()()| code@>=
|
||||
void SimulationIRFWorker::operator()()
|
||||
{
|
||||
ExplicitShockRealization* esr =
|
||||
new ExplicitShockRealization(res.control.getShocks(idata));
|
||||
esr->addToShock(ishock, 0, imp);
|
||||
const TwoDMatrix& data = res.control.getData(idata);
|
||||
ConstVector st(data, res.control.getNumBurn());
|
||||
TwoDMatrix* m = dr.simulate(em, np, st, *esr);
|
||||
m->add(-1.0, res.control.getData(idata));
|
||||
{
|
||||
SYNCHRO syn(&res, "simulation");
|
||||
res.addDataSet(m, esr);
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|RTSimulationWorker::operator()()| code@>=
|
||||
void RTSimulationWorker::operator()()
|
||||
{
|
||||
NormalConj nc(res.nc.getDim());
|
||||
const PartitionY& ypart = dr.getYPart();
|
||||
int nu = dr.nexog();
|
||||
const Vector& ysteady = dr.getSteady();
|
||||
|
||||
@<initialize vectors and subvectors for simulation@>;
|
||||
@<simulate the first real-time period@>;
|
||||
@<simulate other real-time periods@>;
|
||||
{
|
||||
SYNCHRO syn(&res, "rtsimulation");
|
||||
res.nc.update(nc);
|
||||
if (res.num_per-ip > 0) {
|
||||
res.incomplete_simulations++;
|
||||
res.thrown_periods += res.num_per-ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<initialize vectors and subvectors for simulation@>=
|
||||
Vector dyu(ypart.nys()+nu);
|
||||
ConstVector ystart_pred(ystart, ypart.nstat, ypart.nys());
|
||||
ConstVector ysteady_pred(ysteady, ypart.nstat, ypart.nys());
|
||||
Vector dy(dyu, 0, ypart.nys());
|
||||
Vector u(dyu, ypart.nys(), nu);
|
||||
Vector y(nc.getDim());
|
||||
ConstVector ypred(y, ypart.nstat, ypart.nys());
|
||||
|
||||
@
|
||||
@<simulate the first real-time period@>=
|
||||
int ip = 0;
|
||||
dy = ystart_pred;
|
||||
dy.add(-1.0, ysteady_pred);
|
||||
sr.get(ip, u);
|
||||
dr.eval(em, y, dyu);
|
||||
if (ip >= res.num_burn)
|
||||
nc.update(y);
|
||||
|
||||
@
|
||||
@<simulate other real-time periods@>=
|
||||
while (y.isFinite() && ip < res.num_burn + res.num_per) {
|
||||
ip++;
|
||||
dy = ypred;
|
||||
sr.get(ip, u);
|
||||
dr.eval(em, y, dyu);
|
||||
if (ip >= res.num_burn)
|
||||
nc.update(y);
|
||||
}
|
||||
|
||||
@ This calculates factorization $FF^T=V$ in the Cholesky way. It does
|
||||
not work for semidefinite matrices.
|
||||
|
||||
@<|RandomShockRealization::choleskyFactor| code@>=
|
||||
void RandomShockRealization::choleskyFactor(const TwoDMatrix& v)
|
||||
{
|
||||
factor = v;
|
||||
lapack_int rows = factor.nrows();
|
||||
for (int i = 0; i < rows; i++)
|
||||
for (int j = i+1; j < rows; j++)
|
||||
factor.get(i,j) = 0.0;
|
||||
lapack_int info;
|
||||
|
||||
dpotrf("L", &rows, factor.base(), &rows, &info);
|
||||
KORD_RAISE_IF(info != 0,
|
||||
"Info!=0 in RandomShockRealization::choleskyFactor");
|
||||
}
|
||||
|
||||
@ This calculates $FF^T=V$ factorization by symmetric Schur
|
||||
decomposition. It works for semidifinite matrices.
|
||||
|
||||
@<|RandomShockRealization::schurFactor| code@>=
|
||||
void RandomShockRealization::schurFactor(const TwoDMatrix& v)
|
||||
{
|
||||
SymSchurDecomp ssd(v);
|
||||
ssd.getFactor(factor);
|
||||
}
|
||||
|
||||
@
|
||||
@<|RandomShockRealization::get| code@>=
|
||||
void RandomShockRealization::get(int n, Vector& out)
|
||||
{
|
||||
KORD_RAISE_IF(out.length() != numShocks(),
|
||||
"Wrong length of out vector in RandomShockRealization::get");
|
||||
Vector d(out.length());
|
||||
for (int i = 0; i < d.length(); i++) {
|
||||
d[i] = mtwister.normal();
|
||||
}
|
||||
out.zeros();
|
||||
factor.multaVec(out, ConstVector(d));
|
||||
}
|
||||
|
||||
@
|
||||
@<|ExplicitShockRealization| constructor code@>=
|
||||
ExplicitShockRealization::ExplicitShockRealization(ShockRealization& sr,
|
||||
int num_per)
|
||||
: shocks(sr.numShocks(), num_per)
|
||||
{
|
||||
for (int j = 0; j < num_per; j++) {
|
||||
Vector jcol(shocks, j);
|
||||
sr.get(j, jcol);
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@<|ExplicitShockRealization::get| code@>=
|
||||
void ExplicitShockRealization::get(int n, Vector& out)
|
||||
{
|
||||
KORD_RAISE_IF(out.length() != numShocks(),
|
||||
"Wrong length of out vector in ExplicitShockRealization::get");
|
||||
int i = n % shocks.ncols();
|
||||
ConstVector icol(shocks, i);
|
||||
out = icol;
|
||||
}
|
||||
|
||||
@
|
||||
@<|ExplicitShockRealization::addToShock| code@>=
|
||||
void ExplicitShockRealization::addToShock(int ishock, int iper, double val)
|
||||
{
|
||||
KORD_RAISE_IF(ishock < 0 || ishock > numShocks(),
|
||||
"Wrong index of shock in ExplicitShockRealization::addToShock");
|
||||
int j = iper % shocks.ncols();
|
||||
shocks.get(ishock, j) += val;
|
||||
}
|
||||
|
||||
|
||||
@
|
||||
@<|GenShockRealization::get| code@>=
|
||||
void GenShockRealization::get(int n, Vector& out)
|
||||
{
|
||||
KORD_RAISE_IF(out.length() != numShocks(),
|
||||
"Wrong length of out vector in GenShockRealization::get");
|
||||
ExplicitShockRealization::get(n, out);
|
||||
Vector r(numShocks());
|
||||
RandomShockRealization::get(n, r);
|
||||
for (int j = 0; j < numShocks(); j++)
|
||||
if (! isfinite(out[j]))
|
||||
out[j] = r[j];
|
||||
}
|
||||
|
||||
|
||||
@ End of {\tt decision\_rule.cpp} file.
|
File diff suppressed because it is too large
Load Diff
|
@ -1,999 +0,0 @@
|
|||
@q $Id: decision_rule.hweb 2336 2009-01-14 10:37:02Z kamenik $ @>
|
||||
@q Copyright 2004, Ondra Kamenik @>
|
||||
|
||||
@*2 Decision rule and simulation. Start of {\tt decision\_rule.h} file.
|
||||
|
||||
The main purpose of this file is a decision rule representation which
|
||||
can run a simulation. So we define an interface for classes providing
|
||||
realizations of random shocks, and define the class
|
||||
|DecisionRule|. The latter basically takes tensor container of
|
||||
derivatives of policy rules, and adds them up with respect to
|
||||
$\sigma$. The class allows to specify the $\sigma$ different from $1$.
|
||||
|
||||
In addition, we provide classes for running simulations and storing
|
||||
the results, calculating some statistics and generating IRF. The class
|
||||
|DRFixPoint| allows for calculation of the fix point of a given
|
||||
decision rule.
|
||||
|
||||
@s DecisionRule int
|
||||
@s DecisionRuleImpl int
|
||||
@s FoldDecisionRule int
|
||||
@s UnfoldDecisionRule int
|
||||
@s ShockRealization int
|
||||
@s DRFixPoint int
|
||||
@s SimResults int
|
||||
@s SimResultsStats int
|
||||
@s SimResultsDynamicStats int
|
||||
@s RTSimResultsStats int
|
||||
@s SimResultsIRF int
|
||||
@s IRFResults int
|
||||
@s SimulationWorker int
|
||||
@s RTSimulationWorker int
|
||||
@s SimulationIRFWorker int
|
||||
@s RandomShockRealization int
|
||||
@s ExplicitShockRealization int
|
||||
@s GenShockRealization int
|
||||
@s IRFShockRealization int
|
||||
|
||||
@c
|
||||
#ifndef DECISION_RULE_H
|
||||
#define DECISION_RULE_H
|
||||
|
||||
#include <matio.h>
|
||||
|
||||
#include "kord_exception.h"
|
||||
#include "korder.h"
|
||||
#include "normal_conjugate.h"
|
||||
#include "mersenne_twister.h"
|
||||
|
||||
@<|ShockRealization| class declaration@>;
|
||||
@<|DecisionRule| class declaration@>;
|
||||
@<|DecisionRuleImpl| class declaration@>;
|
||||
@<|FoldDecisionRule| class declaration@>;
|
||||
@<|UnfoldDecisionRule| class declaration@>;
|
||||
@<|DRFixPoint| class declaration@>;
|
||||
@<|SimResults| class declaration@>;
|
||||
@<|SimResultsStats| class declaration@>;
|
||||
@<|SimResultsDynamicStats| class declaration@>;
|
||||
@<|SimResultsIRF| class declaration@>;
|
||||
@<|RTSimResultsStats| class declaration@>;
|
||||
@<|IRFResults| class declaration@>;
|
||||
@<|SimulationWorker| class declaration@>;
|
||||
@<|SimulationIRFWorker| class declaration@>;
|
||||
@<|RTSimulationWorker| class declaration@>;
|
||||
@<|RandomShockRealization| class declaration@>;
|
||||
@<|ExplicitShockRealization| class declaration@>;
|
||||
@<|GenShockRealization| class declaration@>;
|
||||
|
||||
#endif
|
||||
|
||||
@ This is a general interface to a shock realizations. The interface
|
||||
has only one method returning the shock realizations at the given
|
||||
time. This method is not constant, since it may change a state of the
|
||||
object.
|
||||
|
||||
@<|ShockRealization| class declaration@>=
|
||||
class ShockRealization {
|
||||
public:@;
|
||||
virtual ~ShockRealization()@+ {}
|
||||
virtual void get(int n, Vector& out) =0;
|
||||
virtual int numShocks() const =0;
|
||||
};
|
||||
|
||||
@ This class is an abstract interface to decision rule. Its main
|
||||
purpose is to define a common interface for simulation of a decision
|
||||
rule. We need only a simulate, evaluate, cetralized clone and output
|
||||
method. The |simulate| method simulates the rule for a given
|
||||
realization of the shocks. |eval| is a primitive evaluation (it takes
|
||||
a vector of state variables (predetermined, both and shocks) and
|
||||
returns the next period variables. Both input and output are in
|
||||
deviations from the rule's steady. |evaluate| method makes only one
|
||||
step of simulation (in terms of absolute values, not
|
||||
deviations). |centralizedClone| returns a new copy of the decision
|
||||
rule, which is centralized about provided fix-point. And finally
|
||||
|writeMat| writes the decision rule to the MAT file.
|
||||
|
||||
@<|DecisionRule| class declaration@>=
|
||||
class DecisionRule {
|
||||
public:@;
|
||||
enum emethod {@+ horner, trad @+};
|
||||
virtual ~DecisionRule()@+ {}
|
||||
virtual TwoDMatrix* simulate(emethod em, int np, const Vector& ystart,
|
||||
ShockRealization& sr) const =0;
|
||||
virtual void eval(emethod em, Vector& out, const ConstVector& v) const =0;
|
||||
virtual void evaluate(emethod em, Vector& out, const ConstVector& ys,
|
||||
const ConstVector& u) const =0;
|
||||
virtual void writeMat(mat_t* fd, const char* prefix) const =0;
|
||||
virtual DecisionRule* centralizedClone(const Vector& fixpoint) const =0;
|
||||
virtual const Vector& getSteady() const =0;
|
||||
virtual int nexog() const =0;
|
||||
virtual const PartitionY& getYPart() const =0;
|
||||
};
|
||||
|
||||
@ The main purpose of this class is to implement |DecisionRule|
|
||||
interface, which is a simulation. To be able to do this we have to
|
||||
know the partitioning of state vector $y$ since we will need to pick
|
||||
only predetermined part $y^*$. Also, we need to know the steady state.
|
||||
|
||||
The decision rule will take the form: $$y_t-\bar
|
||||
y=\sum_{i=0}^n\left[g_{(yu)^i}\right]_{\alpha_1\ldots\alpha_i}\prod_{m=1}^i
|
||||
\left[\matrix{y^*_{t-1}-\bar y^*\cr u_t}\right]^{\alpha_m},$$ where
|
||||
the tensors $\left[g_{(yu)^i}\right]$ are tensors of the constructed
|
||||
container, and $\bar y$ is the steady state.
|
||||
|
||||
If we know the fix point of the rule (conditional zero shocks)
|
||||
$\tilde y$, the rule can be transformed to so called ``centralized''
|
||||
form. This is very similar to the form above but the zero dimensional
|
||||
tensor is zero:
|
||||
$$y_t-\tilde y=\sum_{i=1}^n
|
||||
\left[\tilde g_{(yu)^i}\right]_{\alpha_1\ldots\alpha_i}\prod_{m=1}^i
|
||||
\left[\matrix{y^*_{t-1}-\tilde y^*\cr u_t}\right]^{\alpha_m}.$$
|
||||
We provide a method and a constructor to transform a rule to the centralized form.
|
||||
|
||||
The class is templated, the template argument is either |KOrder::fold|
|
||||
or |KOrder::unfold|. So, there are two implementations of |DecisionRule| interface.
|
||||
|
||||
@<|DecisionRuleImpl| class declaration@>=
|
||||
template <int t>
|
||||
class DecisionRuleImpl : public ctraits<t>::Tpol, public DecisionRule {
|
||||
protected:@;
|
||||
typedef typename ctraits<t>::Tpol _Tparent;
|
||||
const Vector ysteady;
|
||||
const PartitionY ypart;
|
||||
const int nu;
|
||||
public:@;
|
||||
DecisionRuleImpl(const _Tparent& pol, const PartitionY& yp, int nuu,
|
||||
const Vector& ys)
|
||||
: ctraits<t>::Tpol(pol), ysteady(ys), ypart(yp), nu(nuu)@+ {}
|
||||
DecisionRuleImpl(_Tparent& pol, const PartitionY& yp, int nuu,
|
||||
const Vector& ys)
|
||||
: ctraits<t>::Tpol(0, yp.ny(), pol), ysteady(ys), ypart(yp),
|
||||
nu(nuu)@+ {}
|
||||
DecisionRuleImpl(const _Tg& g, const PartitionY& yp, int nuu,
|
||||
const Vector& ys, double sigma)
|
||||
: ctraits<t>::Tpol(yp.ny(), yp.nys()+nuu), ysteady(ys), ypart(yp), nu(nuu)
|
||||
{@+ fillTensors(g, sigma);@+}
|
||||
DecisionRuleImpl(const DecisionRuleImpl<t>& dr, const ConstVector& fixpoint)
|
||||
: ctraits<t>::Tpol(dr.ypart.ny(), dr.ypart.nys()+dr.nu),
|
||||
ysteady(fixpoint), ypart(dr.ypart), nu(dr.nu)
|
||||
{@+ centralize(dr);@+}
|
||||
const Vector& getSteady() const
|
||||
{@+ return ysteady;@+}
|
||||
@<|DecisionRuleImpl::simulate| code@>;
|
||||
@<|DecisionRuleImpl::evaluate| code@>;
|
||||
@<|DecisionRuleImpl::centralizedClone| code@>;
|
||||
@<|DecisionRuleImpl::writeMat| code@>;
|
||||
int nexog() const
|
||||
{@+ return nu;@+}
|
||||
const PartitionY& getYPart() const
|
||||
{@+ return ypart;}
|
||||
protected:@;
|
||||
@<|DecisionRuleImpl::fillTensors| code@>;
|
||||
@<|DecisionRuleImpl::centralize| code@>;
|
||||
@<|DecisionRuleImpl::eval| code@>;
|
||||
};
|
||||
|
||||
@ Here we have to fill the tensor polynomial. This involves two
|
||||
separated actions. First is to evaluate the approximation at a given
|
||||
$\sigma$, the second is to compile the tensors $[g_{{(yu)}^{i+j}}]$ from
|
||||
$[g_{y^iu^j}]$. The first action is done here, the second is done by
|
||||
method |addSubTensor| of a full symmetry tensor.
|
||||
|
||||
The way how the evaluation is done is described here:
|
||||
|
||||
The $q-$order approximation to the solution can be written as:
|
||||
|
||||
$$
|
||||
\eqalign{
|
||||
y_t-\bar y &= \sum_{l=1}^q{1\over l!}\left[\sum_{i+j+k=l}
|
||||
\left(\matrix{l\cr i,j,k}\right)\left[g_{y^iu^j\sigma^k}\right]
|
||||
_{\alpha_1\ldots\alpha_j\beta_1\ldots\beta_j}
|
||||
\prod_{m=1}^i[y^*_{t-1}-\bar y^*]^{\alpha_m}
|
||||
\prod_{n=1}^j[u_t]^{\beta_m}\sigma^k\right]\cr
|
||||
&= \sum_{l=1}^q\left[\sum_{i+j\leq l}\left(\matrix{i+j\cr i}\right)
|
||||
\left[\sum_{k=0}^{l-i-j}{1\over l!}
|
||||
\left(\matrix{l\cr k}\right)\left[g_{y^iu^j\sigma^k}\right]\sigma^k\right]
|
||||
\prod_{m=1}^i[y^*_{t-1}-\bar y^*]^{\alpha_m}
|
||||
\prod_{n=1}^j[u_t]^{\beta_m}\sigma^k\right]
|
||||
}
|
||||
$$
|
||||
|
||||
This means that for each $i+j+k=l$ we have to add
|
||||
$${1\over l!}\left(\matrix{l\cr
|
||||
k}\right)\left[g_{y^iu^j\sigma^k}\right]\cdot\sigma^k=
|
||||
{1\over (i+j)!k!}\left[g_{y^iu^j\sigma^k}\right]\cdot\sigma^k$$ to
|
||||
$g_{(yu)^{i+j}}$. In addition, note that the multiplier
|
||||
$\left(\matrix{i+j\cr i}\right)$ is applied when the fully symmetric
|
||||
tensor $[g_{(yu)^{i+j}}]$ is evaluated.
|
||||
|
||||
So we go through $i+j=d=0\ldots q$ and in each loop we form the fully
|
||||
symmetric tensor $[g_{(yu)^l}]$ and insert it to the container.
|
||||
|
||||
@<|DecisionRuleImpl::fillTensors| code@>=
|
||||
void fillTensors(const _Tg& g, double sigma)
|
||||
{
|
||||
IntSequence tns(2);
|
||||
tns[0] = ypart.nys(); tns[1] = nu;
|
||||
int dfact = 1;
|
||||
for (int d = 0; d <= g.getMaxDim(); d++, dfact*=d) {
|
||||
_Ttensym* g_yud = new _Ttensym(ypart.ny(), ypart.nys()+nu, d);
|
||||
g_yud->zeros();
|
||||
@<fill tensor of |g_yud| of dimension |d|@>;
|
||||
this->insert(g_yud);
|
||||
}
|
||||
}
|
||||
|
||||
@ Here we have to fill the tensor $\left[g_{(yu)^d}\right]$. So we go
|
||||
through all pairs $(i,j)$ giving $i+j=d$, and through all $k$ from
|
||||
zero up to maximal dimension minus $d$. In this way we go through all
|
||||
symmetries of $g_{y^iu^j\sigma^k}$ which will be added to $g_{(yu)^d}$.
|
||||
|
||||
Note that at the beginning, |dfact| is a factorial of |d|. We
|
||||
calculate |kfact| is equal to $k!$. As indicated in
|
||||
|@<|DecisionRuleImpl::fillTensors| code@>|, the added tensor is thus
|
||||
multiplied with ${1\over d!k!}\sigma^k$.
|
||||
|
||||
@<fill tensor of |g_yud| of dimension |d|@>=
|
||||
for (int i = 0; i <= d; i++) {
|
||||
int j = d-i;
|
||||
int kfact = 1;
|
||||
_Ttensor tmp(ypart.ny(),
|
||||
TensorDimens(Symmetry(i,j), tns));
|
||||
tmp.zeros();
|
||||
for (int k = 0; k+d <= g.getMaxDim(); k++, kfact*=k) {
|
||||
Symmetry sym(i,j,0,k);
|
||||
if (g.check(sym)) {
|
||||
double mult = pow(sigma,k)/dfact/kfact;
|
||||
tmp.add(mult,*(g.get(sym)));
|
||||
}
|
||||
}
|
||||
g_yud->addSubTensor(tmp);
|
||||
}
|
||||
|
||||
@ The centralization is straightforward. We suppose here that the
|
||||
object's steady state is the fix point $\tilde y$. It is clear that
|
||||
the new derivatives $\left[\tilde g_{(yu)^i}\right]$ will be equal to
|
||||
the derivatives of the original decision rule |dr| at the new steady
|
||||
state $\tilde y$. So, the new derivatives are obtained by derivating the
|
||||
given decision rule $dr$ and evaluating its polynomial at
|
||||
$$dstate=\left[\matrix{\tilde y^*-\bar y^*\cr 0}\right],$$
|
||||
where $\bar y$ is the steady state of the original rule |dr|.
|
||||
|
||||
@<|DecisionRuleImpl::centralize| code@>=
|
||||
void centralize(const DecisionRuleImpl& dr)
|
||||
{
|
||||
Vector dstate(ypart.nys() + nu);
|
||||
dstate.zeros();
|
||||
Vector dstate_star(dstate, 0, ypart.nys());
|
||||
ConstVector newsteady_star(ysteady, ypart.nstat, ypart.nys());
|
||||
ConstVector oldsteady_star(dr.ysteady, ypart.nstat, ypart.nys());
|
||||
dstate_star.add(1.0, newsteady_star);
|
||||
dstate_star.add(-1.0, oldsteady_star);
|
||||
|
||||
_Tpol pol(dr);
|
||||
int dfac = 1;
|
||||
for (int d = 1; d <= dr.getMaxDim(); d++, dfac *= d) {
|
||||
pol.derivative(d-1);
|
||||
_Ttensym* der = pol.evalPartially(d, dstate);
|
||||
der->mult(1.0/dfac);
|
||||
this->insert(der);
|
||||
}
|
||||
}
|
||||
|
||||
@ Here we evaluate repeatedly the polynomial storing results in the
|
||||
created matrix. For exogenous shocks, we use |ShockRealization|
|
||||
class, for predetermined variables, we use |ystart| as the first
|
||||
state. The |ystart| vector is required to be all state variables
|
||||
|ypart.ny()|, although only the predetermined part of |ystart| is
|
||||
used.
|
||||
|
||||
We simulate in terms of $\Delta y$, this is, at the beginning the
|
||||
|ysteady| is canceled from |ystart|, we simulate, and at the end
|
||||
|ysteady| is added to all columns of the result.
|
||||
|
||||
@<|DecisionRuleImpl::simulate| code@>=
|
||||
TwoDMatrix* simulate(emethod em, int np, const Vector& ystart,
|
||||
ShockRealization& sr) const
|
||||
{
|
||||
KORD_RAISE_IF(ysteady.length() != ystart.length(),
|
||||
"Start and steady lengths differ in DecisionRuleImpl::simulate");
|
||||
TwoDMatrix* res = new TwoDMatrix(ypart.ny(), np);
|
||||
|
||||
@<initialize vectors and subvectors for simulation@>;
|
||||
@<perform the first step of simulation@>;
|
||||
@<perform all other steps of simulations@>;
|
||||
@<add the steady state to columns of |res|@>;
|
||||
return res;
|
||||
}
|
||||
|
||||
@ Here allocate the stack vector $(\Delta y^*, u)$, define the
|
||||
subvectors |dy|, and |u|, then we pickup predetermined parts of
|
||||
|ystart| and |ysteady|.
|
||||
|
||||
@<initialize vectors and subvectors for simulation@>=
|
||||
Vector dyu(ypart.nys()+nu);
|
||||
ConstVector ystart_pred(ystart, ypart.nstat, ypart.nys());
|
||||
ConstVector ysteady_pred(ysteady, ypart.nstat, ypart.nys());
|
||||
Vector dy(dyu, 0, ypart.nys());
|
||||
Vector u(dyu, ypart.nys(), nu);
|
||||
|
||||
|
||||
@ We cancel |ysteady| from |ystart|, get realization to |u|, and
|
||||
evaluate the polynomial.
|
||||
|
||||
@<perform the first step of simulation@>=
|
||||
dy = ystart_pred;
|
||||
dy.add(-1.0, ysteady_pred);
|
||||
sr.get(0, u);
|
||||
Vector out(*res, 0);
|
||||
eval(em, out, dyu);
|
||||
|
||||
@ Also clear. If the result at some period is not finite, we pad the
|
||||
rest of the matrix with zeros.
|
||||
|
||||
@<perform all other steps of simulations@>=
|
||||
int i=1;
|
||||
while (i < np) {
|
||||
ConstVector ym(*res, i-1);
|
||||
ConstVector dym(ym, ypart.nstat, ypart.nys());
|
||||
dy = dym;
|
||||
sr.get(i, u);
|
||||
Vector out(*res, i);
|
||||
eval(em, out, dyu);
|
||||
if (! out.isFinite()) {
|
||||
if (i+1 < np) {
|
||||
TwoDMatrix rest(*res, i+1, np-i-1);
|
||||
rest.zeros();
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
@ Even clearer. We add the steady state to the numbers computed above
|
||||
and leave the padded columns to zero.
|
||||
|
||||
@<add the steady state to columns of |res|@>=
|
||||
for (int j = 0; j < i; j++) {
|
||||
Vector col(*res, j);
|
||||
col.add(1.0, ysteady);
|
||||
}
|
||||
|
||||
|
||||
@ This is one period evaluation of the decision rule. The simulation
|
||||
is a sequence of repeated one period evaluations with a difference,
|
||||
that the steady state (fix point) is cancelled and added once. Hence
|
||||
we have two special methods.
|
||||
|
||||
@<|DecisionRuleImpl::evaluate| code@>=
|
||||
void evaluate(emethod em, Vector& out, const ConstVector& ys,
|
||||
const ConstVector& u) const
|
||||
{
|
||||
KORD_RAISE_IF(ys.length() != ypart.nys() || u.length() != nu,
|
||||
"Wrong dimensions of input vectors in DecisionRuleImpl::evaluate");
|
||||
KORD_RAISE_IF(out.length() != ypart.ny(),
|
||||
"Wrong dimension of output vector in DecisionRuleImpl::evaluate");
|
||||
ConstVector ysteady_pred(ysteady, ypart.nstat, ypart.nys());
|
||||
Vector ys_u(ypart.nys()+nu);
|
||||
Vector ys_u1(ys_u, 0, ypart.nys());
|
||||
ys_u1 = ys;
|
||||
ys_u1.add(-1.0, ysteady_pred);
|
||||
Vector ys_u2(ys_u, ypart.nys(), nu);
|
||||
ys_u2 = u;
|
||||
eval(em, out, ys_u);
|
||||
out.add(1.0, ysteady);
|
||||
}
|
||||
|
||||
@ This is easy. We just return the newly created copy using the
|
||||
centralized constructor.
|
||||
|
||||
@<|DecisionRuleImpl::centralizedClone| code@>=
|
||||
DecisionRule* centralizedClone(const Vector& fixpoint) const
|
||||
{
|
||||
return new DecisionRuleImpl<t>(*this, fixpoint);
|
||||
}
|
||||
|
||||
@ Here we only encapsulate two implementations to one, deciding
|
||||
according to the parameter.
|
||||
|
||||
@<|DecisionRuleImpl::eval| code@>=
|
||||
void eval(emethod em, Vector& out, const ConstVector& v) const
|
||||
{
|
||||
if (em == DecisionRule::horner)
|
||||
_Tparent::evalHorner(out, v);
|
||||
else
|
||||
_Tparent::evalTrad(out, v);
|
||||
}
|
||||
|
||||
@ Write the decision rule and steady state to the MAT file.
|
||||
@<|DecisionRuleImpl::writeMat| code@>=
|
||||
void writeMat(mat_t* fd, const char* prefix) const
|
||||
{
|
||||
ctraits<t>::Tpol::writeMat(fd, prefix);
|
||||
TwoDMatrix dum(ysteady.length(), 1);
|
||||
dum.getData() = ysteady;
|
||||
char tmp[100];
|
||||
sprintf(tmp, "%s_ss", prefix);
|
||||
ConstTwoDMatrix(dum).writeMat(fd, tmp);
|
||||
}
|
||||
|
||||
@ This is exactly the same as |DecisionRuleImpl<KOrder::fold>|. The
|
||||
only difference is that we have a conversion from
|
||||
|UnfoldDecisionRule|, which is exactly
|
||||
|DecisionRuleImpl<KOrder::unfold>|.
|
||||
|
||||
@<|FoldDecisionRule| class declaration@>=
|
||||
class UnfoldDecisionRule;
|
||||
class FoldDecisionRule : public DecisionRuleImpl<KOrder::fold> {
|
||||
friend class UnfoldDecisionRule;
|
||||
public:@;
|
||||
FoldDecisionRule(const ctraits<KOrder::fold>::Tpol& pol, const PartitionY& yp, int nuu,
|
||||
const Vector& ys)
|
||||
: DecisionRuleImpl<KOrder::fold>(pol, yp, nuu, ys) {}
|
||||
FoldDecisionRule(ctraits<KOrder::fold>::Tpol& pol, const PartitionY& yp, int nuu,
|
||||
const Vector& ys)
|
||||
: DecisionRuleImpl<KOrder::fold>(pol, yp, nuu, ys) {}
|
||||
FoldDecisionRule(const ctraits<KOrder::fold>::Tg& g, const PartitionY& yp, int nuu,
|
||||
const Vector& ys, double sigma)
|
||||
: DecisionRuleImpl<KOrder::fold>(g, yp, nuu, ys, sigma) {}
|
||||
FoldDecisionRule(const DecisionRuleImpl<KOrder::fold>& dr, const ConstVector& fixpoint)
|
||||
: DecisionRuleImpl<KOrder::fold>(dr, fixpoint) {}
|
||||
FoldDecisionRule(const UnfoldDecisionRule& udr);
|
||||
};
|
||||
|
||||
@ This is exactly the same as |DecisionRuleImpl<KOrder::unfold>|, but
|
||||
with a conversion from |FoldDecisionRule|, which is exactly
|
||||
|DecisionRuleImpl<KOrder::fold>|.
|
||||
|
||||
@<|UnfoldDecisionRule| class declaration@>=
|
||||
class UnfoldDecisionRule : public DecisionRuleImpl<KOrder::unfold> {
|
||||
friend class FoldDecisionRule;
|
||||
public:@;
|
||||
UnfoldDecisionRule(const ctraits<KOrder::unfold>::Tpol& pol, const PartitionY& yp, int nuu,
|
||||
const Vector& ys)
|
||||
: DecisionRuleImpl<KOrder::unfold>(pol, yp, nuu, ys) {}
|
||||
UnfoldDecisionRule(ctraits<KOrder::unfold>::Tpol& pol, const PartitionY& yp, int nuu,
|
||||
const Vector& ys)
|
||||
: DecisionRuleImpl<KOrder::unfold>(pol, yp, nuu, ys) {}
|
||||
UnfoldDecisionRule(const ctraits<KOrder::unfold>::Tg& g, const PartitionY& yp, int nuu,
|
||||
const Vector& ys, double sigma)
|
||||
: DecisionRuleImpl<KOrder::unfold>(g, yp, nuu, ys, sigma) {}
|
||||
UnfoldDecisionRule(const DecisionRuleImpl<KOrder::unfold>& dr, const ConstVector& fixpoint)
|
||||
: DecisionRuleImpl<KOrder::unfold>(dr, fixpoint) {}
|
||||
UnfoldDecisionRule(const FoldDecisionRule& udr);
|
||||
};
|
||||
|
||||
|
||||
@ This class serves for calculation of the fix point of the decision
|
||||
rule given that the shocks are zero. The class is very similar to the
|
||||
|DecisionRuleImpl|. Besides the calculation of the fix point, the only
|
||||
difference between |DRFixPoint| and |DecisionRuleImpl| is that the
|
||||
derivatives wrt. shocks are ignored (since shocks are zero during the
|
||||
calculations). That is why have a different |fillTensor| method.
|
||||
|
||||
The solution algorithm is Newton and is described in
|
||||
|@<|DRFixPoint::solveNewton| code@>|. It solves $F(y)=0$, where
|
||||
$F=g(y,0)-y$. The function $F$ is given by its derivatives |bigf|. The
|
||||
Jacobian of the solved system is given by derivatives stored in
|
||||
|bigfder|.
|
||||
|
||||
@<|DRFixPoint| class declaration@>=
|
||||
template <int t>
|
||||
class DRFixPoint : public ctraits<t>::Tpol {
|
||||
typedef typename ctraits<t>::Tpol _Tparent;
|
||||
static int max_iter;
|
||||
static int max_newton_iter;
|
||||
static int newton_pause;
|
||||
static double tol;
|
||||
const Vector ysteady;
|
||||
const PartitionY ypart;
|
||||
_Tparent* bigf;
|
||||
_Tparent* bigfder;
|
||||
public:@;
|
||||
typedef typename DecisionRule::emethod emethod;
|
||||
@<|DRFixPoint| constructor code@>;
|
||||
@<|DRFixPoint| destructor code@>;
|
||||
@<|DRFixPoint::calcFixPoint| code@>;
|
||||
int getNumIter() const
|
||||
{@+ return iter;@+}
|
||||
int getNewtonLastIter() const
|
||||
{@+ return newton_iter_last;@+}
|
||||
int getNewtonTotalIter() const
|
||||
{@+ return newton_iter_total;@+}
|
||||
protected:@;
|
||||
@<|DRFixPoint::fillTensors| code@>;
|
||||
@<|DRFixPoint::solveNewton| code@>;
|
||||
private:@;
|
||||
int iter;
|
||||
int newton_iter_last;
|
||||
int newton_iter_total;
|
||||
};
|
||||
|
||||
|
||||
@ Here we have to setup the function $F=g(y,0)-y$ and ${\partial
|
||||
F\over\partial y}$. The former is taken from the given derivatives of
|
||||
$g$ where a unit matrix is subtracted from the first derivative
|
||||
(|Symmetry(1)|). Then the derivative of the $F$ polynomial is
|
||||
calculated.
|
||||
|
||||
@<|DRFixPoint| constructor code@>=
|
||||
DRFixPoint(const _Tg& g, const PartitionY& yp,
|
||||
const Vector& ys, double sigma)
|
||||
: ctraits<t>::Tpol(yp.ny(), yp.nys()),
|
||||
ysteady(ys), ypart(yp), bigf(NULL), bigfder(NULL)
|
||||
{
|
||||
fillTensors(g, sigma);
|
||||
_Tparent yspol(ypart.nstat, ypart.nys(), *this);
|
||||
bigf = new _Tparent((const _Tparent&) yspol);
|
||||
_Ttensym* frst = bigf->get(Symmetry(1));
|
||||
for (int i = 0; i < ypart.nys(); i++)
|
||||
frst->get(i,i) = frst->get(i,i) - 1;
|
||||
bigfder = new _Tparent(*bigf, 0);
|
||||
}
|
||||
|
||||
@
|
||||
@<|DRFixPoint| destructor code@>=
|
||||
virtual ~DRFixPoint()
|
||||
{
|
||||
if (bigf)
|
||||
delete bigf;
|
||||
if (bigfder)
|
||||
delete bigfder;
|
||||
}
|
||||
|
||||
@ Here we fill the tensors for the |DRFixPoint| class. We ignore the
|
||||
derivatives $g_{y^iu^j\sigma^k}$ for which $j>0$. So we go through all
|
||||
dimensions |d|, and all |k| such that |d+k| is between the maximum
|
||||
dimension and |d|, and add ${\sigma^k\over d!k!}g_{y^d\sigma^k}$ to
|
||||
the tensor $g_{(y)^d}$.
|
||||
|
||||
@<|DRFixPoint::fillTensors| code@>=
|
||||
void fillTensors(const _Tg& g, double sigma)
|
||||
{
|
||||
int dfact = 1;
|
||||
for (int d = 0; d <= g.getMaxDim(); d++, dfact*=d) {
|
||||
_Ttensym* g_yd = new _Ttensym(ypart.ny(), ypart.nys(), d);
|
||||
g_yd->zeros();
|
||||
int kfact = 1;
|
||||
for (int k = 0; d+k <= g.getMaxDim(); k++, kfact*=k) {
|
||||
if (g.check(Symmetry(d,0,0,k))) {
|
||||
const _Ttensor* ten = g.get(Symmetry(d,0,0,k));
|
||||
double mult = pow(sigma,k)/dfact/kfact;
|
||||
g_yd->add(mult, *ten);
|
||||
}
|
||||
}
|
||||
this->insert(g_yd);
|
||||
}
|
||||
}
|
||||
|
||||
@ This tries to solve polynomial equation $F(y)=0$, where $F$
|
||||
polynomial is |bigf| and its derivative is in |bigfder|. It returns
|
||||
true if the Newton converged. The method takes the given vector as
|
||||
initial guess, and rewrites it with a solution. The method guarantees
|
||||
to return the vector, which has smaller norm of the residual. That is
|
||||
why the input/output vector |y| is always changed.
|
||||
|
||||
The method proceeds with a Newton step, if the Newton step improves
|
||||
the residual error. So we track residual errors in |flastnorm| and
|
||||
|fnorm| (former and current). In addition, at each step we search for
|
||||
an underrelaxation parameter |urelax|, which improves the residual. If
|
||||
|urelax| is less that |urelax_threshold|, we stop searching and stop
|
||||
the Newton.
|
||||
|
||||
@<|DRFixPoint::solveNewton| code@>=
|
||||
bool solveNewton(Vector& y)
|
||||
{
|
||||
const double urelax_threshold = 1.e-5;
|
||||
Vector sol((const Vector&) y);
|
||||
Vector delta(y.length());
|
||||
newton_iter_last = 0;
|
||||
bool delta_finite = true;
|
||||
double flastnorm = 0.0;
|
||||
double fnorm = 0.0;
|
||||
bool converged = false;
|
||||
double urelax = 1.0;
|
||||
|
||||
do {
|
||||
_Ttensym* jacob = bigfder->evalPartially(1, sol);
|
||||
bigf->evalHorner(delta, sol);
|
||||
if (newton_iter_last == 0)
|
||||
flastnorm = delta.getNorm();
|
||||
delta_finite = delta.isFinite();
|
||||
if (delta_finite) {
|
||||
ConstTwoDMatrix(*jacob).multInvLeft(delta);
|
||||
@<find |urelax| improving residual@>;
|
||||
sol.add(-urelax, delta);
|
||||
delta_finite = delta.isFinite();
|
||||
}
|
||||
delete jacob;
|
||||
newton_iter_last++;
|
||||
converged = delta_finite && fnorm < tol;
|
||||
flastnorm = fnorm;
|
||||
} while (!converged && newton_iter_last < max_newton_iter
|
||||
&& urelax > urelax_threshold);
|
||||
|
||||
newton_iter_total += newton_iter_last;
|
||||
if (! converged)
|
||||
newton_iter_last = 0;
|
||||
y = (const Vector&)sol;
|
||||
return converged;
|
||||
}
|
||||
|
||||
@ Here we find the |urelax|. We cycle as long as the new residual size
|
||||
|fnorm| is greater than last residual size |flastnorm|. If the urelax
|
||||
is less than |urelax_threshold| we give up. The |urelax| is damped by
|
||||
the ratio of |flastnorm| and |fnorm|. It the ratio is close to one, we
|
||||
damp by one half.
|
||||
|
||||
@<find |urelax| improving residual@>=
|
||||
bool urelax_found = false;
|
||||
urelax = 1.0;
|
||||
while (!urelax_found && urelax > urelax_threshold) {
|
||||
Vector soltmp((const Vector&)sol);
|
||||
soltmp.add(-urelax, delta);
|
||||
Vector f(sol.length());
|
||||
bigf->evalHorner(f, soltmp);
|
||||
fnorm = f.getNorm();
|
||||
if (fnorm <= flastnorm)
|
||||
urelax_found = true;
|
||||
else
|
||||
urelax *= std::min(0.5, flastnorm/fnorm);
|
||||
}
|
||||
|
||||
|
||||
@ This method solves the fix point of the no-shocks rule
|
||||
$y_{t+1}=f(y_t)$. It combines dull steps with Newton attempts. The
|
||||
dull steps correspond to evaluations setting $y_{t+1}=f(y_t)$. For
|
||||
reasonable models the dull steps converge to the fix-point but very
|
||||
slowly. That is why we make Newton attempt from time to time. The
|
||||
frequency of the Newton attempts is given by |newton_pause|. We
|
||||
perform the calculations in deviations from the steady state. So, at
|
||||
the end, we have to add the steady state.
|
||||
|
||||
The method also sets the members |iter|, |newton_iter_last| and
|
||||
|newton_iter_total|. These numbers can be examined later.
|
||||
|
||||
The |out| vector is not touched if the algorithm has not convered.
|
||||
|
||||
@<|DRFixPoint::calcFixPoint| code@>=
|
||||
bool calcFixPoint(emethod em, Vector& out)
|
||||
{
|
||||
KORD_RAISE_IF(out.length() != ypart.ny(),
|
||||
"Wrong length of out in DRFixPoint::calcFixPoint");
|
||||
|
||||
Vector delta(ypart.nys());
|
||||
Vector ystar(ypart.nys());
|
||||
ystar.zeros();
|
||||
|
||||
iter = 0;
|
||||
newton_iter_last = 0;
|
||||
newton_iter_total = 0;
|
||||
bool converged = false;
|
||||
do {
|
||||
if ((iter/newton_pause)*newton_pause == iter)
|
||||
converged = solveNewton(ystar);
|
||||
if (! converged) {
|
||||
bigf->evalHorner(delta, ystar);
|
||||
KORD_RAISE_IF_X(! delta.isFinite(),
|
||||
"NaN or Inf asserted in DRFixPoint::calcFixPoint",
|
||||
KORD_FP_NOT_FINITE);
|
||||
ystar.add(1.0, delta);
|
||||
converged = delta.getNorm() < tol;
|
||||
}
|
||||
iter++;
|
||||
} while (iter < max_iter && ! converged);
|
||||
|
||||
if (converged) {
|
||||
_Tparent::evalHorner(out, ystar);
|
||||
out.add(1.0, ysteady);
|
||||
}
|
||||
|
||||
return converged;
|
||||
}
|
||||
|
||||
|
||||
@ This is a basically a number of matrices of the same dimensions,
|
||||
which can be obtained as simulation results from a given decision rule
|
||||
and shock realizations. We also store the realizations of shocks.
|
||||
|
||||
@<|SimResults| class declaration@>=
|
||||
class ExplicitShockRealization;
|
||||
class SimResults {
|
||||
protected:@;
|
||||
int num_y;
|
||||
int num_per;
|
||||
int num_burn;
|
||||
vector<TwoDMatrix*> data;
|
||||
vector<ExplicitShockRealization*> shocks;
|
||||
public:@;
|
||||
SimResults(int ny, int nper, int nburn = 0)
|
||||
: num_y(ny), num_per(nper), num_burn(nburn)@+ {}
|
||||
virtual ~SimResults();
|
||||
void simulate(int num_sim, const DecisionRule& dr, const Vector& start,
|
||||
const TwoDMatrix& vcov, Journal& journal);
|
||||
void simulate(int num_sim, const DecisionRule& dr, const Vector& start,
|
||||
const TwoDMatrix& vcov);
|
||||
int getNumPer() const
|
||||
{@+ return num_per;@+}
|
||||
int getNumBurn() const
|
||||
{@+ return num_burn;@+}
|
||||
int getNumSets() const
|
||||
{@+ return (int)data.size();@+}
|
||||
const TwoDMatrix& getData(int i) const
|
||||
{@+ return *(data[i]);@+}
|
||||
const ExplicitShockRealization& getShocks(int i) const
|
||||
{ @+ return *(shocks[i]);@+}
|
||||
bool addDataSet(TwoDMatrix* d, ExplicitShockRealization* sr);
|
||||
void writeMat(const char* base, const char* lname) const;
|
||||
void writeMat(mat_t* fd, const char* lname) const;
|
||||
};
|
||||
|
||||
@ This does the same as |SimResults| plus it calculates means and
|
||||
covariances of the simulated data.
|
||||
|
||||
@<|SimResultsStats| class declaration@>=
|
||||
class SimResultsStats : public SimResults {
|
||||
protected:@;
|
||||
Vector mean;
|
||||
TwoDMatrix vcov;
|
||||
public:@;
|
||||
SimResultsStats(int ny, int nper, int nburn = 0)
|
||||
: SimResults(ny, nper, nburn), mean(ny), vcov(ny,ny)@+ {}
|
||||
void simulate(int num_sim, const DecisionRule& dr, const Vector& start,
|
||||
const TwoDMatrix& vcov, Journal& journal);
|
||||
void writeMat(mat_t* fd, const char* lname) const;
|
||||
protected:@;
|
||||
void calcMean();
|
||||
void calcVcov();
|
||||
};
|
||||
|
||||
@ This does the similar thing as |SimResultsStats| but the statistics are
|
||||
not calculated over all periods but only within each period. Then we
|
||||
do not calculate covariances with periods but only variances.
|
||||
|
||||
@<|SimResultsDynamicStats| class declaration@>=
|
||||
class SimResultsDynamicStats : public SimResults {
|
||||
protected:@;
|
||||
TwoDMatrix mean;
|
||||
TwoDMatrix variance;
|
||||
public:@;
|
||||
SimResultsDynamicStats(int ny, int nper, int nburn = 0)
|
||||
: SimResults(ny, nper, nburn), mean(ny,nper), variance(ny,nper)@+ {}
|
||||
void simulate(int num_sim, const DecisionRule& dr, const Vector& start,
|
||||
const TwoDMatrix& vcov, Journal& journal);
|
||||
void writeMat(mat_t* fd, const char* lname) const;
|
||||
protected:@;
|
||||
void calcMean();
|
||||
void calcVariance();
|
||||
};
|
||||
|
||||
|
||||
@ This goes through control simulation results, and for each control
|
||||
it adds a given impulse to a given shock and runs a simulation. The
|
||||
control simulation is then cancelled and the result is stored. After
|
||||
that these results are averaged with variances calculated.
|
||||
|
||||
The means and the variances are then written to the MAT-4 file.
|
||||
|
||||
@<|SimResultsIRF| class declaration@>=
|
||||
class SimulationIRFWorker;
|
||||
class SimResultsIRF : public SimResults {
|
||||
friend class SimulationIRFWorker;
|
||||
protected:@;
|
||||
const SimResults& control;
|
||||
int ishock;
|
||||
double imp;
|
||||
TwoDMatrix means;
|
||||
TwoDMatrix variances;
|
||||
public:@;
|
||||
SimResultsIRF(const SimResults& cntl, int ny, int nper, int i, double impulse)
|
||||
: SimResults(ny, nper, 0), control(cntl),
|
||||
ishock(i), imp(impulse),
|
||||
means(ny, nper), variances(ny, nper)@+ {}
|
||||
void simulate(const DecisionRule& dr, Journal& journal);
|
||||
void simulate(const DecisionRule& dr);
|
||||
void writeMat(mat_t* fd, const char* lname) const;
|
||||
protected:@;
|
||||
void calcMeans();
|
||||
void calcVariances();
|
||||
};
|
||||
|
||||
@ This simulates and gathers all statistics from the real time
|
||||
simulations. In the |simulate| method, it runs |RTSimulationWorker|s
|
||||
which accummulate information from their own estimates. The estimation
|
||||
is done by means of |NormalConj| class, which is a conjugate family of
|
||||
densities for normal distibutions.
|
||||
|
||||
@<|RTSimResultsStats| class declaration@>=
|
||||
class RTSimulationWorker;
|
||||
class RTSimResultsStats {
|
||||
friend class RTSimulationWorker;
|
||||
protected:@;
|
||||
Vector mean;
|
||||
TwoDMatrix vcov;
|
||||
int num_per;
|
||||
int num_burn;
|
||||
NormalConj nc;
|
||||
int incomplete_simulations;
|
||||
int thrown_periods;
|
||||
public:@;
|
||||
RTSimResultsStats(int ny, int nper, int nburn = 0)
|
||||
: mean(ny), vcov(ny, ny),
|
||||
num_per(nper), num_burn(nburn), nc(ny),
|
||||
incomplete_simulations(0), thrown_periods(0)@+ {}
|
||||
void simulate(int num_sim, const DecisionRule& dr, const Vector& start,
|
||||
const TwoDMatrix& vcov, Journal& journal);
|
||||
void simulate(int num_sim, const DecisionRule& dr, const Vector& start,
|
||||
const TwoDMatrix& vcov);
|
||||
void writeMat(mat_t* fd, const char* lname);
|
||||
};
|
||||
|
||||
@ For each shock, this simulates plus and minus impulse. The class
|
||||
maintains a vector of simulation results, each gets a particular shock
|
||||
and sign (positive/negative). The results of type |SimResultsIRF| are
|
||||
stored in a vector so that even ones are positive, odd ones are
|
||||
negative.
|
||||
|
||||
The constructor takes a reference to the control simulations, which
|
||||
must be finished before the constructor is called. The control
|
||||
simulations are passed to all |SimResultsIRF|s.
|
||||
|
||||
The constructor also takes the vector of indices of exogenous
|
||||
variables (|ili|) for which the IRFs are generated. The list is kept
|
||||
(as |irf_list_ind|) for other methods.
|
||||
|
||||
@<|IRFResults| class declaration@>=
|
||||
class DynamicModel;
|
||||
class IRFResults {
|
||||
vector<SimResultsIRF*> irf_res;
|
||||
const DynamicModel& model;
|
||||
vector<int> irf_list_ind;
|
||||
public:@;
|
||||
IRFResults(const DynamicModel& mod, const DecisionRule& dr,
|
||||
const SimResults& control, const vector<int>& ili,
|
||||
Journal& journal);
|
||||
~IRFResults();
|
||||
void writeMat(mat_t* fd, const char* prefix) const;
|
||||
};
|
||||
|
||||
@ This worker simulates the given decision rule and inserts the result
|
||||
to |SimResults|.
|
||||
|
||||
@<|SimulationWorker| class declaration@>=
|
||||
class SimulationWorker : public THREAD {
|
||||
protected:@;
|
||||
SimResults& res;
|
||||
const DecisionRule& dr;
|
||||
DecisionRule::emethod em;
|
||||
int np;
|
||||
const Vector& st;
|
||||
ShockRealization& sr;
|
||||
public:@;
|
||||
SimulationWorker(SimResults& sim_res,
|
||||
const DecisionRule& dec_rule,
|
||||
DecisionRule::emethod emet, int num_per,
|
||||
const Vector& start, ShockRealization& shock_r)
|
||||
: res(sim_res), dr(dec_rule), em(emet), np(num_per), st(start), sr(shock_r) {}
|
||||
void operator()();
|
||||
};
|
||||
|
||||
@ This worker simulates a given impulse |imp| to a given shock
|
||||
|ishock| based on a given control simulation with index |idata|. The
|
||||
control simulations are contained in |SimResultsIRF| which is passed
|
||||
to the constructor.
|
||||
|
||||
@<|SimulationIRFWorker| class declaration@>=
|
||||
class SimulationIRFWorker : public THREAD {
|
||||
SimResultsIRF& res;
|
||||
const DecisionRule& dr;
|
||||
DecisionRule::emethod em;
|
||||
int np;
|
||||
int idata;
|
||||
int ishock;
|
||||
double imp;
|
||||
public:@;
|
||||
SimulationIRFWorker(SimResultsIRF& sim_res,
|
||||
const DecisionRule& dec_rule,
|
||||
DecisionRule::emethod emet, int num_per,
|
||||
int id, int ishck, double impulse)
|
||||
: res(sim_res), dr(dec_rule), em(emet), np(num_per),
|
||||
idata(id), ishock(ishck), imp(impulse)@+ {}
|
||||
void operator()();
|
||||
};
|
||||
|
||||
@ This class does the real time simulation job for
|
||||
|RTSimResultsStats|. It simulates the model period by period. It
|
||||
accummulates the information in the |RTSimResultsStats::nc|. If NaN or
|
||||
Inf is observed, it ends the simulation and adds to the
|
||||
|thrown_periods| of |RTSimResultsStats|.
|
||||
|
||||
@<|RTSimulationWorker| class declaration@>=
|
||||
class RTSimulationWorker : public THREAD {
|
||||
protected:@;
|
||||
RTSimResultsStats& res;
|
||||
const DecisionRule& dr;
|
||||
DecisionRule::emethod em;
|
||||
int np;
|
||||
const Vector& ystart;
|
||||
ShockRealization& sr;
|
||||
public:@;
|
||||
RTSimulationWorker(RTSimResultsStats& sim_res,
|
||||
const DecisionRule& dec_rule,
|
||||
DecisionRule::emethod emet, int num_per,
|
||||
const Vector& start, ShockRealization& shock_r)
|
||||
: res(sim_res), dr(dec_rule), em(emet), np(num_per), ystart(start), sr(shock_r) {}
|
||||
void operator()();
|
||||
};
|
||||
|
||||
@ This class generates draws from Gaussian distribution with zero mean
|
||||
and the given variance-covariance matrix. It stores the factor of vcov
|
||||
$V$ matrix, yielding $FF^T = V$.
|
||||
|
||||
@<|RandomShockRealization| class declaration@>=
|
||||
class RandomShockRealization : virtual public ShockRealization {
|
||||
protected:@;
|
||||
MersenneTwister mtwister;
|
||||
TwoDMatrix factor;
|
||||
public:@;
|
||||
RandomShockRealization(const TwoDMatrix& v, unsigned int iseed)
|
||||
: mtwister(iseed), factor(v.nrows(),v.nrows())
|
||||
{@+schurFactor(v);@+}
|
||||
RandomShockRealization(const RandomShockRealization& sr)
|
||||
: mtwister(sr.mtwister), factor(sr.factor)@+ {}
|
||||
virtual ~RandomShockRealization() @+{}
|
||||
void get(int n, Vector& out);
|
||||
int numShocks() const
|
||||
{@+ return factor.nrows();@+}
|
||||
protected:@;
|
||||
void choleskyFactor(const TwoDMatrix& v);
|
||||
void schurFactor(const TwoDMatrix& v);
|
||||
};
|
||||
|
||||
@ This is just a matrix of finite numbers. It can be constructed from
|
||||
any |ShockRealization| with a given number of periods.
|
||||
|
||||
@<|ExplicitShockRealization| class declaration@>=
|
||||
class ExplicitShockRealization : virtual public ShockRealization {
|
||||
TwoDMatrix shocks;
|
||||
public:@;
|
||||
ExplicitShockRealization(const TwoDMatrix& sh)
|
||||
: shocks(sh)@+ {}
|
||||
ExplicitShockRealization(const ConstTwoDMatrix& sh)
|
||||
: shocks(sh)@+ {}
|
||||
ExplicitShockRealization(const ExplicitShockRealization& sr)
|
||||
: shocks(sr.shocks)@+ {}
|
||||
ExplicitShockRealization(ShockRealization& sr, int num_per);
|
||||
void get(int n, Vector& out);
|
||||
int numShocks() const
|
||||
{@+ return shocks.nrows();@+}
|
||||
const TwoDMatrix& getShocks()
|
||||
{@+ return shocks;@+}
|
||||
void addToShock(int ishock, int iper, double val);
|
||||
void print() const
|
||||
{@+ shocks.print();@+}
|
||||
};
|
||||
|
||||
@ This represents a user given shock realization. The first matrix of
|
||||
the constructor is a covariance matrix of shocks, the second matrix is
|
||||
a rectangular matrix, where columns correspond to periods, rows to
|
||||
shocks. If an element of the matrix is {\tt NaN}, or {\tt Inf}, or
|
||||
{\tt -Inf}, then the random shock is taken instead of that element.
|
||||
|
||||
In this way it is a generalization of both |RandomShockRealization|
|
||||
and |ExplicitShockRealization|.
|
||||
|
||||
@<|GenShockRealization| class declaration@>=
|
||||
class GenShockRealization : public RandomShockRealization, public ExplicitShockRealization {
|
||||
public:@;
|
||||
GenShockRealization(const TwoDMatrix& v, const TwoDMatrix& sh, int seed)
|
||||
: RandomShockRealization(v, seed), ExplicitShockRealization(sh)@+
|
||||
{
|
||||
KORD_RAISE_IF(sh.nrows() != v.nrows() || v.nrows() != v.ncols(),
|
||||
"Wrong dimension of input matrix in GenShockRealization constructor");
|
||||
}
|
||||
void get(int n, Vector& out);
|
||||
int numShocks() const
|
||||
{@+ return RandomShockRealization::numShocks();@+}
|
||||
};
|
||||
|
||||
@ End of {\tt decision\_rule.h} file.
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dynamic_model.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
void
|
||||
NameList::print() const
|
||||
{
|
||||
for (int i = 0; i < getNum(); i++)
|
||||
std::cout << getName(i) << '\n';
|
||||
}
|
||||
|
||||
void
|
||||
NameList::writeMat(mat_t *fd, const std::string &vname) const
|
||||
{
|
||||
int maxlen = 0;
|
||||
for (int i = 0; i < getNum(); i++)
|
||||
maxlen = std::max(maxlen, static_cast<int>(getName(i).size()));
|
||||
|
||||
if (maxlen == 0)
|
||||
return;
|
||||
|
||||
auto m = std::make_unique<char[]>(getNum()*maxlen);
|
||||
|
||||
for (int i = 0; i < getNum(); i++)
|
||||
for (int j = 0; j < maxlen; j++)
|
||||
if (j < static_cast<int>(getName(i).size()))
|
||||
m[j*getNum()+i] = getName(i)[j];
|
||||
else
|
||||
m[j*getNum()+i] = ' ';
|
||||
|
||||
size_t dims[2];
|
||||
dims[0] = getNum();
|
||||
dims[1] = maxlen;
|
||||
|
||||
matvar_t *v = Mat_VarCreate(vname.c_str(), MAT_C_CHAR, MAT_T_UINT8, 2, dims, m.get(), 0);
|
||||
|
||||
Mat_VarWrite(fd, v, MAT_COMPRESSION_NONE);
|
||||
|
||||
Mat_VarFree(v);
|
||||
}
|
||||
|
||||
void
|
||||
NameList::writeMatIndices(mat_t *fd, const std::string &prefix) const
|
||||
{
|
||||
TwoDMatrix aux(1, 1);
|
||||
for (int i = 0; i < getNum(); i++)
|
||||
{
|
||||
aux.get(0, 0) = i+1;
|
||||
aux.writeMat(fd, prefix + "_i_" + getName(i));
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
@q $Id: dynamic_model.cweb 431 2005-08-16 15:41:01Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@ Start of {\tt dynamic\_model.cpp} file.
|
||||
|
||||
@c
|
||||
#include "dynamic_model.h"
|
||||
|
||||
@<|NameList::print| code@>;
|
||||
@<|NameList::writeMat| code@>;
|
||||
@<|NameList::writeMatIndices| code@>;
|
||||
|
||||
@
|
||||
@<|NameList::print| code@>=
|
||||
void NameList::print() const
|
||||
{
|
||||
for (int i = 0; i < getNum(); i++)
|
||||
printf("%s\n", getName(i));
|
||||
}
|
||||
|
||||
@
|
||||
@<|NameList::writeMat| code@>=
|
||||
void NameList::writeMat(mat_t* fd, const char* vname) const
|
||||
{
|
||||
int maxlen = 0;
|
||||
for (int i = 0; i < getNum(); i++)
|
||||
if (maxlen < (int)strlen(getName(i)))
|
||||
maxlen = (int)strlen(getName(i));
|
||||
|
||||
if (maxlen == 0)
|
||||
return;
|
||||
|
||||
char *m = new char[getNum()*maxlen];
|
||||
|
||||
for (int i = 0; i < getNum(); i++)
|
||||
for (int j = 0; j < maxlen; j++)
|
||||
if (j < (int)strlen(getName(i)))
|
||||
m[j*getNum()+i] = getName(i)[j];
|
||||
else
|
||||
m[j*getNum()+i] = ' ';
|
||||
|
||||
# if MATIO_MAJOR_VERSION > 1 || (MATIO_MAJOR_VERSION == 1 && MATIO_MINOR_VERSION >= 5)
|
||||
size_t dims[2];
|
||||
const matio_compression compression = MAT_COMPRESSION_NONE;
|
||||
# else
|
||||
int dims[2];
|
||||
const int compression = COMPRESSION_NONE;
|
||||
# endif
|
||||
dims[0] = getNum();
|
||||
dims[1] = maxlen;
|
||||
|
||||
matvar_t *v = Mat_VarCreate(vname, MAT_C_CHAR, MAT_T_UINT8, 2, dims, m, 0);
|
||||
|
||||
Mat_VarWrite(fd, v, compression);
|
||||
|
||||
Mat_VarFree(v);
|
||||
delete[] m;
|
||||
}
|
||||
|
||||
@
|
||||
@<|NameList::writeMatIndices| code@>=
|
||||
void NameList::writeMatIndices(mat_t* fd, const char* prefix) const
|
||||
{
|
||||
char tmp[100];
|
||||
TwoDMatrix aux(1,1);
|
||||
for (int i = 0; i < getNum(); i++) {
|
||||
sprintf(tmp, "%s_i_%s", prefix, getName(i));
|
||||
aux.get(0,0) = i+1;
|
||||
aux.writeMat(fd, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
@ End of {\tt dynamic\_model.cpp} file.
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
// Dynamic model abstraction
|
||||
|
||||
/* This file only defines a generic interface to a DSGE model. The model
|
||||
takes the form:
|
||||
|
||||
𝔼ₜ(f(g**(g*(y,uₜ),uₜ₊₁),g(y,uₜ),yₜ,uₜ)) = 0
|
||||
|
||||
The interface is defined via pure virtual class DynamicModel. */
|
||||
|
||||
#ifndef DYNAMIC_MODEL_H
|
||||
#define DYNAMIC_MODEL_H
|
||||
|
||||
#include "t_container.hh"
|
||||
#include "sparse_tensor.hh"
|
||||
|
||||
#include "Vector.hh"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
/* The class is a virtual pure class which provides an access to names
|
||||
of the variables. */
|
||||
|
||||
class NameList
|
||||
{
|
||||
public:
|
||||
virtual ~NameList() = default;
|
||||
virtual int getNum() const = 0;
|
||||
virtual const std::string &getName(int i) const = 0;
|
||||
void print() const;
|
||||
void writeMat(mat_t *fd, const std::string &vname) const;
|
||||
void writeMatIndices(mat_t *fd, const std::string &prefix) const;
|
||||
};
|
||||
|
||||
/* This is the interface to an information on a generic DSGE model. It is
|
||||
sufficient for calculations of policy rule Taylor approximations at some
|
||||
(not necessarily deterministic) steady state.
|
||||
|
||||
We need to know a partitioning of endogenous variables y. We suppose that y
|
||||
is partitioned as:
|
||||
|
||||
⎡ static⎤
|
||||
⎢ pred ⎥
|
||||
y = ⎢ both ⎥
|
||||
⎣forward⎦
|
||||
|
||||
of which we define:
|
||||
|
||||
|
||||
⎡pred⎤ ⎡ both ⎤
|
||||
y* = ⎣both⎦ y** = ⎣forward⎦
|
||||
|
||||
where “static” are meant those variables, which appear only at time t;
|
||||
“pred” are meant those variables, which appear only at t and t−1; “both” are
|
||||
meant those variables, which appear at least at t−1 and t+1; and “forward”
|
||||
are meant those variables, which appear only at t and t+1. This partitioning
|
||||
is given by methods nstat(), npred(), nboth(), and nforw(). The number of
|
||||
equations numeq() must be the same as a number of endogenous variables.
|
||||
|
||||
In order to complete description, we need to know a number of exogenous
|
||||
variables, which is a size of u, hence nexog() method.
|
||||
|
||||
The model contains an information about names of variables, the
|
||||
variance-covariance matrix of the shocks, the derivatives of equations of f
|
||||
at some steady state, and the steady state. These can be retrieved by the
|
||||
corresponding methods.
|
||||
|
||||
The derivatives of the system are calculated with respect to stacked
|
||||
variables, the stack looks like:
|
||||
|
||||
⎡y**ₜ₊₁⎤
|
||||
⎢ yₜ ⎥
|
||||
⎢ y*ₜ₋₁⎥
|
||||
⎣ uₜ ⎦
|
||||
|
||||
There are only three operations. The first solveDeterministicSteady() solves
|
||||
the deterministic steady steate which can be retrieved by getSteady() later.
|
||||
The method evaluateSystem() calculates f(y**,y,y*,u), where y and u are
|
||||
passed, or f(y**ₜ₊₁, yₜ, y*ₜ₋₁, u), where y**ₜ₊₁, yₜ, y*ₜ₋₁, u are passed.
|
||||
Finally, the method calcDerivativesAtSteady() calculates derivatives of f at
|
||||
the current steady state, and zero shocks. The derivatives can be retrieved
|
||||
with getModelDerivatives(). All the derivatives are done up to a given order
|
||||
in the model, which can be retrieved by order().
|
||||
|
||||
The model initialization is done in a constructor of the implementing class.
|
||||
The constructor usually calls a parser, which parses a given file (usually a
|
||||
text file), and retrieves all necessary information about the model,
|
||||
inluding variables, partitioning, variance-covariance matrix, information
|
||||
helpful for calculation of the deterministic steady state, and so on. */
|
||||
|
||||
class DynamicModel
|
||||
{
|
||||
public:
|
||||
virtual std::unique_ptr<DynamicModel> clone() const = 0;
|
||||
virtual ~DynamicModel() = default;
|
||||
|
||||
virtual int nstat() const = 0;
|
||||
virtual int nboth() const = 0;
|
||||
virtual int npred() const = 0;
|
||||
virtual int nforw() const = 0;
|
||||
virtual int nexog() const = 0;
|
||||
virtual int order() const = 0;
|
||||
int
|
||||
numeq() const
|
||||
{
|
||||
return nstat()+nboth()+npred()+nforw();
|
||||
}
|
||||
|
||||
virtual const NameList &getAllEndoNames() const = 0;
|
||||
virtual const NameList &getStateNames() const = 0;
|
||||
virtual const NameList &getExogNames() const = 0;
|
||||
virtual const TwoDMatrix &getVcov() const = 0;
|
||||
virtual const TensorContainer<FSSparseTensor> &getModelDerivatives() const = 0;
|
||||
virtual const Vector &getSteady() const = 0;
|
||||
virtual Vector &getSteady() = 0;
|
||||
|
||||
virtual void solveDeterministicSteady() = 0;
|
||||
virtual void evaluateSystem(Vector &out, const ConstVector &yy, const Vector &xx) = 0;
|
||||
virtual void evaluateSystem(Vector &out, const ConstVector &yym, const ConstVector &yy,
|
||||
const ConstVector &yyp, const Vector &xx) = 0;
|
||||
virtual void calcDerivativesAtSteady() = 0;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,120 +0,0 @@
|
|||
@q $Id: dynamic_model.hweb 378 2005-07-21 15:50:20Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@*2 Dynamic model abstraction. Start of {\tt dynamic\_model.h} file.
|
||||
|
||||
This file only defines a generic interface to an SDGE model. The model
|
||||
takes the form:
|
||||
$$E_t\left[f(g^{**}(g^*(y,u_t),u_{t+1}),g(y,u),y,u_t)\right]=0$$
|
||||
The interface is defined via pure virtual class |DynamicModel|.
|
||||
|
||||
@s NameList int
|
||||
@s DynamicModel int
|
||||
@c
|
||||
#ifndef DYNAMIC_MODEL_H
|
||||
#define DYNAMIC_MODEL_H
|
||||
|
||||
#include "t_container.h"
|
||||
#include "sparse_tensor.h"
|
||||
|
||||
#include "Vector.h"
|
||||
|
||||
@<|NameList| class declaration@>;
|
||||
@<|DynamicModel| class declaration@>;
|
||||
|
||||
#endif
|
||||
|
||||
@ The class is a virtual pure class which provides an access to names
|
||||
of the variables.
|
||||
@<|NameList| class declaration@>=
|
||||
class NameList {
|
||||
public:@;
|
||||
virtual ~NameList() {}
|
||||
virtual int getNum() const =0;
|
||||
virtual const char* getName(int i) const=0;
|
||||
void print() const;
|
||||
void writeMat(mat_t* fd, const char* vname) const;
|
||||
void writeMatIndices(mat_t* fd, const char* prefix) const;
|
||||
};
|
||||
|
||||
@ This is the interface to an information on a generic SDGE
|
||||
model. It is sufficient for calculations of policy rule Taylor
|
||||
approximations at some (not necessarily deterministic) steady state.
|
||||
|
||||
We need to know a partitioning of endogenous variables $y$. We suppose
|
||||
that $y$ is partitioned as
|
||||
$$y=\left[\matrix{\hbox{static}\cr\hbox{pred}\cr\hbox{both}\cr\hbox{forward}}\right]$$
|
||||
of which we define
|
||||
$$y^*=\left[\matrix{\hbox{pred}\cr\hbox{both}}\right]\quad
|
||||
y^{**}=\left[\matrix{\hbox{both}\cr\hbox{forward}}\right]$$
|
||||
where ``static'' are meant those variables, which appear only at time
|
||||
$t$; ``pred'' are meant those variables, which appear only at $t$ and
|
||||
$t-1$; ``both'' are meant those variables, which appear at least at
|
||||
$t-1$ and $t+1$; and ``forward'' are meant those variables, which
|
||||
appear only at $t$ and $t+1$. This partitioning is given by methods
|
||||
|nstat()|, |npred()|, |nboth()|, and |nforw()|. The number of
|
||||
equations |numeq()| must be the same as a number of endogenous
|
||||
variables.
|
||||
|
||||
In order to complete description, we need to know a number of
|
||||
exogenous variables, which is a size of $u$, hence |nexog()| method.
|
||||
|
||||
The model contains an information about names of variables, the
|
||||
variance-covariance matrix of the shocks, the derivatives of equations
|
||||
of $f$ at some steady state, and the steady state. These can be
|
||||
retrieved by the corresponding methods.
|
||||
|
||||
The derivatives of the system are calculated with respect to stacked
|
||||
variables, the stack looks as:
|
||||
$$\left[\matrix{y^{**}_{t+1}\cr y_t\cr y^*_{t-1}\cr u_t}\right].$$
|
||||
|
||||
There are only three operations. The first
|
||||
|solveDeterministicSteady()| solves the deterministic steady steate
|
||||
which can be retrieved by |getSteady()| later. The method
|
||||
|evaluateSystem| calculates $f(y^{**},y,y^*,u)$, where $y$ and $u$ are
|
||||
passed, or $f(y^{**}_{t+1}, y_t, y^*_{t-1}, u)$, where $y^{**}_{t+1}$,
|
||||
$y_t$, $y^*_{t-1}$, $u$ are passed. Finally, the method
|
||||
|calcDerivativesAtSteady()| calculates derivatives of $f$ at the
|
||||
current steady state, and zero shocks. The derivatives can be
|
||||
retrieved with |getModelDerivatives()|. All the derivatives are done
|
||||
up to a given order in the model, which can be retrieved by |order()|.
|
||||
|
||||
The model initialization is done in a constructor of the implementing
|
||||
class. The constructor usually calls a parser, which parses a given
|
||||
file (usually a text file), and retrieves all necessary information
|
||||
about the model, inluding variables, partitioning, variance-covariance
|
||||
matrix, information helpful for calculation of the deterministic
|
||||
steady state, and so on.
|
||||
|
||||
@<|DynamicModel| class declaration@>=
|
||||
class DynamicModel {
|
||||
public:@;
|
||||
virtual DynamicModel* clone() const =0;
|
||||
virtual ~DynamicModel() {}
|
||||
|
||||
virtual int nstat() const =0;
|
||||
virtual int nboth() const =0;
|
||||
virtual int npred() const =0;
|
||||
virtual int nforw() const =0;
|
||||
virtual int nexog() const =0;
|
||||
virtual int order() const =0;
|
||||
int numeq() const
|
||||
{@+ return nstat()+nboth()+npred()+nforw(); @+}
|
||||
|
||||
virtual const NameList& getAllEndoNames() const =0;
|
||||
virtual const NameList& getStateNames() const =0;
|
||||
virtual const NameList& getExogNames() const =0;
|
||||
virtual const TwoDMatrix& getVcov() const =0;
|
||||
virtual const TensorContainer<FSSparseTensor>& getModelDerivatives() const =0;
|
||||
virtual const Vector& getSteady() const =0;
|
||||
virtual Vector& getSteady() =0;
|
||||
|
||||
virtual void solveDeterministicSteady() =0;
|
||||
virtual void evaluateSystem(Vector& out, const Vector& yy, const Vector& xx) =0;
|
||||
virtual void evaluateSystem(Vector& out, const Vector& yym, const Vector& yy,
|
||||
const Vector& yyp, const Vector& xx) =0;
|
||||
virtual void calcDerivativesAtSteady() =0;
|
||||
};
|
||||
|
||||
|
||||
@ End of {\tt dynamic\_model.h} file.
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "faa_di_bruno.hh"
|
||||
#include "fine_container.hh"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// FaaDiBruno::calculate() folded sparse code
|
||||
/* We take an opportunity to refine the stack container to avoid allocation of
|
||||
more memory than available. */
|
||||
void
|
||||
FaaDiBruno::calculate(const StackContainer<FGSTensor> &cont,
|
||||
const TensorContainer<FSSparseTensor> &f,
|
||||
FGSTensor &out)
|
||||
{
|
||||
out.zeros();
|
||||
for (int l = 1; l <= out.dimen(); l++)
|
||||
{
|
||||
auto [max, mem_mb, p_size_mb] = estimRefinement(out.getDims(), out.nrows(), l);
|
||||
FoldedFineContainer fine_cont(cont, max);
|
||||
fine_cont.multAndAdd(l, f, out);
|
||||
JournalRecord recc(journal);
|
||||
recc << "dim=" << l << " avmem=" << mem_mb << " tmpmem=" << p_size_mb << " max=" << max
|
||||
<< " stacks=" << cont.numStacks() << u8"→" << fine_cont.numStacks() << endrec;
|
||||
}
|
||||
}
|
||||
|
||||
// FaaDiBruno::calculate() folded dense code
|
||||
/* Here we just simply evaluate multAndAdd() for the dense container. There is
|
||||
no opportunity for tuning. */
|
||||
void
|
||||
FaaDiBruno::calculate(const FoldedStackContainer &cont, const FGSContainer &g,
|
||||
FGSTensor &out)
|
||||
{
|
||||
out.zeros();
|
||||
for (int l = 1; l <= out.dimen(); l++)
|
||||
{
|
||||
long int mem = SystemResources::availableMemory();
|
||||
cont.multAndAdd(l, g, out);
|
||||
JournalRecord rec(journal);
|
||||
int mem_mb = mem/1024/1024;
|
||||
rec << "dim=" << l << " avmem=" << mem_mb << endrec;
|
||||
}
|
||||
}
|
||||
|
||||
// FaaDiBruno::calculate() unfolded sparse code
|
||||
/* This is the same as FaaDiBruno::calculate() folded sparse code. The only
|
||||
difference is that we construct unfolded fine container. */
|
||||
void
|
||||
FaaDiBruno::calculate(const StackContainer<UGSTensor> &cont,
|
||||
const TensorContainer<FSSparseTensor> &f,
|
||||
UGSTensor &out)
|
||||
{
|
||||
out.zeros();
|
||||
for (int l = 1; l <= out.dimen(); l++)
|
||||
{
|
||||
auto [max, mem_mb, p_size_mb] = estimRefinement(out.getDims(), out.nrows(), l);
|
||||
UnfoldedFineContainer fine_cont(cont, max);
|
||||
fine_cont.multAndAdd(l, f, out);
|
||||
JournalRecord recc(journal);
|
||||
recc << "dim=" << l << " avmem=" << mem_mb << " tmpmem=" << p_size_mb << " max=" << max
|
||||
<< " stacks=" << cont.numStacks() << u8"→" << fine_cont.numStacks() << endrec;
|
||||
}
|
||||
}
|
||||
|
||||
// FaaDiBruno::calculate() unfolded dense code
|
||||
/* Again, no tuning opportunity here. */
|
||||
void
|
||||
FaaDiBruno::calculate(const UnfoldedStackContainer &cont, const UGSContainer &g,
|
||||
UGSTensor &out)
|
||||
{
|
||||
out.zeros();
|
||||
for (int l = 1; l <= out.dimen(); l++)
|
||||
{
|
||||
long int mem = SystemResources::availableMemory();
|
||||
cont.multAndAdd(l, g, out);
|
||||
JournalRecord rec(journal);
|
||||
int mem_mb = mem/1024/1024;
|
||||
rec << "dim=" << l << " avmem=" << mem_mb << endrec;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function returns a number of maximum rows used for refinement of the
|
||||
stacked container. We want to set the maximum so that the expected memory
|
||||
consumption for the number of paralel threads would be less than available
|
||||
memory. On the other hand we do not want to be too pesimistic since a very
|
||||
fine refinement can be very slow.
|
||||
|
||||
Besides memory needed for a dense unfolded slice of a tensor from ‘f’, each
|
||||
thread needs ‘magic_mult*per_size’ bytes of memory. In the worst case,
|
||||
‘magic_mult’ will be equal to 2, this means memory ‘per_size’ for target
|
||||
temporary (permuted symmetry) tensor plus one copy for intermediate result.
|
||||
However, this shows to be too pesimistic, so we set ‘magic_mult’ to 1.5. The
|
||||
memory for permuted symmetry temporary tensor ‘per_size’ is estimated as a
|
||||
weigthed average of unfolded memory of the ‘out’ tensor and unfolded memory
|
||||
of a symetric tensor with the largest coordinate size. Some experiments
|
||||
showed that the best combination of the two is to take 100% if the latter,
|
||||
so we set ‘lambda’ to zero.
|
||||
|
||||
The ‘max’ number of rows in the refined ‘cont’ must be such that each
|
||||
slice fits to remaining memory. Number of columns of the slice are
|
||||
never greater maxˡ. (This is not true, since stacks corresponding to
|
||||
unit/zero matrices cannot be further refined). We get an equation:
|
||||
|
||||
nthreads·maxˡ·8·r = mem − magic_mult·nthreads·per_size·8·r
|
||||
|
||||
where ‘mem’ is available memory in bytes, ‘nthreads’ is a number of threads,
|
||||
r is a number of rows, and 8 is ‘sizeof(double)’.
|
||||
|
||||
If the right hand side is less than zero, we set ‘max’ to 10, just to let it
|
||||
do something. */
|
||||
|
||||
std::tuple<int, int, int>
|
||||
FaaDiBruno::estimRefinement(const TensorDimens &tdims, int nr, int l)
|
||||
{
|
||||
int nthreads = sthread::detach_thread_group::max_parallel_threads;
|
||||
long per_size1 = tdims.calcUnfoldMaxOffset();
|
||||
long per_size2 = static_cast<long>(std::pow(tdims.getNVS().getMax(), l));
|
||||
double lambda = 0.0;
|
||||
long per_size = sizeof(double)*nr
|
||||
*static_cast<long>(lambda*per_size1+(1-lambda)*per_size2);
|
||||
long mem = SystemResources::availableMemory();
|
||||
int max = 0;
|
||||
double num_cols = static_cast<double>(mem-magic_mult*nthreads*per_size)
|
||||
/nthreads/sizeof(double)/nr;
|
||||
if (num_cols > 0)
|
||||
{
|
||||
double maxd = std::pow(num_cols, 1.0/l);
|
||||
max = static_cast<int>(std::floor(maxd));
|
||||
}
|
||||
if (max == 0)
|
||||
{
|
||||
max = 10;
|
||||
JournalRecord rec(journal);
|
||||
rec << "dim=" << l << " run out of memory, imposing max=" << max;
|
||||
if (nthreads > 1)
|
||||
rec << " (decrease number of threads)";
|
||||
rec << endrec;
|
||||
}
|
||||
int avmem_mb = mem/1024/1024;
|
||||
int tmpmem_mb = nthreads*per_size/1024/1024;
|
||||
return { max, avmem_mb, tmpmem_mb };
|
||||
}
|
|
@ -1,158 +0,0 @@
|
|||
@q $Id: faa_di_bruno.cweb 744 2006-05-09 13:16:07Z kamenik $ @>
|
||||
@q Copyright 2005, Ondra Kamenik @>
|
||||
|
||||
@ Start of {\tt faa\_di\_bruno.cpp} file.
|
||||
|
||||
@s FoldedFineContainer int
|
||||
@s UnfoldedFineContainer int
|
||||
|
||||
@c
|
||||
#include "faa_di_bruno.h"
|
||||
#include "fine_container.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
double FaaDiBruno::magic_mult = 1.5;
|
||||
@<|FaaDiBruno::calculate| folded sparse code@>;
|
||||
@<|FaaDiBruno::calculate| folded dense code@>;
|
||||
@<|FaaDiBruno::calculate| unfolded sparse code@>;
|
||||
@<|FaaDiBruno::calculate| unfolded dense code@>;
|
||||
@<|FaaDiBruno::estimRefinment| code@>;
|
||||
|
||||
@ We take an opportunity to refine the stack container to avoid
|
||||
allocation of more memory than available.
|
||||
|
||||
@<|FaaDiBruno::calculate| folded sparse code@>=
|
||||
void FaaDiBruno::calculate(const StackContainer<FGSTensor>& cont,
|
||||
const TensorContainer<FSSparseTensor>& f,
|
||||
FGSTensor& out)
|
||||
{
|
||||
out.zeros();
|
||||
for (int l = 1; l <= out.dimen(); l++) {
|
||||
int mem_mb, p_size_mb;
|
||||
int max = estimRefinment(out.getDims(), out.nrows(), l, mem_mb, p_size_mb);
|
||||
FoldedFineContainer fine_cont(cont, max);
|
||||
fine_cont.multAndAdd(l, f, out);
|
||||
JournalRecord recc(journal);
|
||||
recc << "dim=" << l << " avmem=" << mem_mb << " tmpmem=" << p_size_mb << " max=" << max
|
||||
<< " stacks=" << cont.numStacks() << "->" << fine_cont.numStacks() << endrec;
|
||||
}
|
||||
}
|
||||
|
||||
@ Here we just simply evaluate |multAndAdd| for the dense
|
||||
container. There is no opportunity for tuning.
|
||||
|
||||
@<|FaaDiBruno::calculate| folded dense code@>=
|
||||
void FaaDiBruno::calculate(const FoldedStackContainer& cont, const FGSContainer& g,
|
||||
FGSTensor& out)
|
||||
{
|
||||
out.zeros();
|
||||
for (int l = 1; l <= out.dimen(); l++) {
|
||||
long int mem = SystemResources::availableMemory();
|
||||
cont.multAndAdd(l, g, out);
|
||||
JournalRecord rec(journal);
|
||||
int mem_mb = mem/1024/1024;
|
||||
rec << "dim=" << l << " avmem=" << mem_mb << endrec;
|
||||
}
|
||||
}
|
||||
|
||||
@ This is the same as |@<|FaaDiBruno::calculate| folded sparse
|
||||
code@>|. The only difference is that we construct unfolded fine
|
||||
container.
|
||||
|
||||
@<|FaaDiBruno::calculate| unfolded sparse code@>=
|
||||
void FaaDiBruno::calculate(const StackContainer<UGSTensor>& cont,
|
||||
const TensorContainer<FSSparseTensor>& f,
|
||||
UGSTensor& out)
|
||||
{
|
||||
out.zeros();
|
||||
for (int l = 1; l <= out.dimen(); l++) {
|
||||
int mem_mb, p_size_mb;
|
||||
int max = estimRefinment(out.getDims(), out.nrows(), l, mem_mb, p_size_mb);
|
||||
UnfoldedFineContainer fine_cont(cont, max);
|
||||
fine_cont.multAndAdd(l, f, out);
|
||||
JournalRecord recc(journal);
|
||||
recc << "dim=" << l << " avmem=" << mem_mb << " tmpmem=" << p_size_mb << " max=" << max
|
||||
<< " stacks=" << cont.numStacks() << "->" << fine_cont.numStacks() << endrec;
|
||||
}
|
||||
}
|
||||
|
||||
@ Again, no tuning opportunity here.
|
||||
@<|FaaDiBruno::calculate| unfolded dense code@>=
|
||||
void FaaDiBruno::calculate(const UnfoldedStackContainer& cont, const UGSContainer& g,
|
||||
UGSTensor& out)
|
||||
{
|
||||
out.zeros();
|
||||
for (int l = 1; l <= out.dimen(); l++) {
|
||||
long int mem = SystemResources::availableMemory();
|
||||
cont.multAndAdd(l, g, out);
|
||||
JournalRecord rec(journal);
|
||||
int mem_mb = mem/1024/1024;
|
||||
rec << "dim=" << l << " avmem=" << mem_mb << endrec;
|
||||
}
|
||||
}
|
||||
|
||||
@ This function returns a number of maximum rows used for refinement of
|
||||
the stacked container. We want to set the maximum so that the expected
|
||||
memory consumption for the number of paralel threads would be less
|
||||
than available memory. On the other hand we do not want to be too
|
||||
pesimistic since a very fine refinement can be very slow.
|
||||
|
||||
Besides memory needed for a dense unfolded slice of a tensor from
|
||||
|f|, each thread needs |magic_mult*per_size| bytes of memory. In the
|
||||
worst case, |magic_mult| will be equal to 2, this means memory
|
||||
|per_size| for target temporary (permuted symmetry) tensor plus one
|
||||
copy for intermediate result. However, this shows to be too
|
||||
pesimistic, so we set |magic_mult| to 1.5. The memory for permuted
|
||||
symmetry temporary tensor |per_size| is estimated as a weigthed
|
||||
average of unfolded memory of the |out| tensor and unfolded memory of
|
||||
a symetric tensor with the largest coordinate size. Some experiments
|
||||
showed that the best combination of the two is to take 100\% if the
|
||||
latter, so we set |lambda| to zero.
|
||||
|
||||
The |max| number of rows in the refined |cont| must be such that each
|
||||
slice fits to remaining memory. Number of columns of the slice are
|
||||
never greater $max^l$. (This is not true, since stacks corresponing to
|
||||
unit/zero matrices cannot be further refined). We get en equation:
|
||||
|
||||
$$nthreads\cdot max^l\cdot 8\cdot r = mem -
|
||||
magic\_mult\cdot nthreads\cdot per\_size\cdot 8\cdot r,$$
|
||||
where |mem| is available memory in bytes, |nthreads| is a number of
|
||||
threads, $r$ is a number of rows, and $8$ is |sizeof(double)|.
|
||||
|
||||
If the right hand side is less than zero, we set |max| to 10, just to
|
||||
let it do something.
|
||||
|
||||
@<|FaaDiBruno::estimRefinment| code@>=
|
||||
int FaaDiBruno::estimRefinment(const TensorDimens& tdims, int nr, int l,
|
||||
int& avmem_mb, int& tmpmem_mb)
|
||||
{
|
||||
int nthreads = THREAD_GROUP::max_parallel_threads;
|
||||
long int per_size1 = tdims.calcUnfoldMaxOffset();
|
||||
long int per_size2 = (long int)pow((double)tdims.getNVS().getMax(), l);
|
||||
double lambda = 0.0;
|
||||
long int per_size = sizeof(double)*nr
|
||||
*(long int)(lambda*per_size1+(1-lambda)*per_size2);
|
||||
long int mem = SystemResources::availableMemory();
|
||||
int max = 0;
|
||||
double num_cols = ((double)(mem-magic_mult*nthreads*per_size))
|
||||
/nthreads/sizeof(double)/nr;
|
||||
if (num_cols > 0) {
|
||||
double maxd = pow(num_cols, ((double)1)/l);
|
||||
max = (int)floor(maxd);
|
||||
}
|
||||
if (max == 0) {
|
||||
max = 10;
|
||||
JournalRecord rec(journal);
|
||||
rec << "dim=" << l << " run out of memory, imposing max=" << max;
|
||||
if (nthreads > 1)
|
||||
rec << " (decrease number of threads)";
|
||||
rec << endrec;
|
||||
}
|
||||
avmem_mb = mem/1024/1024;
|
||||
tmpmem_mb = (nthreads*per_size)/1024/1024;
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
@ End of {\tt faa\_di\_bruno.cpp} file.
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright © 2005 Ondra Kamenik
|
||||
* Copyright © 2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Faà Di Bruno evaluator
|
||||
|
||||
/* This defines a class which implements the Faà Di Bruno Formula
|
||||
|
||||
ₗ
|
||||
[B_sᵏ]_α₁…αₗ = [f_zˡ]_β₁…βₗ ∑ ∏ [z_{s^|cₘ|}]_cₘ(α)^βₘ
|
||||
c∈ℳₗ,ₖ ᵐ⁼¹
|
||||
|
||||
where sᵏ is a general symmetry of dimension k and z is a stack of
|
||||
functions. */
|
||||
|
||||
#ifndef FAA_DI_BRUNO_H
|
||||
#define FAA_DI_BRUNO_H
|
||||
|
||||
#include "journal.hh"
|
||||
#include "stack_container.hh"
|
||||
#include "t_container.hh"
|
||||
#include "sparse_tensor.hh"
|
||||
#include "gs_tensor.hh"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
class FaaDiBruno
|
||||
{
|
||||
Journal &journal;
|
||||
public:
|
||||
FaaDiBruno(Journal &jr)
|
||||
: journal(jr)
|
||||
{
|
||||
}
|
||||
void calculate(const StackContainer<FGSTensor> &cont, const TensorContainer<FSSparseTensor> &f,
|
||||
FGSTensor &out);
|
||||
void calculate(const FoldedStackContainer &cont, const FGSContainer &g,
|
||||
FGSTensor &out);
|
||||
void calculate(const StackContainer<UGSTensor> &cont, const TensorContainer<FSSparseTensor> &f,
|
||||
UGSTensor &out);
|
||||
void calculate(const UnfoldedStackContainer &cont, const UGSContainer &g,
|
||||
UGSTensor &out);
|
||||
protected:
|
||||
std::tuple<int,int,int> estimRefinement(const TensorDimens &tdims, int nr, int l);
|
||||
|
||||
// See FaaDiBruno::calculate() folded sparse code for why we have magic_mult
|
||||
constexpr static double magic_mult = 1.5;
|
||||
};
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue