Compare commits

..

1 Commits

1734 changed files with 91569 additions and 67154 deletions

View File

@ -1,27 +0,0 @@
# NB: whenever the present file is modified, the same modification should be
# applied to the copy in preprocessor.git
# For general information about our coding style, and the specific version
# of clang-format used, see:
# https://git.dynare.org/Dynare/dynare/-/wikis/CodingGuidelines#c-code
# For the list of options of clang-format, see:
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
# Effective configuration can be obtained with:
# clang-format --dump-config
Language: Cpp
Standard: c++20
ColumnLimit: 100
BasedOnStyle: GNU
AllowShortFunctionsOnASingleLine: None
AlwaysBreakTemplateDeclarations: Yes
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
Cpp11BracedListStyle: true
DeriveLineEnding: false
IndentPPDirectives: AfterHash
PackConstructorInitializers: NextLine
PPIndentWidth: 1
PointerAlignment: Left
SpaceAfterTemplateKeyword: false
SpaceBeforeParens: ControlStatements
SpaceBeforeCpp11BracedList: true

View File

@ -1,8 +0,0 @@
# NB: to use clang-tidy on the MEX source code, make sure that you have
# libomp-dev installed (the LLVM implementation of OpenMP)
# TODO: add the following check families:
# - bugprone-*
# - cppcoreguidelines-
Checks: 'performance-*,modernize-*,-modernize-use-trailing-return-type,-clang-diagnostic-unqualified-std-cast-call'

View File

@ -1,8 +1,6 @@
((c-mode . ((indent-tabs-mode . nil)
(fill-column . 100)
(c-file-style . "gnu")))
(c++-mode . ((indent-tabs-mode . nil)
(fill-column . 100)
(c-file-style . "gnu")))
(makefile-mode . ((indent-tabs-mode . t)))
(octave-mode . ((indent-tabs-mode . nil)

168
.gitignore vendored
View File

@ -1,35 +1,159 @@
# For checking that no file has been unduly ignored, run:
# $ git ls-files -i -c --exclude-per-directory=.gitignore
# $ git ls-files -i --exclude-per-directory=.gitignore
# Any file that is displayed should be removed from the ignore list
# (possibly by an exclusion rule beginning with an exclamation mark)
# Generic ignore rules
*~
*.o
*.a
*.fig
\#*\#
TAGS
*.mat
# Created when building the reference manual
# Build system rules
.deps
Makefile
Makefile.in
confdefs.h
configure
config.log
config.status
aclocal.m4
autom4te.cache
config.guess
config.sub
depcomp
install-sh
/missing
/mex/build/matlab/missing
/mex/build/octave/missing
/compile
/mex/build/matlab/compile
/mex/build/octave/compile
ylwrap
ar-lib
# checksum associated with fast option
checksum
# Make Check Rules
*.trs
*.tls
# Doc rules
*.pdf
*.aux
*.log
*.out
*.toc
*.idx
*.scn
*.nav
*.snm
*.vrb
*.bbl
*.blg
*.lof
/doc/manual/build
/doc/manual/utils/version.py
/doc/manual/utils/__pycache__/*
!/doc/guide.bbl
!/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/internals/*.html
doc/internals/ltxpng
# Created by the Windows package build script
/windows/deps/lib64/
/windows/deps/lib64-msys2/
/windows/deps/matlab64/
/windows/deps/mingw64/
/windows/deps/octave64/
/windows/deps/sources64/
/windows/deps/tarballs/
/windows/exe/
/windows/7z/
/windows/zip/
# MATLAB dir
/matlab/preprocessor64/
/matlab/supported_octave_version.m
/matlab/dynare_version.m
# Created by the macOS package build script
/macOS/deps/arm64/sources64/
/macOS/deps/x86_64/sources64/
/macOS/deps/tarballs/
/macOS/deps/arm64/lib64/
/macOS/deps/x86_64/lib64/
build-doc
# DLL rules
*.mex
*.oct
*.mexglx
*.mexa64
*.mexw32
*.mexw64
*.mexmaci
*.mexmaci64
/mex/matlab/
/mex/octave/
# Symbolic links created for building MEX files
/mex/build/matlab/*/*.c
/mex/build/matlab/*/*.cc
/mex/build/matlab/*/*.f08
/mex/build/matlab/*/*.F08
/mex/build/octave/*/*.c
/mex/build/octave/*/*.cc
/mex/build/octave/*/*.f08
/mex/build/octave/*/*.F08
# Fortran modules
/mex/build/matlab/*/*.mod
/mex/build/octave/*/*.mod
# Extra rules for trust_region MEX testfiles
/mex/sources/block_trust_region/test/*.mod
/mex/sources/block_trust_region/test/dulmage_mendelsohn_test
/mex/sources/block_trust_region/test/trust_region_test
!/mex/sources/block_trust_region/test/Makefile
# Windows
!/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/
# MacOS stuff
.DS_Store
macOS/pkg/
macOS/deps/sources64/
macOS/deps/tarballs/
macOS/deps/lib64/
# Emacs stuff
TAGS
scripts/dynare.elc
# MS-Sbvar
/contrib/ms-sbvar/*.prn
/contrib/ms-sbvar/*.dat
/contrib/ms-sbvar/sbvar_commandline
/contrib/ms-sbvar/sbvar_init_file
!/contrib/ms-sbvar/Makefile
/tests/ms-sbvar/*.tmp
# Reporting
*synctex.gz
tests/reporting/tmpRepDir
# Julia Tests
tests/julia/rbc/rbc*.jl
# Octave variables saved when Octave crashes
octave-workspace
# VERSION generated file
VERSION
matlab/supported_octave_version.m

View File

@ -1,99 +1,83 @@
variables:
GIT_SUBMODULE_STRATEGY: recursive
TERM: linux
MATLAB_VERSION: R2023b
OLD_MATLAB_VERSION: R2018b
# To ensure that "false && true" fails, see https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394#note_412609647
FF_ENABLE_BASH_EXIT_CODE_CHECK: 'true'
MATLAB_VERSION: R2022b
OLD_MATLAB_VERSION: R2014a
OCTAVE_VERSION: 7.3.0
# 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 7-unstable-$TIMESTAMP-$COMMIT
# + if on master: use 6-unstable-$TIMESTAMP-$COMMIT
# + on another branch: use $BRANCH-$TIMESTAMP-$COMMIT
# - if in a personal repository: use $USER-$TIMESTAMP-$COMMIT
before_script:
- 'if [[ -z $VERSION ]] && [[ $CI_PROJECT_NAMESPACE == Dynare ]] && [[ -n $CI_COMMIT_TAG ]]; then export VERSION=$CI_COMMIT_TAG; fi'
- 'if [[ -z $VERSION ]] && [[ $CI_PROJECT_NAMESPACE == Dynare ]] && [[ $CI_COMMIT_REF_NAME == master ]]; then export VERSION=7-unstable-$(date +%F-%H%M)-$CI_COMMIT_SHORT_SHA; fi'
- 'if [[ -z $VERSION ]] && [[ $CI_PROJECT_NAMESPACE == Dynare ]]; then export VERSION=$CI_COMMIT_REF_NAME-$(date +%F-%H%M)-$CI_COMMIT_SHORT_SHA; fi'
- 'if [[ -z $VERSION ]]; then export VERSION=$CI_PROJECT_NAMESPACE-$(date +%F-%H%M)-$CI_COMMIT_SHORT_SHA; fi'
- '[[ -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=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
- pkg
- sign
- deploy
build_matlab:
build_binaries:
stage: build
script:
- meson setup -Dbuild_for=matlab -Dmatlab_path=/opt/MATLAB/$MATLAB_VERSION -Dbuildtype=release build-matlab
- meson compile -v -C build-matlab
- autoreconf -si
- ./configure --with-matlab=/usr/local/MATLAB/$MATLAB_VERSION --with-octave=/usr/local/octave/$OCTAVE_VERSION PACKAGE_VERSION=$VERSION PACKAGE_STRING="dynare $VERSION"
- make -j $(nproc) LN_S="cp -p"
artifacts:
paths:
- build-matlab/
expire_in: 3 days
build_octave:
stage: build
script:
- meson setup -Dbuild_for=octave -Dbuildtype=release build-octave
- meson compile -v -C build-octave
artifacts:
paths:
- build-octave/
- preprocessor/dynare-preprocessor
- mex/octave/
- mex/matlab/
expire_in: 3 days
build_doc:
stage: build
script:
- meson rewrite kwargs set project / version "$VERSION"
# Use a local copy of MathJax to avoid using CDN (which are a privacy issue)
# NB: Debian 12 “Bookworm” has MathJax 2. The following needs to be updated
# when Debian moves to MathJax 3.
- meson setup -Dbuild_for=octave -Dmathjax_path=mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML build-doc
- meson compile -v -C build-doc doc
- cp -dR /usr/share/javascript/mathjax build-doc/dynare-manual.html/_static/
- autoreconf -si
- ./configure --disable-matlab --disable-octave PACKAGE_VERSION=$VERSION PACKAGE_STRING="dynare $VERSION"
- make -j $(nproc) pdf html
artifacts:
paths:
- build-doc/
- doc/manual/build/
- doc/**/*.pdf
- preprocessor/doc/*/*.pdf
expire_in: 3 days
pkg_source:
stage: pkg
script:
- meson rewrite kwargs set project / version "$VERSION"
- git commit -a -m "Source for $VERSION"
- meson setup -Dbuild_for=octave build-src
- meson dist -C build-src --no-tests
- rm doc/manual/source/_static/mathjax && sed -i "/^mathjax_path *=/d" doc/manual/source/conf.py
- '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 --with-matlab=/usr/local/MATLAB/$MATLAB_VERSION --with-octave=/usr/local/octave/$OCTAVE_VERSION
- make dist
artifacts:
paths:
- build-src/meson-dist/dynare-*.tar.xz
- dynare-*.tar.xz
expire_in: 3 days
needs: []
pkg_windows:
stage: pkg
script:
- meson rewrite kwargs set project / version "$VERSION"
- mkdir -p windows/deps/tarballs && cp /usr/lib/dynare-runner/matlab64-* windows/deps/tarballs/
- ln -s ~/tarballs windows/deps/
- make -C windows
- rm windows/deps/tarballs/matlab64-* # No need to cache these files
cache:
- key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths:
- windows/deps/sources64/
- windows/deps/lib64/
# We do not cache lib64-msys2, mingw64, octave64 and
# matlab64, because those are simply extracted from a tarball. It
# would be a waste of space and of (re-compression) time.
- key: $CI_JOB_NAME
# This cache is shared between all branches, to save space
paths:
- windows/deps/tarballs/
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths:
- windows/deps/sources64/
- windows/deps/lib64/
# We do not cache lib64-msys2, mingw64, octave64 and
# matlab64, because those are simply extracted from a tarball. It
# would be a waste of space and of (re-compression) time.
artifacts:
paths:
- windows/exe/*
@ -102,18 +86,16 @@ pkg_windows:
expire_in: 3 days
needs: [ "build_doc" ]
pkg_macOS_x86_64:
pkg_macOS:
stage: pkg
script:
# Enforce the arm64 meson for rewrite, as a workaround to https://github.com/mesonbuild/meson/issues/12282
- env PATH="/opt/homebrew/bin:$PATH" meson rewrite kwargs set project / version "$VERSION"
- ln -s ~/tarballs macOS/deps/x86_64
- make -C macOS build-x86_64
- ln -s ~/tarballs macOS/deps/
- make -C macOS
cache:
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths:
- macOS/deps/x86_64/sources64/
- macOS/deps/x86_64/lib64/
- macOS/deps/sources64/
- macOS/deps/lib64/
tags:
- macOS
artifacts:
@ -122,46 +104,32 @@ pkg_macOS_x86_64:
expire_in: 3 days
needs: [ "build_doc" ]
pkg_macOS_arm64:
stage: pkg
script:
# Enforce the arm64 meson for rewrite, as a workaround to https://github.com/mesonbuild/meson/issues/12282
- env PATH="/opt/homebrew/bin:$PATH" meson rewrite kwargs set project / version "$VERSION"
- ln -s ~/tarballs macOS/deps/arm64
- make -C macOS build-arm64
cache:
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths:
- macOS/deps/arm64/sources64/
- macOS/deps/arm64/lib64/
tags:
- macOS
.test_matlab_template:
stage: test
artifacts:
paths:
- macOS/pkg/*
expire_in: 3 days
needs: [ "build_doc" ]
- tests/**/*.m.log
- tests/**/*.m.trs
- tests/**/*.jnl
- tests/run_test_matlab_output.txt
when: always
needs: [ "build_binaries" ]
test_matlab:
stage: test
extends: .test_matlab_template
script:
- meson test -C build-matlab --no-rebuild --num-processes $(($(nproc) * 3 / 4))
artifacts:
paths:
- build-matlab/meson-logs/testlog.txt
when: always
needs: [ "build_matlab" ]
- autoreconf -si
- ./configure --disable-octave --with-matlab=/usr/local/MATLAB/$MATLAB_VERSION
- make -j $(($(nproc) * 3 / 4)) -C tests check-matlab
test_old_matlab:
stage: test
extends: .test_matlab_template
script:
- meson setup -Dbuild_for=matlab -Dmatlab_path=/opt/MATLAB/$OLD_MATLAB_VERSION -Dbuildtype=release build-old-matlab
- meson compile -v -C build-old-matlab
- meson test -C build-old-matlab --num-processes $(($(nproc) * 3 / 4))
artifacts:
paths:
- build-old-matlab/meson-logs/testlog.txt
when: always
- autoreconf -si
- ./configure --disable-octave --with-matlab=/usr/local/MATLAB/$OLD_MATLAB_VERSION
- 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:
@ -169,41 +137,22 @@ test_octave:
variables:
OPENBLAS_NUM_THREADS: 1
script:
- meson test -C build-octave --no-rebuild
- autoreconf -si
- ./configure --disable-matlab --with-octave=/usr/local/octave/$OCTAVE_VERSION
- make -j $(nproc) -C tests check-octave
artifacts:
paths:
- build-octave/meson-logs/testlog.txt
- tests/**/*.o.log
- tests/**/*.o.trs
- tests/**/*.jnl
- tests/run_test_octave_output.txt
when: always
needs: [ "build_octave" ]
needs: [ "build_binaries" ]
when: manual
test_clang_format:
stage: test
script:
- meson setup -Dbuild_for=octave build-clang-format
- ninja -C build-clang-format clang-format-check
needs: []
# For the sign and deploy jobs, we dont use the “needs” keyword, since we
# dont want those jobs to start before the “test” and “pkg” stages have
# succeeded. Hence we stick to the “dependencies” keyword.
sign_windows:
stage: sign
rules:
- if: '$CI_PROJECT_NAMESPACE == "Dynare" && $CI_COMMIT_REF_NAME == "master"'
when: on_success
- when: never
tags:
- sign
dependencies:
- pkg_windows
script:
- f=(windows/exe/*) && mkdir -p windows/exe-signed/ && osslsigncode sign -pkcs11module /usr/lib/x86_64-linux-gnu/libykcs11.so.2 -key "pkcs11:id=%01;type=private;pin-value=$YUBIKEY_PIN" -certs ~/cepremap-code-signing-comodo-sectigo.pem -n Dynare -i https://www.dynare.org -t http://timestamp.comodoca.com -in ${f[0]} -out windows/exe-signed/${f[0]##*/}
artifacts:
paths:
- windows/exe-signed/*
expire_in: 3 days
# For the deploy jobs, we dont use the “needs” keyword, since we dont want
# those jobs to start before the “test” and “pkg” stages have succeeded. Hence
# we stick to the “dependencies” keyword.
deploy_manual_unstable:
stage: deploy
@ -212,11 +161,13 @@ deploy_manual_unstable:
when: on_success
- when: never
tags:
- deploy
- restricted
dependencies:
- build_doc
script:
- rsync --recursive --links --delete build-doc/dynare-manual.html/ /srv/www.dynare.org/manual-unstable/
- 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
@ -225,19 +176,17 @@ deploy_snapshot_unstable:
when: on_success
- when: never
tags:
- deploy
- restricted
dependencies:
- pkg_source
- pkg_windows
- sign_windows
- pkg_macOS_arm64
- pkg_macOS_x86_64
- pkg_macOS
script:
- cp build-src/meson-dist/*.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-signed/*) && 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/exe/*) && osslsigncode sign -pkcs12 ~/cepremap-comodo-sectigo-code-signing.p12 -n Dynare -i https://www.dynare.org -t http://timestamp.comodoca.com -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/*-arm64.pkg) && cp ${f[0]} /srv/www.dynare.org/snapshot/macos-arm64/ && ln -sf ${f[0]##*/} /srv/www.dynare.org/snapshot/macos-arm64/dynare-latest-macos-arm64.pkg
- f=(macOS/pkg/*-x86_64.pkg) && cp ${f[0]} /srv/www.dynare.org/snapshot/macos-x86_64/ && ln -sf ${f[0]##*/} /srv/www.dynare.org/snapshot/macos-x86_64/dynare-latest-macos-x86_64.pkg
- 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

11
.gitmodules vendored
View File

@ -10,10 +10,19 @@
[submodule "matlab/utilities/tests"]
path = matlab/utilities/tests
url = ../../Dynare/m-unit-tests.git
[submodule "matlab/particles"]
path = matlab/particles
url = ../../Dynare/particles.git
[submodule "matlab/modules/dseries"]
path = matlab/dseries
path = matlab/modules/dseries
url = ../../Dynare/dseries.git
branch = master
[submodule "matlab/modules/reporting"]
path = matlab/modules/reporting
url = ../../Dynare/reporting.git
[submodule "contrib/jsonlab"]
path = contrib/jsonlab
url = https://github.com/fangq/jsonlab.git
[submodule "preprocessor"]
path = preprocessor
url = ../../Dynare/preprocessor.git

View File

@ -2,29 +2,31 @@
## Introduction
Hello from the Dynare Team! Were happy youre on this page because hopefully that means youre thinking of getting directly involved with the Dynare project. Herein, we outline how you can contribute to Dynare. Please read this document all the way through before contributing.
Hello from the Dynare Team! We're happy you're on this page because hopefully that means you're thinking of getting directly involved with the Dynare project. Herein, we outline how you can contribute to Dynare. Please read this document all the way through before contributing.
Please follow the steps in the sections below in order. Note that, though wed love for you to contribute code, you dont need to be a programmer to contribute to Dynare. You can report bugs, ask for enhancements, fix typos in the manual, contribute tests to the test suite, or do something we havent thought of yet!
Please follow the steps in the sections below in order. Note that, though we'd love for you to contribute code, you don't need to be a programmer to contribute to Dynare. You can report bugs, ask for enhancements, fix typos in the manual, contribute tests to the test suite, or do something we haven't thought of yet!
If something is not clear, dont hesitate to ask if you cant find the answer online. You can contact us directly at [dev@dynare.org](mailto:dev@dynare.org).
If something is not clear, don't hesitate to ask if you can't find the answer online. You can contact us directly at [dev@dynare.org](mailto:dev@dynare.org).
Please note that the repositories under the purview of this page are:
* [Dynare](https://git.dynare.org/Dynare/dynare)
* [Preprocessor](https://git.dynare.org/Dynare/preprocessor)
* [Particles](https://git.dynare.org/Dynare/particles)
* [Dseries](https://git.dynare.org/Dynare/dseries)
* [Reporting](https://git.dynare.org/Dynare/reporting)
* [Testsuite](https://git.dynare.org/Dynare/testsuite)
* [M-unit-tests](https://git.dynare.org/Dynare/m-unit-tests)
## Making your Intentions Known
Before making changes to the codebase, itd be helpful if you communicated your intentions with us. This will avoid double work and ensure that you dont contribute code that wont be included in Dynare for one reason or another.
Before making changes to the codebase, it'd be helpful if you communicated your intentions with us. This will avoid double work and ensure that you don't contribute code that won't be included in Dynare for one reason or another.
### Create your account on our GitLab instance
All the development of Dynare happens in [GitLab](https://about.gitlab.com/), which is an integrated environment for storing code under git, keeping track of issues and milestones, and perform testing. The Dynare Team has its own instance of GitLab.
In order to work with us, you need to create your account on our GitLab instance on the [register page](https://git.dynare.org/users/sign_in). Note that account requests are manually validated, so be prepared to wait for a couple of hours or days before your account is created; if your account request is rejected, do not hesitate to contact us directly.
In order to work with us, you need to create your account on our GitLab instance on the [register page](https://git.dynare.org/users/sign_in).
You will also need to register your SSH key in your GitLab profile if you want to contribute code.
@ -34,7 +36,7 @@ You can report bugs in both the stable and unstable versions of Dynare. Before r
To report a bug in Dynare, simply open a Gitlab issue in the repository where the bug resides. For example, to report a bug in Dynare itself, go to the [Dynare repository issue page](https://git.dynare.org/Dynare/dynare/issues) and click on "New Issue."
The minimal information to add is a subject and a description of the steps needed to reproduce the bug. However, the most helpful description would also provide the code to reproduce the bug (often times a `.mod` file). The most helpful `.mod` file is a minimal, quick-running example that reproduces the bug, but well take anything that will help us squash a bug.
The minimal information to add is a subject and a description of the steps needed to reproduce the bug. However, the most helpful description would also provide the code to reproduce the bug (often times a `.mod` file). The most helpful `.mod` file is a minimal, quick-running example that reproduces the bug, but we'll take anything that will help us squash a bug.
To include short amounts of code, please paste it into the description box, using the appropriate [GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html) code. For larger amounds of code like `.mod` files, please create a new [GitLab snippet](https://git.dynare.org/dashboard/snippets) and provide the link in the description box.
@ -42,13 +44,13 @@ To include short amounts of code, please paste it into the description box, usin
Issues are not only used to report bugs. They are also used to ask for improvements to the codebase or new features to Dynare in general. Please be descriptive when asking for improvements or new features. Links or references to papers or detailed examples are helpful.
Though our development priorities lay with those who finance Dynare and with what we think may most benefit the Dynare community, this does not mean we are closed to outside ideas for enhancements. On the contrary: we invite them! Moreover, if you are willing to program the enhancement you want, the odds of it being included in Dynare are much higher than if you needed us to do it. That said, it is best to create an issue with an enhancement idea **before** beginning the work. As stated above, this is important to avoid duplication of work and also because we wouldnt want you to take the time to work on something that would not end up being included in Dynare.
Though our development priorities lay with those who finance Dynare and with what we think may most benefit the Dynare community, this does not mean we are closed to outside ideas for enhancements. On the contrary: we invite them! Moreover, if you are willing to program the enhancement you want, the odds of it being included in Dynare are much higher than if you needed us to do it. That said, it is best to create an issue with an enhancement idea **before** beginning the work. As stated above, this is important to avoid duplication of work and also because we wouldn't want you to take the time to work on something that would not end up being included in Dynare.
## Get to Coding!
So, now youve reported the bug or asked for an enhancemnt by creating a GitLab issue. Thats already a great help. Thank you!
So, now you've reported the bug or asked for an enhancemnt by creating a GitLab issue. That's already a great help. Thank you!
Now, if you want to go the extra mile, youll volunteer to contribute code to fix the GitLab issue you created above. Once weve agreed that youll do it, please do the following:
Now, if you want to go the extra mile, you'll volunteer to contribute code to fix the GitLab issue you created above. Once we've agreed that you'll do it, please do the following:
1. Clone the Dynare repository:
* `git clone --recurse-submodules https://git.dynare.org/Dynare/dynare.git`
@ -61,7 +63,7 @@ Now, if you want to go the extra mile, youll volunteer to contribute code to
1. Do your work, all the while respecting the [Dynare Coding Guidelines](https://git.dynare.org/Dynare/dynare/-/wikis/CodingGuidelines)
1. You may also want to have a look at the [coding resources](https://git.dynare.org/Dynare/dynare/-/wikis/CodingResources)
As you work, your forked repository will likely fall out of sync with the main Dynare repository as well be working in parallel. No matter. Follow these steps to ensure your changes will be merge-able when theyre done:
As you work, your forked repository will likely fall out of sync with the main Dynare repository as we'll be working in parallel. No matter. Follow these steps to ensure your changes will be merge-able when they're done:
1. Get the changes from the main Dynare repository:
* `git checkout master`
@ -72,7 +74,7 @@ As you work, your forked repository will likely fall out of sync with the main D
* `git rebase origin/master`
* This last command may cause a conflict. It is up to you to resolve this conflict.
Once youve made the changes necessary to fix the bug or add an enhancement, ensure that it has been rebased on the master branch (following the steps above), commit it, push it to your forked Dynare repository, and create a pull request:
Once you've made the changes necessary to fix the bug or add an enhancement, ensure that it has been rebased on the master branch (following the steps above), commit it, push it to your forked Dynare repository, and create a pull request:
1. Get the latest changes from Dynare and rebase your branch on top of them (see above)
1. Commit your changes:
@ -84,17 +86,17 @@ Once youve made the changes necessary to fix the bug or add an enhancement, e
## Tests
The Dynare testsuite runs every time a commit is pushed, either in the official repository or in your personal repository, through [GitLab Continuous Integration](https://docs.gitlab.com/ee/ci/). Its how we quickly catch bugs that may have been introduced by changes made.
The Dynare testsuite runs every time a commit is pushed, either in the official repository or in your personal repository, through [GitLab Continuous Integration](https://docs.gitlab.com/ee/ci/). It's how we quickly catch bugs that may have been introduced by changes made.
The output from the latest run of the test suite can be found in the `test_matlab` job associated to the [latest pipeline](https://git.dynare.org/Dynare/dynare/pipelines). This is also a good place to start fixing bugs. If you see a `.mod` file that doesnt run in the test suite and think you can fix it, create an issue and once you have the go ahead, go for it!
The output from the latest run of the test suite can be found in the `test_matlab` job associated to the [latest pipeline](https://git.dynare.org/Dynare/dynare/pipelines). This is also a good place to start fixing bugs. If you see a `.mod` file that doesn't run in the test suite and think you can fix it, create an issue and once you have the go ahead, go for it!
### Integration tests
Its useful to contribute `.mod` files that test some aspect of Dynare that is not currently tested. A `.mod` file that runs into a bug is perfect. As the test suite currently takes several hours to run, we prefer you modify a current test to also create the bug youve found. If you cant do that, please add a new test that runs as quickly as possible. It will contain only those commands necessary to create the bug, nothing more. To contribute a test, after having made an issue and cloned and forked the repository as described above, do the following:
It's useful to contribute `.mod` files that test some aspect of Dynare that is not currently tested. A `.mod` file that runs into a bug is perfect. As the test suite currently takes several hours to run, we prefer you modify a current test to also create the bug you've found. If you can't do that, please add a new test that runs as quickly as possible. It will contain only those commands necessary to create the bug, nothing more. To contribute a test, after having made an issue and cloned and forked the repository as described above, do the following:
1. Modify the `mod_and_m_tests` variable in `meson.build` with a entry containing your test file name
1. If any ancillary files are needed to run your test, please include them in the `'extra'` field
1. Add and commit your test file and `meson.build` as described above
1. Modify the `MODFILES` variable in `tests/Makefile.am` with a line containing your test file name
1. If any ancillary files are needed to run your test, please include them in the `EXTRA_DIST` variable in `tests/Makefile.am`
1. Add and commit your test file and `tests/Makefile.am` as described above
1. Push and create a pull request as described above
### Unit tests

68
Makefile.am Normal file
View File

@ -0,0 +1,68 @@
SUBDIRS = preprocessor doc tests mex/sources
if ENABLE_MATLAB
SUBDIRS += mex/build/matlab
endif
if ENABLE_OCTAVE
SUBDIRS += mex/build/octave
endif
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = \
matlab \
dynare++ \
contrib \
NEWS.md \
license.txt \
README.md \
COPYING \
CONTRIBUTING.md \
windows \
macOS \
examples \
scripts \
.dir-locals.el
all-local:
# Create top-level preprocessor symlink needed by matlab/dynare.m (when Dynare is run
# from the locally-built copy)
$(LN_S) -f $(abs_builddir)/preprocessor/src/dynare-preprocessor$(EXEEXT) $(abs_builddir)/preprocessor/dynare-preprocessor$(EXEEXT)
# Create backward-compatibility symlink for old location of preprocessor
$(MKDIR_P) matlab/preprocessor64/
$(LN_S) -f $(abs_builddir)/preprocessor/src/dynare-preprocessor$(EXEEXT) $(abs_srcdir)/matlab/preprocessor64/dynare_m$(EXEEXT)
clean-local:
rm -f preprocessor/dynare-preprocessor$(EXEEXT)
rm -rf matlab/preprocessor64/
dist-hook:
rm -rf `find $(distdir)/matlab $(distdir)/examples -name *~`
rm -f $(distdir)/matlab/dynare_version.m
rm -rf $(distdir)/matlab/preprocessor64/
$(MKDIR_P) $(distdir)/mex/matlab $(distdir)/mex/octave
rm -rf `find $(distdir) -name '.git*'`
install-exec-local:
$(MKDIR_P) $(DESTDIR)$(pkglibdir)/preprocessor
# The following will break under Windows, but we dont use the install rule there
$(LN_S) -f $(bindir)/dynare-preprocessor$(EXEEXT) $(DESTDIR)$(pkglibdir)/preprocessor/dynare-preprocessor$(EXEEXT)
$(MKDIR_P) $(DESTDIR)$(pkglibdir)/contrib/ms-sbvar/TZcode
cp -r contrib/ms-sbvar/TZcode/MatlabFiles $(DESTDIR)$(pkglibdir)/contrib/ms-sbvar/TZcode
$(MKDIR_P) $(DESTDIR)$(pkglibdir)/contrib/jsonlab
cp -r contrib/jsonlab $(DESTDIR)$(pkglibdir)/contrib/jsonlab
cp -r examples $(DESTDIR)$(pkglibdir)
cp -r matlab $(DESTDIR)$(pkglibdir)
find $(DESTDIR)$(pkglibdir) -name LICENSE.md -delete
# Recreate backward-compatibility symlink
rm -f $(DESTDIR)$(pkglibdir)/matlab/preprocessor64/dynare_m$(EXEEXT)
$(LN_S) -f $(bindir)/dynare-preprocessor$(EXEEXT) $(DESTDIR)$(pkglibdir)/matlab/preprocessor64/dynare_m$(EXEEXT)
# We dont fail over doc install rules, since the user may deliberately not have compiled them
# (e.g. with the “nodoc” option under Debian)
$(MKDIR_P) $(DESTDIR)$(docdir)
-cp doc/*.pdf doc/gsa/gsa.pdf doc/parallel/parallel.pdf doc/dseries-and-reporting/dseriesReporting.pdf preprocessor/doc/preprocessor/preprocessor.pdf preprocessor/doc/macroprocessor/macroprocessor.pdf doc/manual/build/latex/dynare-manual.pdf $(DESTDIR)$(docdir)
-cp -r doc/manual/build/html $(DESTDIR)$(docdir)/dynare-manual.html
uninstall-local:
rm -rf $(DESTDIR)$(pkglibdir)
rm -rf $(DESTDIR)$(docdir)

519
NEWS.md
View File

@ -1,521 +1,3 @@
Announcement for Dynare 6.0 (on 2024-02-02)
===========================================
We are pleased to announce the release of Dynare 6.0.
This major release adds new features and fixes various bugs.
The Windows, macOS, MATLAB Online and source packages are already available for
download at [the Dynare website](https://www.dynare.org/download/).
This release is compatible with MATLAB versions ranging from 9.5 (R2018b) to
23.2 (R2023b), and with GNU Octave versions ranging from 7.1.0 to 8.4.0 (NB:
the Windows package requires version 8.4.0 specifically).
Major user-visible changes
--------------------------
- The Sequential Monte Carlo sampler as described by Herbst and Schorfheide
(2014) is now available under value `hssmc` for option
`posterior_sampling_method`.
- New routines for perfect foresight simulation with expectation errors. In
such a scenario, agents make expectation errors in that the path they had
anticipated in period 1 is not realized exactly. More precisely, in some
simulation periods, they may receive new information that makes them revise
their anticipation for the path of future shocks. Also, under this scenario,
it is assumed that agents behave as under perfect foresight, *i.e.* they
make their decisions as if there were no uncertainty and they knew exactly
the path of future shocks; the new information that they may receive comes
as a total surprise to them. Available under new
`perfect_foresight_with_expectation_errors_setup` and
`perfect_foresight_with_expectation_errors_solver` commands, and
`shocks(learnt_in=…)`, `mshocks(learnt_in=…)` and `endval(learnt_in=…)`
blocks.
- New routines for IRF matching with stochastic simulations:
- Both frequentist (as in Christiano, Eichenbaum, and Evans, 2005) and
Bayesian (as in Christiano, Trabandt, and Walentin, 2010) IRF matching
approaches are implemented. The core idea of IRF matching is to treat
empirical impulse responses (*e.g.* given from an SVAR or local projection
estimation) as data and select model parameters that align the models
IRFs closely with their empirical counterparts.
- Available under option `mom_method = irf_matching` option to the
`method_of_moments` command.
- New blocks `matched_irfs` and `matched_irfs_weights` for specifying the
values and weights of the empirical impulse response functions.
- Pruning à la Andreasen et al. (2018) is now available at an arbitrary
approximation order when performing stochastic simulations with
`stoch_simul`, and at 3rd order when performing particle filtering.
- New `log` option to the `var` statement. In addition to the endogenous
variable(s) thus declared, this option also triggers the creation of
auxiliary variable(s) equal to the log of the corresponding endogenous
variable(s). For example, given a `var(log) y;` statement, two endogenous
will be created (`y` and `LOG_y`), and an auxiliary equation linking the two
will also be added (equal to `y = exp(LOG_y);`). Moreover, every occurrence
of `y` in the model will be replaced by `exp(LOG_y)`. This option is, for
example, useful for performing a loglinear approximation of some variable(s)
in the context of a first-order stochastic approximation; or for ensuring
that the variable(s) stay(s) in the definition domain of the function
defining the steady state or the dynamic residuals when the nonlinear solver
is used.
- New model editing features
- Multiple `model` blocks are now supported (this was already working but
not explicitly documented).
- Multiple `estimated_params` blocks now concatenate their contents (instead
of overwriting previous ones, which was the former undocumented behavior);
an `overwrite` option has been added to provide the old behavior.
- New `model_options` statement to set model options in a global fashion.
- New `model_remove` command to remove equations.
- New `model_replace` block to replace equations.
- New `var_remove` command to remove variables (or parameters).
- New `estimated_params_remove` block to remove estimated parameters.
- Stochastic simulations
- Performance improvements for simulation of the solution under perturbation
and for particle filtering at higher order (⩾ 3).
- Performance improvement for the first order perturbation solution using
either cycle reduction (`dr=cycle_reduction` option) or logarithmic
reduction (`dr=logarithmic_reduction`).
- New `nomodelsummary` option to the `stoch_simul` command, to suppress the
printing of the model summary and the covariance of the exogenous shocks.
- Estimation
- A truncated normal distribution can now be specified as a prior, using the
3rd and 4th parameters of the `estimated_params` block as the bounds.
- New `conditional_likelihood` option to the `estimation` command. When the
option is set, instead of using the Kalman filter to evaluate the
likelihood, Dynare will evaluate the conditional likelihood based on the
first-order reduced form of the model by assuming that the initial state
vector is at its steady state.
- New `additional_optimizer_steps` option to the `estimation` command to
trigger the sequential execution of several optimizers when looking for
the posterior mode.
- The `generate_trace_plots` command now allows comparing multiple chains.
- The Geweke and Raftery-Lewis convergence diagnostics will now also be
displayed when `mh_nblocks>1`.
- New `robust`, `TolGstep`, and `TolGstepRel` options to the optimizer
available under `mode_compute=5` (“newrat”).
- New `brooks_gelman_plotrows` option to the `estimation` command for
controlling the number of parameters to depict along the rows of the
figures depicting the Brooks and Gelman (1998) convergence diagnostics.
- New `mh_init_scale_factor` option to the `estimation` command tor govern
the overdispersion of the starting draws when initializing several Monte
Carlo Markov Chains. This option supersedes the `mh_init_scale` option,
which is now deprecated.
- Steady state computation
- Steady state computation now accounts for occasionally-binding constraints
of mixed-complementarity problems (as defined by `mcp` tags).
- New `tolx` option to the `steady` command for governing the termination
based on the step tolerance.
- New `fsolve_options` option to the `steady` command for passing options to
`fsolve` (in conjunction with the `solve_algo=0` option).
- New option `from_initval_to_endval` option to the `homotopy_setup` block,
for easily computing homotopy from initial to terminal steady state (when
the former is already computed).
- New `non_zero` option to `resid` command to restrict display to non-zero
residuals.
- Perfect foresight
- Significant performance improvement of the `stack_solve_algo=1` option to
the `perfect_foresight_solver` command (Laffargue-Boucekkine-Juillard
algorithm) when used in conjunction with options `block` and/or `bytecode`
of the `model` block.
- New `relative_to_initval` option to the `mshocks` block, to use the
initial steady state as a basis for the multiplication when there is an
`endval` block.
- New `static_mfs` option to the `model` block (and to the `model_options`
command), for controlling the minimum feedback set computation for the
static model. It defaults to `0` (corresponding to the behavior in Dynare
version 5).
- Various improvements to homotopy
- New `endval_steady` option to the `perfect_foresight_setup` command for
computing the terminal steady state at the same time as the transitory
dynamics (and new options `steady_solve_algo`, `steady_tolf`,
`steady_tolx`, `steady_maxit` and `steady_markowitz` for controlling the
steady state nonlinear solver).
- New `homotopy_linearization_fallback` and
`homotopy_marginal_linearization_fallback` options to the
`perfect_foresight_solver` command to get an approximate solution when
homotopy fails to go to 100%.
- New `homotopy_initial_step_size`, `homotopy_min_step_size`,
`homotopy_step_size_increase_success_count` and
`homotopy_max_completion_share` options to the
`perfect_foresight_solver` command to fine tune the homotopy behavior.
- Purely backward, forward and static models are now supported by the
homotopy procedure.
- The `stack_solve_algo=1` and `stack_solve_algo=6` options of the
`perfect_foresight_solver` command were merged and are now synonymous.
They both provide the Laffargue-Boucekkine-Juillard algorithm and work
with and without the `block` and `bytecode` options of the `model` block.
Using `stack_solve_algo=1` is now recommended, but `stack_solve_algo=6` is
kept for backward compatibility.
- OccBin
- New `simul_reset_check_ahead_periods` option to the `occbin_setup` and
`occbin_solver` commands, for resetting `check_ahead_periods` in each
simulation period.
- new `simul_max_check_ahead_periods`, `likelihood_max_check_ahead_periods`,
and `smoother_max_check_ahead_periods` options to the `occbin_setup`
command, for truncating the number of periods for which agents check ahead
which regime is present.
- Optimal policy
- The `osr` command now accepts the `analytic_derivation` and
`analytic_derivation_mode` options.
- The `evaluate_planner_objective` command now computes the unconditional
welfare for higher-order approximations (⩾ 3).
- New `periods` and `drop` options to the `evaluate_planner_objective`
command.
- Semi-structural models
- New `pac_target_info` block for decomposing the PAC target into an
arbitrary number of components. Furthermore, in the presence of such a
block, the new `pac_target_nonstationary` operator can be used to select
the non stationary part of the target (typically useful in the error
correction term of the PAC equation).
- New `kind` option to the `pac_model` command. This option allows the user
to select the formula used to compute the weights on the VAR companion
matrix variables that are used to form PAC expectations.
- Performance improvement to `solve_algo=12` and `solve_algo=14`, which
significantly accelerates the simulation of purely backward, forward and
static models with the `perfect_foresight_solver` command and the routines
for semi-structural models.
- dseries classes
- The `remove` and `remove_` methods now accept a list of variables (they
would previously only accept a single variable).
- New MATLAB/Octave command `dplot` to plot mathematical expressions
generated from variables fetched from (different) dseries objects.
- Misc
- New `display_parameter_values` command to print the parameter values in
the command window.
- New `collapse_figures_in_tabgroup` command to dock all figures.
- Performance improvement for the `use_dll` option of the `model` block. The
preprocessor now takes advantage of parallelization when compiling the MEX
files.
- New mathematical primitives available: complementary error function
(`erfc`), hyperbolic functions (`cosh`, `sinh`, `tanh`, `acosh`, `asinh`,
`atanh`).
- New `last_simulation_period` option to the `initval_file` command.
- The `calib_smoother` command now accepts the `nobs` and
`heteroskedastic_filter` options.
- Under the MATLAB Desktop, autocompletion is now available for the `dynare`
command and other CLI commands (thanks to Eduard Benet Cerda from
MathWorks).
- Model debugging: The preprocessor now creates files for evaluating the
left- and right-hand sides of model equations separately. For a model file
called `ramst.mod`, you can call
`[lhs,rhs]=ramst.debug.static_resid(y,x,params);` (for the static model)
and `[lhs,rhs]=ramst.debug.dynamic_resid(y,x,params,steady_state);` (for
the dynamic model), where `y` are the endogenous, `x` the exogenous,
`params` the parameters, and `steady_state` is self-explanatory. NB: In
the dynamic case, the vector `y` of endogenous must have 3n elements
where n is the number of endogenous (including auxiliary ones); the
first n elements correspond to the lagged values, the middle n
elements to the contemporaneous values, and the last n elements to the
lead values.
- New interactive MATLAB/Octave command `search` for listing the equations
in which given variable(s) appear (requires `json` command line option).
- The `model_info` command allows to print the block decomposition even if
the `block` option of the `model` block has not been used, by specifying
the new options `block_static` and `block_dynamic`.
- There is now a default value for the global initialization file
(`GlobalInitFile` option of the configuration file): the `global_init.m`
in the Dynare configuration directory (typically
`$HOME/.config/dynare/global_init.m` under Linux and macOS, and
`c:\Users\USERNAME\AppData\Roaming\dynare\global_init.m` under Windows).
- For those compiling Dynare from source, the build system has been entirely
rewritten and now uses Meson; as a consequence, it is now faster and
easier to understand.
- References:
- 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), 1-49.
- Brooks, Stephen P., and Andrew Gelman (1998): “General methods for
monitoring convergence of iterative simulations,” *Journal of Computational
and Graphical Statistics*, 7, pp. 434455.
- Christiano, Eichenbaum and Charles L. Evans (2005): “Nominal Rigidities and
the Dynamic Effects of a Shock to Monetary Policy,” *Journal of Political
Economy*, 113(1), 145.
- Christiano, Lawrence J., Mathias Trabandt, and Karl Walentin (2010): “DSGE
Models for Monetary Policy Analysis,” In: *Handbook of Monetary Economics
3*, 285367.
- Herbst, Edward and Schorfheide, Frank (2014): "Sequential Monte Carlo
Sampling for DSGE Models," *Journal of Applied Econometrics*, 29,
1073-1098.
Incompatible changes
--------------------
- The default value of the `mode_compute` option of the `estimation` command
has been changed to `5` (it was previously `4`).
- When using block decomposition (with the `block` option of the `model`
block), the option `mfs` now defaults to `1`. This setting should deliver
better performance in perfect foresight simulation on most models.
- The default location for the configuration file has changed. On Linux and
macOS, the configuration file is now searched by default under
`dynare/dynare.ini` in the configuration directories defined by the XDG
specification (typically `$HOME/.config/dynare/dynare.ini` for the
user-specific configuration and `/etc/xdg/dynare/dynare.ini` for the
system-wide configuration, the former having precedence over the latter).
Under Windows, the configuration file is now searched by default in
`%APPDATA%\dynare\dynare.ini` (typically
`c:\Users\USERNAME\AppData\Roaming\dynare\dynare.ini`).
- The information stored in `oo_.endo_simul, oo_.exo_simul`, and `oo_.irfs` is
no longer duplicated in the base workspace. New helper functions
`send_endogenous_variables_to_workspace`,
`send_exogenous_variables_to_workspace`, and `send_irfs_to_workspace` have
been introduced to explicitly request these outputs and to mimic the old
behavior.
- The `dynare_sensitivity` command has been renamed `sensitivity`. The old
name is still accepted but triggers a warning.
- The syntax `resid(1)` is no longer supported.
- The `mode_compute=6` option to the `estimation` command now recursively
updates the covariance matrix across the `NumberOfMh` Metropolis-Hastings
runs, starting with the `InitialCovarianceMatrix` in the first run, instead
of computing it from scratch in every Metropolis-Hastings run.
- The `periods` command has been removed.
- The `Sigma_e` command has been removed.
- The `block` option of the `model` block no longer has an effect when used in
conjunction with `stoch_simul` or `estimation` commands.
- The Dynare++ executable is no longer distributed since almost all of its
functionalities have been integrated inside Dynare for MATLAB/Octave.
- A macro-processor variable defined without a value (such as `@#define var`
in the `.mod` file or alternatively `-Dvar` on the `dynare` command line) is
now assigned the `true` logical value (it was previously assigned `1`).
- The `parallel_slave_open_mode` option of the `dynare` command has been
renamed `parallel_follower_open_mode`.
- The `static` option of the `model_info` command is now deprecated and is
replaced by the `block_static` option.
Bugs that were present in 5.5 and that have been fixed in 6.0
-------------------------------------------------------------
* The `mh_initialize_from_previous_mcmc` option of the `estimation` command
would not work if estimation was conducted with a different prior and the
last draw in the previous MCMC fell outside the new prior bounds
* When specifying a generalized inverse Gamma prior, the hyperparameter
computation would erroneously ignore the resulting mean shift
* When using the `mh_recover` option of the `estimation` command, the status
bar always started at zero instead of showing the overall progress of the
recovered chain
* The `model_diagnostics` command would fail to check the correctness of
user-defined steady state files
* GSA: LaTeX output was not working as expected
* Forecasts and filtered variables could not be retrieved with the
`heteroskedastic_shocks` block
* The OccBin smoother would potentially not display all smoothed shocks with
`heteroskedastic_filter` option
* The OccBin smoother would crash if the number of requested periods was
smaller than the data length
* The multivariate OccBin smoother would return wrong results if the constraint
was binding in the first period
* The `plot_shock_decomposition` command would fail with the `init2shocks`
block if the `initial_condition_decomposition` was not run before
* LaTeX output under Windows failed to compile for `plot_priors=1` option of
the `estimation` command and Brooks and Gelman (1998) convergence diagnostics
* The plot produced by the `shock_decomposition` command was too big, making
the close button inaccessible
* Monthly dates for October, November and December (*i.e.* with a 2-digit month
number) were not properly interpreted by the preprocessor
* Theoretical moments computed by `stoch_simul` at `order=2` with `pruning`
would not contain unconditional and conditional variance decomposition
Announcement for Dynare 5.5 (on 2023-10-23)
===========================================
We are pleased to announce the release of Dynare 5.5.
This maintenance release fixes various bugs.
The Windows, macOS and source packages are already available for download at
[the Dynare website](https://www.dynare.org/download/).
All users are strongly encouraged to upgrade.
This release is compatible with MATLAB versions ranging from 8.3 (R2014a) to
23.2 (R2023b), and with GNU Octave version 8.3.0 (under Windows).
Note for macOS users with an Apple Silicon processor: this is the first Dynare
release that comes with native Apple Silicon (arm64) support under MATLAB.
Please download the corresponding package, to be used with MATLAB R2023b for
Apple Silicon.
Here is a list of the problems identified in version 5.4 and that have been
fixed in version 5.5:
* In a stochastic context, results could be incorrect if an endogenous with a
lead ⩾ 2 or an exogenous with a lead ⩾ 1 appeared in the argument(s) of a
call to a (nonlinear) external function
* With the `use_dll` option of the `model` block, the expression `sign(x)`
would evaluate to ±1 instead of 0 if `x=0`
* If the guess value given to the `steady` command was such that the residuals
were all below tolerance, except some that are `NaN`, then this guess value
was incorrectly accepted as the solution to the steady state problem
* The `method_of_moments` command with GMM was ignoring the
`analytic_standard_errors` option when using `mode_compute=4`
* Homotopy with the `extended_path` command at `order=0` was broken
* The `parallel_use_psexec` command-line option was ignored
* With the `bytecode` option of the `model` block, using the operators `abs()`,
`cbrt()` and `sign()` would lead to a crash
* The `fast` command-line option was broken under MATLAB with Windows
* Ramsey steady state computation could fail if an `expectation` or `diff`
operator was present in the model
* A crash could occur if some external function call was present in an
auxiliary variable
* The `endogenous_prior` option of the `estimation` command could erroneously
display a warning message about missing observations
* The `model_comparison` command would crash if the `.mod` file name had less
than four characters
* The `shock_decomposition` command would overwrite previously stored smoother
results
* The `x13` interface in dseries did not handle missing values, particularly at
the beginning of a series
* The `x13` interface in dseries would occasionally crash under Windows with
segmentation violations
* OccBin: estimation would crash if a previous `shocks(surprise)` simulation
was conducted
* The `internals` command would not find the location of the `_results.mat`
file
* The `prior optimize` command would not work with `mode_compute=5`
Announcement for Dynare 5.4 (on 2023-03-22)
===========================================
We are pleased to announce the release of Dynare 5.4.
This maintenance release fixes various bugs.
The Windows, macOS and source packages are already available for download at
[the Dynare website](https://www.dynare.org/download/).
All users are strongly encouraged to upgrade.
This release is compatible with MATLAB versions ranging from 8.3 (R2014a) to
9.14 (R2023a), and with GNU Octave version 8.1.0 (under Windows).
Note for macOS users with an Apple Silicon processor, and who are also MATLAB
users: the official MATLAB version for use on those processors is still the
Intel version (running through Rosetta 2), so the official Dynare package for
download on our website is built for Intel only. However, since Mathworks has
released a beta version of MATLAB for Apple Silicon, we created a beta package
of Dynare that you can try with it. See this forum thread for more details:
https://forum.dynare.org/t/testers-wanted-release-of-dynare-5-x-beta-for-apple-silicon-m1-m2-chips/20499
Here is a list of the problems identified in version 5.3 and that have been
fixed in version 5.4:
* Files installed through the Windows installer had too weak permissions and
could be modified by unpriviledged local users, if the default installation
location (`c:\dynare\`) had been chosen
* Estimation:
+ the `load_results_after_load_mh` option would not find the location of the
results file
+ the computation of prior/posterior statistics would crash if the value of
the `filter step_ahead` option was greater than 1 without requesting a
`forecast` or the `smoother`
+ NaN or complex parameters returned by steady state files were not correctly
handled
+ `analytical_derivation` could be triggered with `endogenous_prior` but
would not take the endogenous prior into account for the Jacobian and
Hessian
* OccBin:
+ running the `calib_smoother` command with `smoother_inversion_filter` would
crash unless `likelihood_inversion_filter` was also specified
+ running the piecewise Kalman smoother would crash if an error was
encountered during computation of the decision rules
* PAC equation estimation through iterative OLS would crash if the auxiliary
model contained a constant
* The variable label was incorrect for leads and lags of exogenous variables in
the display of decision rules and in the `model_info` command
* Declaring a `trend_var` variable while not having a `var(deflator=...)`
statement would cause the preprocessor to crash
* Macro processor: error messages following a `@#define`, `@#include` or
`@#includepath` directive could in some cases point to a line number off by 1
* Perfect foresight simulations: the `debug` option would not preserve
sparsity, causing out of memory errors
Announcement for Dynare 5.3 (on 2022-11-21)
===========================================
@ -563,6 +45,7 @@ fixed in version 5.3:
* Problems related to Bayesian or ML estimation:
+ `mh_recover` and `load_mh_file` would not find the saved proposal density
and had to rely on the `_mode` file
+ `load_results_after_load_mh` would not find the location of the `_results` file
+ When requesting `bayesian_irf` together with `loglinear`, the resulting
IRFs would be incorrect
+ the diffuse Kalman smoother initialization (`lik_init=3`) was wrong when

392
README.md
View File

@ -33,6 +33,8 @@ This source can be retrieved in three forms:
- 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
@ -43,8 +45,8 @@ determine the type of your MATLAB/Octave installation, type:
```matlab
>> computer
```
at the MATLAB/Octave prompt. Under MATLAB, if it returns `PCWIN64`, `GLNX64`,
`MACI64` or `MACA64` then it is a 64-bit MATLAB; if it returns `PCWIN`, `MACI` or `GLNX`,
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.
@ -56,7 +58,6 @@ a 32-bit Octave.
1. [**Fedora, CentOS or RHEL**](#fedora-centos-or-rhel)
1. [**Windows**](#windows)
1. [**macOS**](#macos)
1. [**Docker**](#docker)
## General Instructions
@ -64,27 +65,28 @@ a 32-bit Octave.
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](https://gcc.gnu.org/), version 10 or later, with
gcc, g++ and gfortran
gcc, g++ and gfortran (mandatory)
- [MATLAB](https://mathworks.com) (if you want to compile the MEX for MATLAB)
- [GNU Octave](https://www.octave.org) with
- the development headers (if you want to compile the MEX for Octave)
- the development libraries corresponding to the [UMFPACK](https://people.engr.tamu.edu/davis/suitesparse.html) packaged with Octave (if you want to compile the MEX for Octave)
- the [statistics](https://octave.sourceforge.io/statistics/) package and, optionally, the [control](https://octave.sourceforge.io/control/), [io](https://octave.sourceforge.io/io/) and [optimization](https://octave.sourceforge.io/optim/) packages, either installed via your package manager or through [Octave Forge](https://octave.sourceforge.io/)
- [Meson](https://mesonbuild.com), version 0.64.0 or later
- [Pkgconf](http://pkgconf.org/), or another pkg-config implementation
- [Bash](https://www.gnu.org/software/bash/)
- the development libraries corresponding to the [UMFPACK](https://people.engr.tamu.edu/davis/suitesparse.html) packaged with Octave
- Optionally, the [Control](https://octave.sourceforge.io/control/), [IO](https://octave.sourceforge.io/io/), [Optimization](https://octave.sourceforge.io/optim/) and [Statistics](https://octave.sourceforge.io/statistics/) package either installed via your package manager or through [Octave Forge](https://octave.sourceforge.io/).
- [Boost libraries](https://www.boost.org), version 1.36 or later
- [Bison](https://www.gnu.org/software/bison/), version 3.2 or later
- [Flex](https://github.com/westes/flex), version 2.5.4 or later
- [MAT File I/O library](https://sourceforge.net/projects/matio/), version 1.5 or later (only when compiling for Octave)
- [SLICOT](http://www.slicot.org)
- [GSL library](https://www.gnu.org/software/gsl/)
- [Bison](https://www.gnu.org/software/bison/), version 3.2 or later (only if you get the source through Git)
- [Flex](https://github.com/westes/flex), version 2.5.4 or later (only if you get the source through Git)
- [Autoconf](https://www.gnu.org/software/autoconf/), version 2.62 or later (only if you get the source through Git)
- [Automake](https://www.gnu.org/software/automake/), version 1.11.2 or later (only if you get the source through Git)
- [MAT File I/O library](https://sourceforge.net/projects/matio/), version 1.5 or later (if you want to compile Markov-Switching code, the estimation DLL, and the k-order DLL)
- [SLICOT](http://www.slicot.org) (if you want to compile the Kalman steady state DLL)
- [GSL library](https://www.gnu.org/software/gsl/) (if you want to compile Markov-Switching code)
- A decent LaTeX distribution (if you want to compile PDF documentation),
ideally with Beamer
- For building the reference manual:
- [Sphinx](https://www.sphinx-doc.org/)
- [MathJax](https://www.mathjax.org/)
- [Doxygen](https://www.doxygen.nl) (if you want to build Dynare preprocessor source documentation)
- [X-13ARIMA-SEATS Seasonal Adjustment Program](https://www.census.gov/data/software/x13as.html)
### Preparing the sources
@ -96,78 +98,107 @@ have the [Git LFS](https://git-lfs.github.com/) extension installed):
```sh
git clone --recurse-submodules https://git.dynare.org/Dynare/dynare.git
cd dynare
autoreconf -si
```
If you want a certain version (e.g. 5.x) , then add `--single-branch --branch 5.x` to the git clone command.
The last line runs Autoconf and Automake in order to prepare the build environment (this is not necessary if you got the sources from an official source archive or the source snapshot). If you want a certain version (e.g. 5.x) , then add `--single-branch --branch 5.x` to the git clone command.
### Configuring the build directory
### Configuring the build tree
If you want to compile for MATLAB, please run the following (after adapting the path to MATLAB):
Simply launch the configure script from a terminal:
```sh
meson setup -Dmatlab_path=/usr/local/MATLAB/R2023b -Dbuildtype=debugoptimized build-matlab
./configure --with-matlab=<…>
```
The build directory will thus be `build-matlab`.
where the path to MATLAB is specified.
Or for Octave:
```sh
meson setup -Dbuild_for=octave -Dbuildtype=debugoptimized build-octave
Some important options:
- `--disable-matlab`: skip the compilation of MEX files for MATLAB
- `--disable-octave`: skip the compilation of MEX files for Octave
- `--disable-doc`: skip the compilation of the documentation (PDF and HTML)
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. 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
```
The build directory will thus be `build-octave`.
Note that if you do not chose `build-matlab` (under MATLAB) or `build-octave`
(under Octave) as the build directory, you will need to set the environment
variable `DYNARE_BUILD_DIR` to the full path of your build tree, before running
MATLAB or Octave, if you want Dynare to be able to find the preprocessor and
the MEX files.
It is possible to specify various Meson options, see the Meson documentation
for more details. Modifying options of an existing build directory can be
done using the `meson configure` command.
(where you need to replace `<DYNARE_ROOT>` with the full path to your Dynare copy).
### Building
For compiling the preprocessor and the MEX files:
Binaries are built with:
```sh
meson compile -C <builddir>
make
```
where `<builddir>` is the build directory, typically either `build-matlab` or `build-octave`.
PDF and HTML documentation can be built with:
PDF and HTML documentation are respectively built with:
```sh
meson compile -C <builddir> doc
make pdf
make html
```
### Check
Dynare comes with unit tests (in the MATLAB functions) and integration tests (under the `tests` subfolder). All the tests can be run with:
The Git source comes with unit tests (in the MATLAB functions) and integration tests (under the `tests` subfolder). All the tests can be run with:
```sh
meson test -C <builddir>
make check
```
in the `tests` subfolder. If Dynare has been compiled against MATLAB and Octave, the tests will be run with both MATLAB and Octave. Depending on the performance of your machine, this can take several hours. It is possible to run the tests only with MATLAB:
```sh
make check-matlab
```
or only with Octave:
```sh
make check-octave
```
Depending on the performance of your machine, this can take several hours.
Note that running the testsuite with Octave requires the additional packages `pstoedit`, `epstool`, `xfig`, and `gnuplot`.
Often, it does not make sense to run the complete testsuite. For instance, if you modify codes only related to the perfect foresight model solver, you can decide to run only a subset of the integration tests, with:
A summary of the results is available in `tests/run_test_matlab_output.txt` or `tests/run_test_octave_output.txt`. Often, it does not make sense to run the complete testsuite. For instance, if you modify codes only related to the perfect foresight model solver, you can decide to run only a subset of the integration tests, with:
```sh
meson test -C <builddir> --suite deterministic_simulations
make deterministic_simulations
```
This will run all the integration tests in `tests/deterministic_simulations`.
This syntax also works with a nested directory (e.g. `--suite deterministic_simulations/purely_forward`).
Finally if you want to run a single integration test, e.g. `deterministic_simulations/lbj/rbc.mod`:
This will run all the integration tests in `tests/deterministic_simulations` with MATLAB and Octave. Again, it is possible to do this only with MATLAB:
```sh
meson test -C <builddir> deterministic_simulations/lbj/rbc.mod
make m/deterministic_simulations
```
NB: Some individual tests cannot be run using that syntax, if they are a dependency in a chain of tests (see the `mod_and_m_tests` variable `meson.build`); in that case, you should use the name of the last `.mod` file in the chain as the test name to be passed to `meson test`.
or with Octave:
```sh
make o/deterministic_simulations
```
Finally if you want to run a single integration test, e.g. `deterministic_simulations/lbj/rbc.mod` with MATLAB:
```sh
make deterministic_simulations/lbj/rbc.m.trs
```
or with Octave:
```sh
make deterministic_simulations/lbj/rbc.o.trs
```
The result of the test (`PASSED` or `FAILED`) will be printed in the terminal, the produced log can be displayed with:
```sh
make deterministic_simulations/lbj/rbc.m.drs
```
or
```sh
make deterministic_simulations/lbj/rbc.o.drs
```
Note that only tests will be executed where the `m.trs/o.trs` does not yet exist. You can run
```sh
make clean
```
in the `tests` folder to delete files that were created by the run of the testsuite. You can also manually delete the desired `m.trs/o.trs` file(s).
## Debian or Ubuntu
All the prerequisites are packaged:
- `gcc`
- `g++`
- `build-essential` (for gcc, g++ and make)
- `gfortran`
- `octave-dev` (or `liboctave-dev` on older Debian/Ubuntu releases)
- `liboctave-dev`
- `libboost-graph-dev`
- `libgsl-dev`
- `libmatio-dev`
@ -175,31 +206,40 @@ All the prerequisites are packaged:
- `libsuitesparse-dev`
- `flex` and `libfl-dev`
- `bison`
- `meson`
- `pkgconf`
- `autoconf`
- `automake`
- `texlive`
- `texlive-publishers` (for Econometrica bibliographic style)
- `texlive-latex-extra` (for fullpage.sty)
- `texlive-fonts-extra` (for ccicons)
- `texlive-latex-recommended`
- `texlive-science` (for amstex)
- `texlive-plain-generic`
- `lmodern` (for macroprocessor PDF)
- `python3-sphinx`
- `tex-gyre`
- `latexmk`
- `libjs-mathjax`
- `doxygen`
- `x13as`
You can install them all at once with:
```sh
apt install gcc g++ gfortran octave-dev libboost-graph-dev libgsl-dev libmatio-dev libslicot-dev libslicot-pic libsuitesparse-dev flex libfl-dev bison meson pkgconf texlive texlive-publishers texlive-latex-extra texlive-fonts-extra texlive-science lmodern python3-sphinx make tex-gyre latexmk libjs-mathjax x13as
apt install build-essential gfortran liboctave-dev libboost-graph-dev libgsl-dev libmatio-dev libslicot-dev libslicot-pic libsuitesparse-dev flex libfl-dev bison autoconf automake texlive texlive-publishers texlive-latex-extra texlive-fonts-extra texlive-latex-recommended texlive-science texlive-plain-generic lmodern python3-sphinx tex-gyre latexmk libjs-mathjax doxygen x13as
```
If you use MATLAB, we strongly advise to also `apt install matlab-support` and confirm to rename the GCC libraries shipped with MATLAB to avoid possible conflicts with GCC libraries shipped by your distribution.
Tested on
- Debian “Buster” 10
- Debian “Bullseye” 11
- Ubuntu 20.04
- Ubuntu 20.10
## Fedora, CentOS or RHEL
Almost all prerequisites are packaged:
- `gcc`, `gcc-c++`
- `gcc`, `gcc-c++`, `make`
- `gcc-gfortran`
- `boost-devel`
- `gsl-devel`
@ -207,23 +247,24 @@ Almost all prerequisites are packaged:
- `suitesparse-devel`
- `flex`
- `bison`
- `meson`
- `autoconf`
- `automake`
- `redhat-rpm-config`
- `octave`, `octave-devel`, `octave-statistics`, `octave-io`, `octave-optim`, `octave-control`
- `texlive-scheme-minimal`, `texlive-collection-publishers`, `texlive-collection-latexextra`, `texlive-collection-fontsextra`, `texlive-collection-latexrecommended`, `texlive-collection-science`, `texlive-collection-plaingeneric`, `texlive-lm`
- `python3-sphinx`
- `latexmk`
- `mathjax`
- `make` (for building Slicot)
- `doxygen`
You can install them all at once with:
```sh
# Minimal packages
dnf install -y gcc gcc-c++ make gcc-gfortran boost-devel gsl-devel matio-devel suitesparse-devel flex bison meson redhat-rpm-config
# Octave packages
# Minimal packages (use --disable-doc and --disable-octave flags)
dnf install -y gcc gcc-c++ make gcc-gfortran boost-devel gsl-devel matio-devel suitesparse-devel flex bison autoconf automake redhat-rpm-config
# Octave packages (use --disable-doc flag)
dnf install octave octave-devel octave-statistics octave-io octave-optim octave-control
# Documentation packages (only needed if you build documentation)
dnf install texlive-scheme-minimal texlive-collection-publishers texlive-collection-latexextra texlive-collection-fontsextra texlive-collection-latexrecommended texlive-collection-science texlive-collection-plaingeneric texlive-lm python3-sphinx latexmk mathjax
# Documentation packages
dnf install texlive-scheme-minimal texlive-collection-publishers texlive-collection-latexextra texlive-collection-fontsextra texlive-collection-latexrecommended texlive-collection-science texlive-collection-plaingeneric texlive-lm python3-sphinx latexmk mathjax doxygen
```
In Fedora these are available from the default repositories; whereas for CentOS and RHEL you need to enable the [Extra Packages for Enterprise Linux (EPEL)](https://fedoraproject.org/wiki/EPEL) repository and either the PowerTools repository for CentOS or the CodeReady Linux Builder repository for RHEL:
```sh
@ -234,7 +275,7 @@ dnf config-manager --set-enabled PowerTools
ARCH=$( /bin/arch )
subscription-manager repos --enable "codeready-builder-for-rhel-8-${ARCH}-rpms"
```
The documentation packages have slightly different names in CentOS and RHEL, but this should only impact you if you build the documentation.
The documentation packages have slightly different names in CentOS and RHEL, you can also choose to pass the `--disable-doc` flag to your configure script to skip these dependencies.
`Slicot` and `x13as` need to be compiled from source:
@ -245,19 +286,16 @@ cd /home/$USER/dynare/slicot
wget https://deb.debian.org/debian/pool/main/s/slicot/slicot_5.0+20101122.orig.tar.gz
tar xf slicot_5.0+20101122.orig.tar.gz
cd slicot-5.0+20101122
mkdir -p /home/$USER/dynare/slicot/lib
# The following two lines are only for MATLAB
make FORTRAN=gfortran OPTS="-O2 -fPIC -fdefault-integer-8" LOADER=gfortran lib
cp slicot.a /home/$USER/dynare/slicot/lib/libslicot64_pic.a
# The following two lines are only for Octave
make FORTRAN=gfortran OPTS="-O2 -fPIC" LOADER=gfortran lib
cp slicot.a /home/$USER/dynare/slicot/lib/libslicot_pic.a
mkdir -p /home/$USER/dynare/slicot/lib
cp slicot.a /home/$USER/dynare/slicot/lib/libslicot64_pic.a #for matlab
cp slicot.a /home/$USER/dynare/slicot/lib/libslicot_pic.a #for octave
# compile x13as from source and put it into /usr/bin/
mkdir -p /home/$USER/dynare/x13as
cd /home/$USER/dynare/x13as
wget https://www2.census.gov/software/x-13arima-seats/x13as/unix-linux/program-archives/x13as_asciisrc-v1-1-b60.tar.gz
tar xf x13as_asciisrc-v1-1-b60.tar.gz
wget https://www2.census.gov/software/x-13arima-seats/x13as/unix-linux/program-archives/x13as_asciisrc-v1-1-b58.tar.gz
tar xf x13as_asciisrc-v1-1-b58.tar.gz
sed -i "s|-static| |" makefile.gf # this removes '-static' in the makefile.gf
make -f makefile.gf FFLAGS="-O2 -std=legacy" PROGRAM=x13as
sudo cp x13as /usr/bin/
@ -265,16 +303,17 @@ sudo cp x13as /usr/bin/
If you use MATLAB, we strongly advise to also rename or exclude the GCC libraries shipped with MATLAB to avoid possible conflicts with GCC libraries shipped by Fedora, see e.g. [Matlab on Fedora 33](https://mutschler.eu/linux/install-guides/fedora-post-install/#matlab) or [MATLAB-ArchWiki](https://wiki.archlinux.org/index.php/MATLAB) for instructions.
Now use the following commands if using MATLAB (adapt them for Octave, see above):
Keep in mind to use the `--with-slicot` option to the configure command, e.g.:
```sh
cd /home/$USER/dynare
git clone --recurse-submodules https://git.dynare.org/dynare/dynare.git unstable
cd unstable
meson setup -Dmatlab_path=/usr/local/MATLAB/R2023b -Dfortran_args="[ '-B', '/home/$USER/dynare/slicot']" -Dbuildtype=debugoptimized build-matlab
meson compile -C build-matlab
autoreconf -si
./configure --with-slicot=/home/$USER/dynare/slicot --with-matlab=/usr/local/MATLAB/R2020b
make -j$(($(nproc)+1)) #rule of thumb: one more than CPUs as shown by e.g. lscpu
```
If your distribution ships an older version of `bison`, compile it from source and append it *temporarily* to your path before running meson:
If your distribution ships an older version of `bison`, compile it from source and append it *temporarily* to your path before calling the configure script:
```sh
bison --version # bison (GNU Bison) 3.0.4
mkdir -p /home/$USER/dynare/bison
@ -290,6 +329,12 @@ bison --version # bison (GNU Bison) 3.6.4
```
Now configure dynare as above.
Tested on
- CentOS 8
- Fedora Workstation 32
- Fedora Workstation 33
- Red Hat Enterprise Linux 8
## Windows
- Install [MSYS2](http://www.msys2.org)
@ -303,9 +348,9 @@ pacman -Syu
window to complete the upgrade.
- Install all needed dependencies:
```sh
pacman -S git bison flex make tar mingw-w64-x86_64-meson 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-pkgconf
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
```
- Compile and install SLICOT
- Compile and install SLICOT, needed for the `kalman_steady_state` MEX file
```sh
wget https://deb.debian.org/debian/pool/main/s/slicot/slicot_5.0+20101122.orig.tar.gz
tar xf slicot_5.0+20101122.orig.tar.gz
@ -319,10 +364,11 @@ cd ..
```sh
git clone --recurse-submodules https://git.dynare.org/Dynare/dynare.git
cd dynare
autoreconf -si
```
- Configure Dynare from the source directory:
```sh
meson setup -Dmatlab_path=<…> -Dbuildtype=debugoptimized -Dprefer_static=true -Dfortran_args="['-B','/usr/local/lib']" build-matlab
./configure --with-slicot=/usr/local --with-matlab=<…> --disable-octave --disable-doc
```
where the path of MATLAB is specified. Note that you should use
the MSYS2 notation and not put spaces in the MATLAB path, so you probably want
@ -332,11 +378,11 @@ does not have short filenames (8dot3), then you can run `mkdir -p
then pass `/usr/local/MATLAB/…` as MATLAB path to the configure script.
- Compile:
```sh
meson compile -C build-matlab
make
```
- Run the testsuite:
```sh
meson test -C build-matlab
make -C tests check-matlab
```
**Note:** The above assumes that you have a 64-bit version of MATLAB. It can be
@ -351,168 +397,118 @@ adapted to a 32-bit MATLAB with the following modifications:
currently not supported.
## macOS
Dynare supports both Intel and Apple Silicon chips and is compiled from source
using a [Homebrew](https://brew.sh/) toolchain. If you have an Apple silicon processor
(*M1/M2 PRO/MAX/ULTRA*), you can compile Dynare both for Intel's `x86_64` (using Rosetta 2)
as well as Apple's native `arm64` platform by using the corresponding Homebrew packages.
If you have an Intel chip you can only compile for `x86_64`.
using a [Homebrew](https://brew.sh/) toolchain. However, if you have a *M1*, *M1 PRO*
or *M1 MAX* processor, you need to make sure that you are not using the ARM
Homebrew packages. This is due to the fact that although MATLAB runs natively on
Intel, it is not yet available in an ARM version and therefore must be run with the
Intel compatibility layer called Rosetta 2. Accordingly, if you are on Apple Silicon
you need to compile Dynare under Rosetta 2 as well and use the Intel packages from
Homebrew. You can check this by e.g. running `which brew` which should point to
`/usr/local/bin/brew` and not to `/opt/homebrew/bin/brew`. In the steps below, we
create a temporary alias to ensure that `brew` points to the Intel packages.
You can check the platform of your current Homebrew installation by e.g. running
`which brew` which should point to `/opt/homebrew/bin/brew` for `arm64` and to
`/usr/local/bin/brew` for `x86_64` systems. In the steps below, we
create a temporary environment variable `BREWDIR` to ensure that the correct packages are used.
For the following steps open Terminal.app and enter the commands listed below.
The following commands install all requirements and Dynare from source.
They should be entered at the command prompt in Terminal.app.
### Preparatory work
- Install the Xcode Command Line Tools:
```sh
xcode-select --install
```
- Install Rosetta 2 (Apple Silicon only):
```sh
softwareupdate --install-rosetta --agree-to-license
```
- Install the Xcode Command Line Tools:
```sh
xcode-select --install
```
- Install [Homebrew](https://brew.sh/):
Create environment variables for which platform you want to compile for, i.e. either `arm64` or `x86_64`:
For `arm64` run the following commands:
```sh
export ARCH=arm64
export BREWDIR=/opt/homebrew
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
The prefix `arch -x86_64` makes sure that you are using Rosetta 2 to install Homebrew.
- Apple Silicon only: Make a (temporary) alias to run `brew` under Rosetta 2:
```sh
alias brew='arch -x86_64 /usr/local/bin/brew'
which brew
#brew: aliased to arch -x86_64 /usr/local/bin/brew
```
For `x86_64` run the following commands:
- Install required Homebrew packages and link sphinx-doc:
```sh
export ARCH=x86_64
export BREWDIR=/usr/local
brew install automake bison flex boost gcc gsl libmatio veclibfort octave sphinx-doc wget
brew link --force sphinx-doc
```
Install Homebrew using the environment variables:
- Install [MacTeX](http://www.tug.org/mactex/index.html) using the universal installer. MacTeX runs natively on both ARM and Intel machines. On Apple Silicon, we need to put `pdflatex` and `bibtex` into our path:
```sh
arch -$ARCH /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
ln -s /Library/TeX/texbin/pdflatex /usr/local/bin/pdflatex
ln -s /Library/TeX/texbin/bibtex /usr/local/bin/bibtex
```
The prefix `arch -arm64` or `arch -x86_64` makes sure that you are installing the correct packages.
Don't forget to run the displayed commands (**Next steps**) in the terminal to add Homebrew to your PATH.
Alternatively, if you dont want to install MacTeX, you should pass the `--disable-doc` flag to the `configure` command below.
If you have both Homebrew installations installed, make sure that you are accessing the correct packages by temporarily (!) prepending it to the path:
- Install MATLAB and additional toolboxes. We recommend, but don't require, the following: Optimization, Global Optimization, Statistics and Machine Learning, Econometrics, and Control System. As there is no ARM version of MATLAB yet, Rosetta 2 will be used on Apple Silicon machines. Don't forget to run MATLAB at least once to make sure you have a valid license.
- Compile and install SLICOT, needed for the `kalman_steady_state` MEX file.
```sh
export PATH="$BREWDIR/bin:$PATH"
```
- Install required Homebrew packages:
```sh
arch -$ARCH $BREWDIR/bin/brew install meson bison flex boost gcc gsl libmatio veclibfort octave sphinx-doc docutils wget pkg-config git-lfs
```
If you are installing `git-lfs` for the first time, you need to run `git lfs install` once after installing it.
- Link the sphinx-doc package to be able to compile the documentation:
```sh
arch -$ARCH $BREWDIR/bin/brew link --force sphinx-doc
```
- Install [MacTeX](http://www.tug.org/mactex/index.html) using the universal installer, if you want to build the documentation. MacTeX runs natively on both ARM and Intel machines. On Apple Silicon, it is advised to symlink `pdflatex`, `bibtex` and `latexmk` into `/usr/local/bin`:
```sh
sudo ln -s /Library/TeX/texbin/pdflatex /usr/local/bin/pdflatex
sudo ln -s /Library/TeX/texbin/bibtex /usr/local/bin/bibtex
sudo ln -s /Library/TeX/texbin/latexmk /usr/local/bin/latexmk
```
If you don't have admin privileges, then you can also symlink them into `$HOME/.local/bin` and add this folder to your PATH.
- Install MATLAB and additional toolboxes.
We recommend, but don't require, the following: Optimization, Global Optimization, Statistics and Machine Learning, Econometrics, and Control System.
For Apple Silicon: MATLAB offers a native Apple silicon version (arm64) as of version R2023b, see [the official instructions](https://de.mathworks.com/support/requirements/apple-silicon.html) how to install it.
You can also run the Intel version (x86_64) under Rosetta 2.
Don't forget to run MATLAB at least once to make sure you have a valid license.
- Create a folder for Dynare and its dependencies
```sh
export DYNAREDIR=$HOME/dynare
```
- Compile and install SLICOT
```sh
mkdir -p $DYNAREDIR/slicot/lib
cd $DYNAREDIR/slicot
curl -O https://deb.debian.org/debian/pool/main/s/slicot/slicot_5.0+20101122.orig.tar.gz
mkdir -p $HOME/dynare/slicot
cd $HOME/dynare/slicot
wget https://deb.debian.org/debian/pool/main/s/slicot/slicot_5.0+20101122.orig.tar.gz
tar xf slicot_5.0+20101122.orig.tar.gz
cd slicot-5.0+20101122
make -j$(sysctl -n hw.ncpu) FORTRAN=$BREWDIR/bin/gfortran OPTS="-O2" LOADER=gfortran lib
cp slicot.a $DYNAREDIR/slicot/lib/libslicot_pic.a
make -j$(sysctl -n hw.physicalcpu) FORTRAN=gfortran OPTS="-O2" LOADER=gfortran lib
cp slicot.a /usr/local/lib/libslicot_pic.a
make clean
make -j$(sysctl -n hw.ncpu) FORTRAN=$BREWDIR/bin/gfortran OPTS="-O2 -fdefault-integer-8" LOADER=gfortran lib
cp slicot.a $DYNAREDIR/slicot/lib/libslicot64_pic.a
make -j$(sysctl -n hw.physicalcpu) FORTRAN=gfortran OPTS="-O2 -fdefault-integer-8" LOADER=gfortran lib
cp slicot.a /usr/local/lib/libslicot64_pic.a
cd $HOME/dynare
```
- Compile and install the X-13ARIMA-SEATS Seasonal Adjustment Program
```sh
mkdir -p $DYNAREDIR/x13as
cd $DYNAREDIR/x13as
curl -O https://www2.census.gov/software/x-13arima-seats/x13as/unix-linux/program-archives/x13as_asciisrc-v1-1-b60.tar.gz
tar xf x13as_asciisrc-v1-1-b60.tar.gz
mkdir -p $HOME/dynare/x13as
cd $HOME/dynare/x13as
wget https://www2.census.gov/software/x-13arima-seats/x13as/unix-linux/program-archives/x13as_asciisrc-v1-1-b58.tar.gz
tar xf x13as_asciisrc-v1-1-b58.tar.gz
sed -i '' 's/-static//g' makefile.gf
make -j$(sysctl -n hw.ncpu) -f makefile.gf FC=$BREWDIR/bin/gfortran LINKER=$BREWDIR/bin/gcc-13 FFLAGS="-O2 -std=legacy" LDFLAGS=-static-libgcc LIBS="$BREWDIR/lib/gcc/current/libgfortran.a /$BREWDIR/lib/gcc/current/libquadmath.a" PROGRAM=x13as
sudo cp $DYNAREDIR/x13as/x13as /usr/local/bin/x13as
cd $DYNAREDIR
make -j$(sysctl -n hw.physicalcpu) -f makefile.gf FC=gfortran LINKER=gfortran FFLAGS="-O2 -std=legacy" PROGRAM=x13as
cp x13as /usr/local/bin/x13as
cd ;
x13as
```
Alternatively, if you don't have admin privileges you can install it into `$HOME/.local/bin` and add this folder to your PATH.
### Compile Dynare from source
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.
folder where you want Dynare installed. Apple Silicon: make sure `brew`
points towards `/usr/local/bin/brew` (see above).
- Prepare the Dynare sources for the unstable version:
```sh
git clone --recurse-submodules https://git.dynare.org/Dynare/dynare.git $DYNAREDIR/unstable
cd $DYNAREDIR/unstable
mkdir -p $HOME/dynare/unstable
git clone --recurse-submodules https://git.dynare.org/Dynare/dynare.git $HOME/dynare/unstable
cd $HOME/dynare/unstable
arch -x86_64 autoreconf -si
```
If you want a certain version (e.g. 5.x) , then add `--single-branch --branch 5.x` to the git clone command.
You can also choose a specific version of Dynare by checking out the corresponding branch or a specific tag with git.
- Configure Dynare from the source directory:
```sh
export BUILDDIR=build-matlab
export MATLABPATH=/Applications/MATLAB_R2023b.app
arch -$ARCH meson setup --native-file macOS/homebrew-native-$ARCH.ini -Dmatlab_path=$MATLABPATH -Dbuildtype=debugoptimized -Dfortran_args="['-B','$DYNAREDIR/slicot/lib']" $BUILDDIR
arch -x86_64 ./configure CC=gcc-12 CXX=g++-12 CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib LEX=/usr/local/opt/flex/bin/flex YACC=/usr/local/opt/bison/bin/bison --with-matlab=/Applications/MATLAB_R2021b.app
```
where you need to adapt the path to MATLAB.
Similarly, if you want to compile for Octave, replace the `-Dmatlab_path` option by `-Dbuild_for=octave`, and change the build directory to `build-octave`.
where you need to adapt the path to MATLAB. If you dont have MATLAB, simply replace `--with-matlab=<…>` by `--disable-matlab`. Check the output of the command whether Dynare is configured for building everything except the internal docs of Dynare and M2HTML.
- Compile:
```sh
arch -$ARCH meson compile -C $BUILDDIR
arch -x86_64 make -j$(sysctl -n hw.physicalcpu)
```
If no errors occured, you are done. Dynare is now ready to use.
- If you additionally want to compile the documentation run:
```sh
arch -$ARCH meson compile -C $BUILDDIR doc
```
- Optionally, run the testsuite:
```sh
arch -$ARCH meson test -C $BUILDDIR --num-processes=$(sysctl -n hw.perflevel0.physicalcpu)
```
where `--num-processes` specifies the number of parallel processes to use for the testsuite (here set to the number of performance cores on your mac).
### Optional: pass the full PATH to MATLAB to run system commands
If you start MATLAB from a terminal, you will get the PATH inherited from the shell.
However, when you click on the application icon in macOS, you are not running at the terminal level:
the program is run by launcher, which does not go through a shell login session.
In other words, you get the system default PATH which includes `/usr/bin:/bin:/usr/sbin:/sbin`, but not `/usr/local/bin` or `$HOME/.local/bin`.
So if you want to use system commands like `pdflatex`, `latexmk` or `x13as` you should either call them by their full path (e.g `/Library/TeX/texbin/pdflatex`)
or append the PATH by running `setenv('PATH', [getenv('PATH') ':/usr/local/bin:$HOME/.local/bin:/Library/TeX/texbin']);` in your MATLAB command line once,
e.g. by adding this to your mod file. Alternatively, you can create a `startup.m` file or change the system default PATH in the `/etc/paths` file.
If you start MATLAB from a terminal, you will get the PATH inherited from the shell. However, when you click on the icon in macOS, you are not running at the terminal: the program is run by launcher, which does not go through a shell login session. You get the system default PATH which includes `/usr/bin:/bin:/usr/sbin:/sbin`, but not `/usr/local/bin` or `$HOME/.local/bin`. So if you want to use system commands like `pdflatex` or `x13as` you should either call them by their full path (e.g `/Library/TeX/texbin/pdflatex`) or append the PATH in MATLAB by running `setenv('PATH', [getenv('PATH') ':/usr/local/bin:$HOME/.local/bin:/Library/TeX/texbin']);`. Alternatively, you can create a `startup.m` file or change the system default PATH in the `/etc/paths` file.
## Docker
We offer a variety of pre-configured Docker containers for Dynare, pre-configured with Octave and MATLAB including all recommended toolboxes.
These are readily available for your convenience on [Docker Hub](https://hub.docker.com/r/dynare/dynare).
The `scripts/docker` folder contains [information and instructions](scripts/docker/README.md) to interact, built and customize the containers.
Tested on
- macOS Monterey 12.1 (Apple M1 Virtual Machine)
- macOS Monterey 12.1 (MacBook Air Intel)
- macOS Monterey 12.1 (MacBook Air M1)

1
VERSION.in Normal file
View File

@ -0,0 +1 @@
@PACKAGE_VERSION@

151
configure.ac Normal file
View File

@ -0,0 +1,151 @@
dnl Process this file with autoconf to produce a configure script.
dnl Copyright © 2009-2023 Dynare Team
dnl
dnl This file is part of Dynare.
dnl
dnl Dynare is free software: you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation, either version 3 of the License, or
dnl (at your option) any later version.
dnl
dnl Dynare is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with Dynare. If not, see <https://www.gnu.org/licenses/>.
AC_PREREQ([2.62])
AC_INIT([dynare], [6-unstable])
AC_CONFIG_SRCDIR([preprocessor/src/DynareMain.cc])
AM_INIT_AUTOMAKE([1.11 -Wall -Wno-portability foreign no-dist-gzip dist-xz tar-pax])
AC_CONFIG_SUBDIRS([preprocessor])
AC_PROG_CC
AC_PROG_CXX
AC_CANONICAL_HOST
case ${host_os} in
*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 -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
;;
esac
# Use C++ for testing headers
AC_LANG([C++])
AM_CXXFLAGS="-std=gnu++20 -Wall -Wno-dangling-else -Wextra -Wno-unused-parameter -Wold-style-cast"
AC_SUBST([AM_CXXFLAGS])
# If default 'ar' is not available, try to find one with a host prefix (see ticket #145)
AC_CHECK_PROGS([AR], [ar ${host_alias}-ar])
AC_PROG_RANLIB
AM_PROG_AR
AX_PROG_LN_S
AC_PROG_MKDIR_P
# Define optional components and their corresponding flags and Automake conditionals
AC_ARG_ENABLE([doc], AS_HELP_STRING([--disable-doc], [disable compilation of documentation]), [], [enable_doc=yes])
AM_CONDITIONAL([ENABLE_DOC], [test "$enable_doc" = yes])
AC_ARG_ENABLE([matlab], AS_HELP_STRING([--disable-matlab], [disable compilation of MEX files for MATLAB]), [], [enable_matlab=yes])
AM_CONDITIONAL([ENABLE_MATLAB], [test "$enable_matlab" = yes])
AC_ARG_ENABLE([octave], AS_HELP_STRING([--disable-octave], [disable compilation of MEX files for Octave]), [], [enable_octave=yes])
AM_CONDITIONAL([ENABLE_OCTAVE], [test "$enable_octave" = yes])
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 -n "$enable_org_export"])
# Check utilities needed for documentation
if test "$enable_doc" = yes; then
AC_CHECK_PROG([PDFLATEX], [pdflatex], [pdflatex], [no])
test "$PDFLATEX" = no && AC_MSG_ERROR([pdflatex cannot be found. If you want to skip the compilation of the documentation, pass the --disable-doc flag.])
AC_CHECK_PROG([BIBTEX], [bibtex], [bibtex], [no])
test "$BIBTEX" = no && AC_MSG_ERROR([bibtex cannot be found. If you want to skip the compilation of the documentation, pass the --disable-doc flag.])
AC_CHECK_PROG([SPHINXBUILD], [sphinx-build], [sphinx-build], [no])
test "$SPHINXBUILD" = no && AC_MSG_ERROR([sphinx-build cannot be found. If you want to skip the compilation of the documentation, pass the --disable-doc flag.])
AX_LATEX_CLASS([beamer], [ax_latex_have_beamer], [], [AC_MSG_ERROR([beamer cannot be found. If you want to skip the compilation of the documentation, pass the --disable-doc flag.])])
fi
# Check for MATLAB
if test "$enable_matlab" = yes; then
AC_CONFIG_SUBDIRS([mex/build/matlab])
AX_MATLAB
AX_MATLAB_BATCH_OPTIONS
test "$ax_enable_matlab" != yes && AC_MSG_ERROR([MATLAB cannot be found. If you want to compile Dynare without MATLAB support, pass the --disable-matlab flag.])
fi
# Check for Octave
if test "$enable_octave" = yes; then
AC_CONFIG_SUBDIRS([mex/build/octave])
AX_OCTAVE
test "$ax_enable_octave" != yes && AC_MSG_ERROR([Octave cannot be found. If you want to compile Dynare without Octave support, pass the --disable-octave flag.])
fi
# Construct final output message
if test "$enable_doc" = yes; then
BUILD_DOC="yes"
else
BUILD_DOC="no"
fi
if test -n "$enable_org_export"; then
BUILD_INTERNAL_DOC="yes"
else
BUILD_INTERNAL_DOC="no"
fi
if test "$enable_matlab" = yes; then
TESTSUITE_MATLAB="yes"
else
TESTSUITE_MATLAB="no"
fi
if test "$enable_octave" = yes; then
TESTSUITE_OCTAVE="yes"
else
TESTSUITE_OCTAVE="no"
fi
AC_MSG_NOTICE([
Dynare is now configured for building the following components...
Documentation (with "make html pdf"):
Manual and other documents $BUILD_DOC
Dynare internal doc: $BUILD_INTERNAL_DOC
Testsuites (run with "make check"):
Dynare for MATLAB: $TESTSUITE_MATLAB
Dynare for Octave: $TESTSUITE_OCTAVE
])
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
mex/sources/Makefile
])
AC_OUTPUT

1
contrib/jsonlab Submodule

@ -0,0 +1 @@
Subproject commit 5a58fafdca239e61be4d7b2270307b2445bb571a

@ -1 +1 @@
Subproject commit 391689d9f1bea4bd68ef6641dc2dc4a1bd867850
Subproject commit f1d0fd61ea6d9c4f8694b373780d6c372e344f6e

@ -1 +1 @@
Subproject commit ac6d0ae1b69cda26aa9486188d54c8c010f115c4
Subproject commit 216abedb9ab4df5dd4dca07c721f7c07392801e9

26
doc/Makefile.am Normal file
View File

@ -0,0 +1,26 @@
SUBDIRS = parallel internals gsa dseries-and-reporting
if ENABLE_DOC
SUBDIRS += manual
pdf-local: guide.pdf bvar-a-la-sims.pdf dr.pdf
endif
EXTRA_DIST = guide.tex guide.bbl bibmad.sty bvar-a-la-sims.tex dr.tex dr.bib dynare.plots
guide.pdf: guide.tex guide.bbl bibmad.sty
$(PDFLATEX) guide
$(PDFLATEX) guide
bvar-a-la-sims.pdf: bvar-a-la-sims.tex
$(PDFLATEX) bvar-a-la-sims
$(PDFLATEX) bvar-a-la-sims
dr.pdf: dr.tex
$(PDFLATEX) dr
$(BIBTEX) dr
$(PDFLATEX) dr
$(PDFLATEX) dr
clean-local:
# Do not delete guide.bbl which is not autogenerated
rm -f *~ *.pdf *.log *.aux *.out *.blg dr.bbl

105
doc/bibmad.sty Normal file
View File

@ -0,0 +1,105 @@
\message{harvard bibliography,}
\def\@hiteml[#1]#2#3#4{\item[]\if@filesw%
{ \def\protect##1{\string ##1\space}\immediate%
\write\@auxout{\string\harvardcite{#4}{#2}{#1}{#3}}}\fi%
\protect\hspace*{-\labelwidth}\protect\hspace*{-\labelsep}\ignorespaces}
\def\@hitem#1#2#3{\item[]\if@filesw%
{ \def\protect##1{\string ##1\space}\immediate%
\write\@auxout{\string\harvardcite{#3}{#1}{#1}{#2}}}\fi%
\protect\hspace*{-\labelwidth}\protect\hspace*{-\labelsep}\ignorespaces}
\def\harvarditem{\@ifnextchar [{\@hiteml}{\@hitem}}
\def\harvardcite#1#2#3#4{
\global\@namedef{bhf@#1}{#2}
\global\@namedef{bha@#1}{#3}
\global\@namedef{bhy@#1}{#4}\global\@namedef{b@#1}{\csname bhf@#1\endcsname}
}
\def\citeasnoun{\@ifnextchar [{\@tempswatrue\@citex}{\@tempswafalse\@citex[]}}
\def\cite{\@ifnextchar [{\@tempswatrue\@citexasnoun}
{\@tempswafalse\@citexasnoun[]}
}
\def\citeyear{\@ifnextchar [{\@tempswatrue\@citexyear}
{\@tempswafalse\@citexyear[]}
}
\def\citename{\@ifnextchar [{\@tempswatrue\@citexname}
{\@tempswafalse\@citexname[]}
}
% \def\@enamedef#1{\expandafter\edef\csname #1\endcsname}
% Previous line should be replaced by the following to prevent
% problems with the NFSS. Solution by Bernd Raichle.
\def\@enamedef#1{\expandafter\def\csname #1\expandafter\endcsname\expandafter}
\def\@citex[#1]#2{\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi
\def\@citea{}\@cite{\@for\@citeb:=#2\do
{\@citea\def\@citea{\@hisep\penalty\@m\ }\@ifundefined
{b@\@citeb}{{\bf ?}\@warning
{Citation `\@citeb' on page \thepage \space undefined}}%
{{\csname b@\@citeb\endcsname\@hysep\csname bhy@\@citeb\endcsname}%
\global\@enamedef{b@\@citeb}{\csname bha@\@citeb\endcsname}}%
}}{#1}}
\def\@citexasnoun[#1]#2{%
\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi%
\@citeasnoun{{\@ifundefined%
{b@#2}%
{[{\bf ?}\@warning{Citation `#2' on page \thepage \space undefined}}%
{{\csname b@#2\endcsname\ [\csname bhy@#2\endcsname}%
\global\@namedef{b@#2}{\csname bha@#2\endcsname}}%
}}{#1}}
\def\@citexname[#1]#2{%
\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi%
\@citename{{\@ifundefined%
{b@#2}%
{{\bf ?}\@warning{Citation `#2' on page \thepage \space undefined}}%
{{\csname bhf@#2\endcsname}}%
}}{#1}}
\def\@citexyear[#1]#2{\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi
\def\@citeayear{}\@cite{\@for\@citebyear:=#2\do
{\@citeayear\def\@citeayear{\@hisep\penalty\@m\ }\@ifundefined
{b@\@citebyear}{{\bf ?}\@warning
{Citation `\@citebyear' on page \thepage \space undefined}}%
{{\csname bhy@\@citebyear\endcsname}%
}%
}}{#1}}
\gdef\hysep@agsm{\ }\gdef\hisep@agsm{,}%
\gdef\hysep@dcu{, }\gdef\hisep@dcu{;}%
\let\@hysep\hysep@agsm \let\@hisep\hisep@agsm
\def\citationstyle#1{%
\global\@namedef{@hysep}{\csname hysep@#1\endcsname}%
\global\@namedef{@hisep}{\csname hisep@#1\endcsname}}
%DEFAULT DEFINITIONS
\def\@cite#1#2{({#1\if@tempswa , #2\fi})}
\def\@citeasnoun#1#2{{#1\if@tempswa , #2\fi]}}
\def\@citename#1#2{{#1\if@tempswa \ (#2)\fi}}
% CHANGE \end{document} - to handle double definitions
\def\enddocument{\@checkend{document}\clearpage\begingroup
\if@filesw \immediate\closeout\@mainaux
\def\global\@namedef##1##2{}\def\newlabel{\@testdef r}%
\def\bibcite{\@testdef b}%
\def\harvardcite{\@testbibh}\@tempswafalse \makeatletter\input \jobname.aux
\if@tempswa \@warning{Label(s) may have changed. Rerun to get
cross-references right}\fi\fi\endgroup\deadcycles\z@\@@end}
\def\@testbibh #1#2#3{
\def\@tempa{#2}\expandafter
\ifx \csname bhf@#1\endcsname \@tempa
\def\@tempa{#3}\expandafter
\ifx \csname bha@#1\endcsname \@tempa
\else \@tempswatrue
\fi
\else
\@tempswatrue
\fi
}
%

View File

@ -26,7 +26,7 @@
}}
\author{S\'ebastien Villemot\thanks{Paris School of Economics and
CEPREMAP.} \and Johannes Pfeifer\thanks{University of the Bundeswehr Munich. E-mail: \href{mailto:johannes.pfeifer@unibw.de}{\texttt{johannes.pfeifer@unibw.de}}.}}
CEPREMAP.} \and Johannes Pfeifer\thanks{Universität der Bundeswehr München. E-mail: \href{mailto:johannes.pfeifer@unibw.de}{\texttt{johannes.pfeifer@unibw.de}}.}}
\date{First version: September 2007 \hspace{1cm} This version: May 2017}
\maketitle

View File

@ -650,7 +650,7 @@ equation is:
In the general case, this equation is a specialized Sylvester equation, which
can be solved using the algorithm proposed by
\citet{kamenik:2004}\footnote{This paper is distributed with Dynare, in the
\texttt{sylvester.pdf} file under the documentation directory.}.
\texttt{sylvester.pdf} file under the Dynare++ documentation directory.}.
\bibliographystyle{elsarticle-harv}
\bibliography{dr}

View File

@ -0,0 +1,14 @@
if ENABLE_DOC
pdf-local: dseriesReporting.pdf
endif
SRC = dseriesReporting.tex
EXTRA_DIST = $(SRC)
dseriesReporting.pdf: $(SRC)
$(PDFLATEX) dseriesReporting
$(PDFLATEX) dseriesReporting
clean-local:
rm -f dseriesReporting.pdf *.toc *.aux *.log *.nav *.snm *.vrb *.out *~

16
doc/gsa/Makefile.am Normal file
View File

@ -0,0 +1,16 @@
if ENABLE_DOC
pdf-local: gsa.pdf
endif
SRC = gsa.tex marco.bib
EXTRA_DIST = $(SRC)
gsa.pdf: $(SRC)
$(PDFLATEX) gsa
$(BIBTEX) gsa
$(PDFLATEX) gsa
$(PDFLATEX) gsa
clean-local:
rm -f *.pdf *.log *.aux *.toc *.lof *.blg *.bbl *.out *~

View File

@ -22,7 +22,7 @@
\begin{document}
% ----------------------------------------------------------------
\title{Sensitivity Analysis Toolbox for Dynare\thanks{Copyright \copyright~2012-2024 Dynare
\title{Sensitivity Analysis Toolbox for DYNARE\thanks{Copyright \copyright~2012 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
@ -32,9 +32,9 @@
\author{Marco Ratto\\
European Commission, Joint Research Centre \\
TP581\\21027 Ispra
TP361, IPSC, \\21027 Ispra
(VA) Italy\\
\texttt{Marco.Ratto@ec.europa.eu}
\texttt{marco.ratto@jrc.ec.europa.eu}
\thanks{The author gratefully thanks Christophe Planas, Kenneth Judd, Michel Juillard,
Alessandro Rossi, Frank Schorfheide and the participants to the
Courses on Global Sensitivity Analysis for Macroeconomic
@ -52,21 +52,21 @@ helpful suggestions.}}
%-----------------------------------------------------------------------
\begin{abstract}
\noindent The Sensitivity Analysis Toolbox for Dynare is a set of
\noindent The Sensitivity Analysis Toolbox for DYNARE is a set of
MATLAB routines for the analysis of DSGE models with global
sensitivity analysis. The routines are thought to be used within
the Dynare 6 environment.
the DYNARE v4 environment.
\begin{description}
\item \textbf{Keywords}: Stability Mapping , Reduced form solution, DSGE models,
Monte Carlo filtering, Global Sensitivity Analysis.
Monte Carlo filtering, Global Sensitivity Analysis.
\end{description}
\end{abstract}
\newpage
% ----------------------------------------------------------------
\section{Introduction} \label{s:intro}
The Sensitivity Analysis Toolbox for Dynare is a collection of
The Sensitivity Analysis Toolbox for DYNARE is a collection of
MATLAB routines implemented to answer the following questions: (i)
Which is the domain of structural coefficients assuring the
stability and determinacy of a DSGE model? (ii) Which parameters
@ -81,18 +81,20 @@ described in \cite{Ratto_CompEcon_2008}.
\section{Use of the Toolbox}
The Dynare parser now recognizes sensitivity analysis commands.
The DYNARE parser now recognizes sensitivity analysis commands.
The syntax is based on a single command:
\vspace{0.5cm}
\verb"sensitivity(option1=<opt1_val>,option2=<opt2_val>,...)"
\verb"dynare_sensitivity(option1=<opt1_val>,option2=<opt2_val>,...)"
\vspace{0.5cm} \noindent with a list of options described in the
next section.
In order to work properly, the sensitivity analysis Toolbox does not need
a Dynare estimation environment to be set up. Rather, \verb"sensitivity"
is the only command to run to
With respect to the previous version of the toolbox, in order to
work properly, the sensitivity analysis Toolbox \emph{no longer}
needs that the DYNARE estimation environment is set-up.
Therefore, \verb"dynare_sensitivity" is the only command to run to
make a sensitivity analysis on a DSGE model\footnote{Of course,
when the user needs to perform the mapping of the fit with a
posterior sample, a Bayesian estimation has to be performed
@ -206,17 +208,16 @@ a multivariate normal MC sample, with covariance matrix based on
the inverse Hessian at the optimum: this analysis is useful when
ML estimation is done (i.e. no Bayesian estimation);
\item when \verb"ppost=1" the Toolbox analyses
the RMSE's for the posterior sample obtained by Dynare's
the RMSE's for the posterior sample obtained by DYNARE's
Metropolis procedure.
\end{enumerate}
The use of cases 2. and 3. require an estimation step beforehand!
The use of cases 2. and 3. requires an estimation step beforehand!
To facilitate the sensitivity analysis after estimation, the
\verb"sensitivity" command also allows to indicate some
options of \verb"estimation". These are:
\verb"dynare_sensitivity" command also allows to indicate some
options of \verb"dynare_estimation". These are:
\begin{itemize}
\item \verb"datafile"
\item \verb"diffuse_filter"
\item \verb"mode_file"
\item \verb"first_obs"
\item \verb"lik_init"
@ -277,10 +278,10 @@ identifiable.
\end{tabular}
\vspace{1cm}
\noindent For example, the following commands in the Dynare model file
\noindent For example, the following commands in the DYNARE model file
\vspace{1cm}
\noindent\verb"sensitivity(identification=1, morris=2);"
\noindent\verb"dynare_sensitivity(identification=1, morris=2);"
\vspace{1cm}
\noindent trigger the identification analysis using \cite{Iskrev2010,Iskrev2011}, jointly with the mapping of the acceptable region.
@ -292,75 +293,75 @@ Sensitivity analysis results are saved on the hard-disk of the
computer. The Toolbox uses a dedicated folder called \verb"GSA",
located in \\
\\
\verb"<Dynare_file>\GSA", \\
\verb"<DYNARE_file>\GSA", \\
\\
where \verb"<Dynare_file>.mod" is the name of the Dynare model
where \verb"<DYNARE_file>.mod" is the name of the DYNARE model
file.
\subsection{Binary data files}
A set of binary data files is saved in the \verb"GSA" folder:
\begin{description}
\item[]\verb"<Dynare_file>_prior.mat": this file stores
\item[]\verb"<DYNARE_file>_prior.mat": this file stores
information about the analyses performed sampling from the prior
ranges, i.e. \verb"pprior=1" and \verb"ppost=0";
\item[]\verb"<Dynare_file>_mc.mat": this file stores
\item[]\verb"<DYNARE_file>_mc.mat": this file stores
information about the analyses performed sampling from
multivariate normal, i.e. \verb"pprior=0" and \verb"ppost=0";
\item[]\verb"<Dynare_file>_post.mat": this file stores information
\item[]\verb"<DYNARE_file>_post.mat": this file stores information
about analyses performed using the Metropolis posterior sample,
i.e. \verb"ppost=1".
\end{description}
\begin{description}
\item[]\verb"<Dynare_file>_prior_*.mat": these files store
\item[]\verb"<DYNARE_file>_prior_*.mat": these files store
the filtered and smoothed variables for the prior MC sample,
generated when doing RMSE analysis (\verb"pprior=1" and
\verb"ppost=0");
\item[]\verb"<Dynare_file>_mc_*.mat": these files store
\item[]\verb"<DYNARE_file>_mc_*.mat": these files store
the filtered and smoothed variables for the multivariate normal MC
sample, generated when doing RMSE analysis (\verb"pprior=0" and
\verb"ppost=0").
\end{description}
\subsection{Stability analysis}
Figure files \verb"<Dynare_file>_prior_*.fig" store results for
Figure files \verb"<DYNARE_file>_prior_*.fig" store results for
the stability mapping from prior MC samples:
\begin{description}
\item[]\verb"<Dynare_file>_prior_stab_SA_*.fig": plots of the Smirnov
test analyses confronting the CDF of the sample fulfilling
Blanchard-Kahn conditions with the CDF of the rest of the sample;
\item[]\verb"<Dynare_file>_prior_stab_indet_SA_*.fig": plots of the Smirnov
test analyses confronting the CDF of the sample producing
indeterminacy with the CDF of the original prior sample;
\item[]\verb"<Dynare_file>_prior_stab_unst_SA_*.fig": plots of the Smirnov
test analyses confronting the CDF of the sample producing unstable
(explosive roots) behaviour with the CDF of the original prior
\item[]\verb"<DYNARE_file>_prior_stab_SA_*.fig": plots of the Smirnov
test analyses confronting the cdf of the sample fulfilling
Blanchard-Kahn conditions with the cdf of the rest of the sample;
\item[]\verb"<DYNARE_file>_prior_stab_indet_SA_*.fig": plots of the Smirnov
test analyses confronting the cdf of the sample producing
indeterminacy with the cdf of the original prior sample;
\item[]\verb"<DYNARE_file>_prior_stab_unst_SA_*.fig": plots of the Smirnov
test analyses confronting the cdf of the sample producing unstable
(explosive roots) behaviour with the cdf of the original prior
sample;
\item[]\verb"<Dynare_file>_prior_stable_corr_*.fig": plots of
\item[]\verb"<DYNARE_file>_prior_stable_corr_*.fig": plots of
bivariate projections of the sample fulfilling Blanchard-Kahn
conditions;
\item[]\verb"<Dynare_file>_prior_indeterm_corr_*.fig": plots of
\item[]\verb"<DYNARE_file>_prior_indeterm_corr_*.fig": plots of
bivariate projections of the sample producing indeterminacy;
\item[]\verb"<Dynare_file>_prior_unstable_corr_*.fig": plots of
\item[]\verb"<DYNARE_file>_prior_unstable_corr_*.fig": plots of
bivariate projections of the sample producing instability;
\item[]\verb"<Dynare_file>_prior_unacceptable_corr_*.fig": plots of
\item[]\verb"<DYNARE_file>_prior_unacceptable_corr_*.fig": plots of
bivariate projections of the sample producing unacceptable
solutions, i.e. either instability or indeterminacy or the
solution could not be found (e.g. the steady state solution could
not be found by the solver).
\end{description}
Similar conventions apply for \verb"<Dynare_file>_mc_*.fig" files,
Similar conventions apply for \verb"<DYNARE_file>_mc_*.fig" files,
obtained when samples from multivariate normal are used.
\subsection{RMSE analysis}
Figure files \verb"<Dynare_file>_rmse_*.fig" store results for the
Figure files \verb"<DYNARE_file>_rmse_*.fig" store results for the
RMSE analysis.
\begin{description}
\item[]\verb"<Dynare_file>_rmse_prior*.fig": save results for
\item[]\verb"<DYNARE_file>_rmse_prior*.fig": save results for
the analysis using prior MC samples;
\item[]\verb"<Dynare_file>_rmse_mc*.fig": save results for
\item[]\verb"<DYNARE_file>_rmse_mc*.fig": save results for
the analysis using multivariate normal MC samples;
\item[]\verb"<Dynare_file>_rmse_post*.fig": save results for
\item[]\verb"<DYNARE_file>_rmse_post*.fig": save results for
the analysis using Metropolis posterior samples.
\end{description}
@ -368,33 +369,33 @@ The following types of figures are saved (we show prior sample to
fix ideas, but the same conventions are used for multivariate
normal and posterior):
\begin{description}
\item[]\verb"<Dynare_file>_rmse_prior_*.fig": for each parameter, plots the CDF's
\item[]\verb"<DYNARE_file>_rmse_prior_*.fig": for each parameter, plots the cdf's
corresponding to the best 10\% RMES's of each observed series;
\item[]\verb"<Dynare_file>_rmse_prior_dens_*.fig": for each parameter, plots the pdf's
\item[]\verb"<DYNARE_file>_rmse_prior_dens_*.fig": for each parameter, plots the pdf's
corresponding to the best 10\% RMES's of each observed series;
\item[]\verb"<Dynare_file>_rmse_prior_<name of observedseries>_corr_*.fig": for each observed series plots the
\item[]\verb"<DYNARE_file>_rmse_prior_<name of observedseries>_corr_*.fig": for each observed series plots the
bi-dimensional projections of samples with the best 10\% RMSE's,
when the correlation is significant;
\item[]\verb"<Dynare_file>_rmse_prior_lnlik*.fig": for each observed
series, plots \emph{in red} the CDF of the log-likelihood
corresponding to the best 10\% RMSE's, \emph{in green} the CDF of
the rest of the sample and \emph{in blue }the CDF of the full
\item[]\verb"<DYNARE_file>_rmse_prior_lnlik*.fig": for each observed
series, plots \emph{in red} the cdf of the log-likelihood
corresponding to the best 10\% RMSE's, \emph{in green} the cdf of
the rest of the sample and \emph{in blue }the cdf of the full
sample; this allows to see the presence of some idiosyncratic
behaviour;
\item[]\verb"<Dynare_file>_rmse_prior_lnpost*.fig": for each observed
series, plots \emph{in red} the CDF of the log-posterior
corresponding to the best 10\% RMSE's, \emph{in green} the CDF of
the rest of the sample and \emph{in blue }the CDF of the full
\item[]\verb"<DYNARE_file>_rmse_prior_lnpost*.fig": for each observed
series, plots \emph{in red} the cdf of the log-posterior
corresponding to the best 10\% RMSE's, \emph{in green} the cdf of
the rest of the sample and \emph{in blue }the cdf of the full
sample; this allows to see idiosyncratic behaviour;
\item[]\verb"<Dynare_file>_rmse_prior_lnprior*.fig": for each observed
series, plots \emph{in red} the CDF of the log-prior corresponding
to the best 10\% RMSE's, \emph{in green} the CDF of the rest of
the sample and \emph{in blue }the CDF of the full sample; this
\item[]\verb"<DYNARE_file>_rmse_prior_lnprior*.fig": for each observed
series, plots \emph{in red} the cdf of the log-prior corresponding
to the best 10\% RMSE's, \emph{in green} the cdf of the rest of
the sample and \emph{in blue }the cdf of the full sample; this
allows to see idiosyncratic behaviour;
\item[]\verb"<Dynare_file>_rmse_prior_lik_SA_*.fig": when
\item[]\verb"<DYNARE_file>_rmse_prior_lik_SA_*.fig": when
\verb"lik_only=1", this shows the Smirnov tests for the filtering
of the best 10\% log-likelihood values;
\item[]\verb"<Dynare_file>_rmse_prior_post_SA_*.fig": when
\item[]\verb"<DYNARE_file>_rmse_prior_post_SA_*.fig": when
\verb"lik_only=1", this shows the Smirnov test for the filtering
of the best 10\% log-posterior values.
\end{description}
@ -404,19 +405,19 @@ In the case of the mapping of the reduced form solution, synthetic
figures are saved in the \verb"\GSA" folder:
\begin{description}
\item[]\verb"<Dynare_file>_redform_<endo name>_vs_lags_*.fig":
\item[]\verb"<DYNARE_file>_redform_<endo name>_vs_lags_*.fig":
shows bar charts of the sensitivity indices for the \emph{ten most
important} parameters driving the reduced form coefficients of the
selected endogenous variables (\verb"namendo") versus lagged
endogenous variables (\verb"namlagendo"); suffix \verb"log"
indicates the results for log-transformed entries;
\item[]\verb"<Dynare_file>_redform_<endo name>_vs_shocks_*.fig":
\item[]\verb"<DYNARE_file>_redform_<endo name>_vs_shocks_*.fig":
shows bar charts of the sensitivity indices for the \emph{ten most
important} parameters driving the reduced form coefficients of the
selected endogenous variables (\verb"namendo") versus exogenous
variables (\verb"namexo"); suffix \verb"log" indicates the results
for log-transformed entries;
\item[]\verb"<Dynare_file>_redform_GSA(_log).fig": shows bar chart of
\item[]\verb"<DYNARE_file>_redform_GSA(_log).fig": shows bar chart of
all sensitivity indices for each parameter: this allows to notice
parameters that have a minor effect for \emph{any} of the reduced
form coefficients,
@ -448,24 +449,24 @@ without the need of any user's intervention.
\subsection{Screening analysis}
The results of the screening analysis with Morris sampling design
are stored in the subfolder \verb"\GSA\SCREEN". The data file
\verb"<Dynare_file>_prior" stores all the information of the
\verb"<DYNARE_file>_prior" stores all the information of the
analysis (Morris sample, reduced form coefficients, etc.).
Screening analysis merely concerns reduced form coefficients.
Similar synthetic bar charts as for the reduced form analysis with
MC samples are saved:
\begin{description}
\item[]\verb"<Dynare_file>_redform_<endo name>_vs_lags_*.fig":
\item[]\verb"<DYNARE_file>_redform_<endo name>_vs_lags_*.fig":
shows bar charts of the elementary effect tests for the \emph{ten
most important} parameters driving the reduced form coefficients
of the selected endogenous variables (\verb"namendo") versus
lagged endogenous variables (\verb"namlagendo");
\item[]\verb"<Dynare_file>_redform_<endo name>_vs_shocks_*.fig":
\item[]\verb"<DYNARE_file>_redform_<endo name>_vs_shocks_*.fig":
shows bar charts of the elementary effect tests for the \emph{ten
most important} parameters driving the reduced form coefficients
of the selected endogenous variables (\verb"namendo") versus
exogenous variables (\verb"namexo");
\item[]\verb"<Dynare_file>_redform_screen.fig": shows bar chart of
\item[]\verb"<DYNARE_file>_redform_screen.fig": shows bar chart of
all elementary effect tests for each parameter: this allows to
identify parameters that have a minor effect for \emph{any} of the
reduced form coefficients.

16
doc/guide.bbl Normal file
View File

@ -0,0 +1,16 @@
\ifx\undefined\bysame
\newcommand{\bysame}{\leavevmode\hbox to\leftmargin{\hrulefill\,\,}}
\fi
\begin{thebibliography}{xx}
\harvarditem[Collard and Juillard]{Collard and Juillard}{2001}{COLL/JUIL/01a}
{ Collard, F. and M.~Juillard}, Accuracy of stochastic perturbation methods:
The case of asset pricing models, {\it Journal of Economic Dynamics and
Control}, 2001, {\it 25}, 979--999.
\harvarditem[Schmitt-Grohe and Uribe]{Schmitt-Grohe and Uribe}{2002}{SGU/02}
{ Schmitt-Grohe, S. and M.~Uribe}, {\it Solving Dynamic General Equilibrium
Models Using a Second-Order Approximation to the Policy Function}, technical
working paper, Rutgers Univsersity 2002.
\end{thebibliography}

View File

@ -0,0 +1,9 @@
EXTRA_DIST = dynare-internals.org
if ENABLE_ORG_EXPORT
html-local:
emacs --batch --visit=dynare-internals.org --funcall org-html-export-to-html
endif
clean-local:
rm -rf *.html ltxpng

View File

@ -2,6 +2,7 @@ function build_internal_documentation()
% The name of the function should be explicit...
datafiles = [];
datafiles = [ datafiles ; {'../../matlab/utilities/dataset'}, {'initialize_dataset'}];
datafiles = [ datafiles ; {'../../matlab/utilities/dataset'}, {'descriptive_statistics'}];
datafiles = [ datafiles ; {'../../matlab/utilities/dataset'}, {'compute_stdv'}];
datafiles = [ datafiles ; {'../../matlab/utilities/dataset'}, {'compute_cova'}];
@ -80,4 +81,4 @@ if rows(miscfiles)
fprintf(fid,'\n\n\n');
end
end
fclose(fid);
fclose(fid);

19
doc/manual/Makefile.am Normal file
View File

@ -0,0 +1,19 @@
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
rm -rf utils/__pycache__

View File

@ -1,53 +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="87.89pt" height="34.182pt" viewBox="0 0 87.89 34.182" version="1.1">
<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.34375 -12.953125 4.453125 -13.03125 C 4.5625 -13.109375 4.703125 -13.203125 4.875 -13.28125 C 5.03125 -13.375 5.234375 -13.453125 5.46875 -13.53125 C 5.703125 -13.609375 5.984375 -13.640625 6.3125 -13.640625 C 6.796875 -13.640625 7.171875 -13.515625 7.484375 -13.265625 C 7.78125 -13.015625 7.9375 -12.6875 7.9375 -12.265625 C 7.9375 -11.9375 7.875 -11.640625 7.734375 -11.40625 C 7.59375 -11.171875 7.4375 -10.953125 7.234375 -10.765625 C 7.03125 -10.578125 6.828125 -10.390625 6.59375 -10.234375 C 6.375 -10.078125 6.171875 -9.90625 5.96875 -9.71875 C 5.796875 -9.546875 5.65625 -9.34375 5.53125 -9.140625 C 5.421875 -8.921875 5.390625 -8.6875 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.421875 -8.609375 7.5625 -8.765625 C 7.703125 -8.921875 7.875 -9.0625 8.078125 -9.234375 C 8.28125 -9.390625 8.484375 -9.546875 8.703125 -9.734375 C 8.9375 -9.90625 9.140625 -10.125 9.3125 -10.359375 C 9.515625 -10.609375 9.671875 -10.890625 9.78125 -11.21875 C 9.90625 -11.5625 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.359375 9.015625 -14.625 C 8.703125 -14.875 8.34375 -15.09375 7.9375 -15.234375 C 7.5 -15.375 7.03125 -15.453125 6.5 -15.453125 C 6.125 -15.453125 5.78125 -15.40625 5.453125 -15.34375 C 5.125 -15.28125 4.8125 -15.171875 4.53125 -15.0625 C 4.25 -14.9375 3.984375 -14.8125 3.765625 -14.640625 C 3.515625 -14.484375 3.3125 -14.328125 3.09375 -14.140625 Z M 4.90625 -3.625 C 4.90625 -3.234375 5.03125 -2.90625 5.296875 -2.65625 C 5.546875 -2.375 5.875 -2.25 6.265625 -2.25 C 6.453125 -2.25 6.625 -2.296875 6.796875 -2.359375 C 6.953125 -2.421875 7.09375 -2.53125 7.21875 -2.65625 C 7.328125 -2.78125 7.4375 -2.921875 7.515625 -3.078125 C 7.578125 -3.25 7.609375 -3.4375 7.609375 -3.625 C 7.609375 -3.796875 7.578125 -3.984375 7.515625 -4.15625 C 7.4375 -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.625 -4.953125 6.453125 -5 6.265625 -5 C 5.875 -5 5.546875 -4.859375 5.296875 -4.59375 C 5.03125 -4.34375 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 "/>
<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.546875 -8.875 C 17.546875 -10.203125 17.328125 -11.40625 16.90625 -12.5 C 16.484375 -13.59375 15.890625 -14.515625 15.125 -15.3125 C 14.359375 -16.078125 13.4375 -16.6875 12.359375 -17.125 C 11.28125 -17.546875 10.09375 -17.75 8.796875 -17.75 L 2.15625 -17.75 L 2.15625 0 L 8.796875 0 C 10.09375 0 11.28125 -0.203125 12.359375 -0.640625 C 13.4375 -1.0625 14.359375 -1.65625 15.125 -2.4375 C 15.890625 -3.21875 16.484375 -4.15625 16.90625 -5.234375 C 17.328125 -6.328125 17.546875 -7.546875 17.546875 -8.875 Z M 15.078125 -8.875 C 15.078125 -7.78125 14.9375 -6.796875 14.640625 -5.953125 C 14.34375 -5.09375 13.921875 -4.359375 13.375 -3.765625 C 12.828125 -3.1875 12.171875 -2.71875 11.390625 -2.421875 C 10.609375 -2.109375 9.75 -1.953125 8.796875 -1.953125 L 4.578125 -1.953125 L 4.578125 -15.8125 L 8.796875 -15.8125 C 9.75 -15.8125 10.609375 -15.65625 11.390625 -15.34375 C 12.171875 -15.03125 12.828125 -14.578125 13.375 -13.984375 C 13.921875 -13.375 14.34375 -12.65625 14.640625 -11.796875 C 14.9375 -10.9375 15.078125 -9.96875 15.078125 -8.875 Z M 15.078125 -8.875 "/>
<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 5.484375 3.703125 L 12.484375 -12.546875 L 10.734375 -12.546875 C 10.59375 -12.546875 10.453125 -12.515625 10.328125 -12.421875 C 10.21875 -12.34375 10.140625 -12.234375 10.09375 -12.09375 L 6.828125 -4.203125 C 6.75 -4.015625 6.6875 -3.828125 6.625 -3.640625 C 6.5625 -3.453125 6.515625 -3.265625 6.453125 -3.078125 C 6.421875 -3.265625 6.375 -3.453125 6.3125 -3.640625 C 6.25 -3.828125 6.1875 -4 6.125 -4.1875 L 2.765625 -12.09375 C 2.71875 -12.203125 2.640625 -12.3125 2.53125 -12.421875 C 2.421875 -12.5 2.265625 -12.546875 2.078125 -12.546875 L 0.171875 -12.546875 L 5.359375 -0.734375 L 3.0625 4.25 L 4.703125 4.25 C 4.9375 4.25 5.109375 4.203125 5.203125 4.09375 C 5.328125 4 5.421875 3.859375 5.484375 3.703125 Z M 5.484375 3.703125 "/>
<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 1.8125 0 L 4.015625 0 L 4.015625 -9.25 C 4.5 -9.78125 5.015625 -10.203125 5.578125 -10.515625 C 6.140625 -10.828125 6.75 -10.984375 7.40625 -10.984375 C 8.296875 -10.984375 8.96875 -10.734375 9.390625 -10.203125 C 9.84375 -9.671875 10.046875 -8.953125 10.046875 -7.984375 L 10.046875 0 L 12.25 0 L 12.25 -7.984375 C 12.25 -8.703125 12.171875 -9.359375 11.984375 -9.9375 C 11.796875 -10.515625 11.53125 -11.03125 11.171875 -11.453125 C 10.828125 -11.859375 10.390625 -12.1875 9.859375 -12.421875 C 9.34375 -12.640625 8.734375 -12.75 8.046875 -12.75 C 7.171875 -12.75 6.390625 -12.5625 5.71875 -12.1875 C 5.046875 -11.828125 4.4375 -11.34375 3.890625 -10.734375 L 3.71875 -12.09375 C 3.625 -12.40625 3.4375 -12.546875 3.125 -12.546875 L 1.8125 -12.546875 Z M 1.8125 0 "/>
<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 11.03125 0 L 11.03125 -8.03125 C 11.03125 -8.734375 10.921875 -9.375 10.75 -9.96875 C 10.5625 -10.546875 10.265625 -11.046875 9.90625 -11.46875 C 9.53125 -11.875 9.0625 -12.1875 8.53125 -12.421875 C 7.984375 -12.65625 7.359375 -12.78125 6.65625 -12.78125 C 5.671875 -12.78125 4.796875 -12.609375 3.984375 -12.28125 C 3.1875 -11.9375 2.4375 -11.453125 1.75 -10.78125 L 2.140625 -10.078125 C 2.203125 -9.96875 2.296875 -9.859375 2.40625 -9.78125 C 2.53125 -9.703125 2.65625 -9.671875 2.796875 -9.671875 C 2.984375 -9.671875 3.1875 -9.734375 3.375 -9.859375 C 3.5625 -10.015625 3.796875 -10.15625 4.0625 -10.328125 C 4.34375 -10.5 4.65625 -10.65625 5.03125 -10.78125 C 5.390625 -10.921875 5.84375 -10.984375 6.375 -10.984375 C 7.203125 -10.984375 7.8125 -10.75 8.234375 -10.234375 C 8.65625 -9.734375 8.859375 -9.015625 8.859375 -8.03125 L 8.859375 -7.046875 C 7.4375 -7.015625 6.234375 -6.890625 5.25 -6.671875 C 4.28125 -6.4375 3.46875 -6.140625 2.875 -5.78125 C 2.25 -5.421875 1.828125 -5.03125 1.546875 -4.5625 C 1.28125 -4.109375 1.140625 -3.625 1.140625 -3.140625 C 1.140625 -2.5625 1.234375 -2.0625 1.40625 -1.65625 C 1.609375 -1.234375 1.859375 -0.890625 2.171875 -0.625 C 2.484375 -0.34375 2.84375 -0.15625 3.265625 0 C 3.703125 0.125 4.15625 0.203125 4.640625 0.203125 C 5.125 0.203125 5.5625 0.15625 5.953125 0.078125 C 6.34375 -0.015625 6.71875 -0.125 7.0625 -0.296875 C 7.40625 -0.453125 7.75 -0.640625 8.046875 -0.890625 C 8.359375 -1.109375 8.6875 -1.390625 9.015625 -1.6875 L 9.265625 -0.515625 C 9.3125 -0.3125 9.390625 -0.15625 9.53125 -0.09375 C 9.671875 -0.03125 9.84375 0 10.046875 0 Z M 5.296875 -1.34375 C 5.015625 -1.34375 4.75 -1.390625 4.5 -1.46875 C 4.25 -1.53125 4.046875 -1.640625 3.859375 -1.78125 C 3.671875 -1.953125 3.53125 -2.140625 3.421875 -2.375 C 3.3125 -2.609375 3.265625 -2.90625 3.265625 -3.234375 C 3.265625 -3.578125 3.359375 -3.890625 3.5625 -4.171875 C 3.765625 -4.453125 4.09375 -4.703125 4.53125 -4.90625 C 4.984375 -5.125 5.5625 -5.28125 6.265625 -5.40625 C 6.96875 -5.53125 7.84375 -5.609375 8.859375 -5.65625 L 8.859375 -3.03125 C 8.609375 -2.78125 8.34375 -2.546875 8.109375 -2.328125 C 7.828125 -2.125 7.5625 -1.953125 7.28125 -1.8125 C 6.984375 -1.65625 6.6875 -1.546875 6.375 -1.46875 C 6.046875 -1.390625 5.6875 -1.34375 5.296875 -1.34375 Z M 5.296875 -1.34375 "/>
<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 1.8125 0 L 4.015625 0 L 4.015625 -7.984375 C 4.359375 -8.84375 4.796875 -9.484375 5.296875 -9.9375 C 5.828125 -10.390625 6.46875 -10.609375 7.234375 -10.609375 C 7.671875 -10.609375 8 -10.5625 8.234375 -10.484375 C 8.46875 -10.40625 8.65625 -10.375 8.765625 -10.375 C 8.96875 -10.375 9.09375 -10.46875 9.15625 -10.6875 L 9.4375 -12.328125 C 9.203125 -12.46875 8.953125 -12.578125 8.65625 -12.65625 C 8.375 -12.734375 8.0625 -12.78125 7.71875 -12.78125 C 6.859375 -12.78125 6.125 -12.53125 5.5 -12.046875 C 4.859375 -11.546875 4.34375 -10.859375 3.90625 -9.984375 L 3.75 -11.9375 C 3.71875 -12.171875 3.65625 -12.328125 3.5625 -12.421875 C 3.484375 -12.5 3.3125 -12.546875 3.078125 -12.546875 L 1.8125 -12.546875 Z M 1.8125 0 "/>
<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 6.78125 -12.75 C 5.875 -12.75 5.0625 -12.59375 4.328125 -12.265625 C 3.59375 -11.953125 2.984375 -11.515625 2.484375 -10.953125 C 1.96875 -10.40625 1.59375 -9.734375 1.3125 -8.984375 C 1.046875 -8.234375 0.921875 -7.40625 0.921875 -6.53125 C 0.921875 -5.453125 1.0625 -4.484375 1.359375 -3.65625 C 1.65625 -2.828125 2.078125 -2.125 2.609375 -1.5625 C 3.140625 -0.984375 3.765625 -0.5625 4.515625 -0.265625 C 5.234375 0.03125 6.03125 0.171875 6.90625 0.171875 C 7.359375 0.171875 7.8125 0.140625 8.28125 0.046875 C 8.734375 -0.03125 9.1875 -0.140625 9.609375 -0.296875 C 10.0625 -0.453125 10.453125 -0.65625 10.84375 -0.890625 C 11.21875 -1.140625 11.546875 -1.421875 11.828125 -1.765625 L 11.203125 -2.5625 C 11.109375 -2.703125 10.96875 -2.78125 10.78125 -2.78125 C 10.640625 -2.78125 10.46875 -2.71875 10.28125 -2.578125 C 10.09375 -2.453125 9.84375 -2.3125 9.546875 -2.171875 C 9.265625 -2.015625 8.921875 -1.890625 8.53125 -1.765625 C 8.109375 -1.625 7.640625 -1.5625 7.09375 -1.5625 C 6.5 -1.5625 5.953125 -1.65625 5.484375 -1.859375 C 5 -2.046875 4.578125 -2.34375 4.234375 -2.71875 C 3.890625 -3.125 3.625 -3.625 3.421875 -4.203125 C 3.21875 -4.78125 3.109375 -5.484375 3.09375 -6.265625 L 11.453125 -6.265625 C 11.65625 -6.265625 11.796875 -6.328125 11.875 -6.4375 C 11.9375 -6.546875 11.984375 -6.796875 11.984375 -7.140625 C 11.984375 -8.03125 11.84375 -8.828125 11.59375 -9.515625 C 11.328125 -10.21875 10.96875 -10.796875 10.5 -11.28125 C 10.046875 -11.765625 9.484375 -12.125 8.859375 -12.359375 C 8.234375 -12.625 7.53125 -12.75 6.78125 -12.75 Z M 6.828125 -11.125 C 7.328125 -11.125 7.78125 -11.046875 8.171875 -10.875 C 8.5625 -10.703125 8.890625 -10.453125 9.171875 -10.15625 C 9.4375 -9.84375 9.65625 -9.484375 9.78125 -9.046875 C 9.921875 -8.625 10 -8.15625 10 -7.640625 L 3.171875 -7.640625 C 3.328125 -8.734375 3.703125 -9.59375 4.3125 -10.203125 C 4.921875 -10.8125 5.765625 -11.125 6.828125 -11.125 Z M 6.828125 -11.125 "/>
<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 22 6 L 22 34.183594 L 0 34.183594 Z M 0 6 "/>
<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.321" y="24.097"/>
<use xlink:href="#glyph0-2" x="21.985686" y="24.097"/>
<use xlink:href="#glyph0-3" x="34.676682" y="24.097"/>
<use xlink:href="#glyph0-4" x="48.458309" y="24.097"/>
<use xlink:href="#glyph0-5" x="61.025369" y="24.097"/>
<use xlink:href="#glyph0-6" x="71.01457" y="24.097"/>
<use xlink:href="#glyph0-1" x="3.32" y="24.072"/>
</g>
<path style="fill:none;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,49.804688%,39.99939%);stroke-opacity:1;stroke-miterlimit:10;" d="M -13.323406 -17.010156 C -13.323406 -17.010156 0.785969 14.802344 5.387531 15.591406 C 9.989094 16.376563 16.891437 -8.35 19.844562 -11.338281 C 22.793781 -14.326562 24.797687 -6.029687 26.645344 -5.951562 C 28.493 -5.873437 31.434406 -10.455469 33.164875 -10.771875 C 34.895344 -11.088281 37.504719 -8.299219 39.118 -8.221094 C 40.731281 -8.142969 43.215656 -10.127344 44.789875 -10.205469 C 46.360187 -10.283594 48.883625 -8.865625 50.457844 -8.7875 C 52.032062 -8.709375 54.551594 -9.6 56.125812 -9.639062 C 57.700031 -9.678125 60.301594 -9.111719 61.797687 -9.072656 C 63.289875 -9.033594 66.89925 -9.353906 66.89925 -9.353906 " transform="matrix(1,0,0,-1,15.882,16.775)"/>
<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.53"/>
<use xlink:href="#glyph0-2" x="22.552686" y="23.53"/>
<use xlink:href="#glyph0-3" x="35.243681" y="23.53"/>
<use xlink:href="#glyph0-4" x="49.025309" y="23.53"/>
<use xlink:href="#glyph0-5" x="61.592369" y="23.53"/>
<use xlink:href="#glyph0-6" x="71.58157" y="23.53"/>
<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(100%,49.804688%,39.99939%);stroke-opacity:1;stroke-miterlimit:10;" d="M -9.128094 -7.935937 C -9.128094 -7.935937 -5.753094 -1.135156 -5.753094 -1.135156 " transform="matrix(1,0,0,-1,15.882,16.775)"/>
<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>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1 @@
/usr/share/javascript/mathjax/

View File

@ -13,23 +13,20 @@ Bibliography
* Andrews, Donald W.K (1991): “Heteroskedasticity and autocorrelation consistent covariance matrix estimation”, *Econometrica*, 59(3), 817858.
* Backus, David K., Patrick J. Kehoe, and Finn E. Kydland (1992): “International Real Business Cycles,” *Journal of Political Economy*, 100(4), 745775.
* 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), 575593.
* Bini, Dario A., Guy Latouche, and Beatrice Meini (2002): “Solving matrix polynomial equations arising in queueing problems,” *Linear Algebra and its Applications*, 340, 225244.
* Born, Benjamin and Johannes Pfeifer (2014): “Policy risk and the business cycle”, *Journal of Monetary Economics*, 68, 68-85.
* Boucekkine, Raouf (1995): “An alternative methodology for solving nonlinear forward-looking models,” *Journal of Economic Dynamics and Control*, 19, 711734.
* Brayton, Flint and Peter Tinsley (1996): A Guide to FRB/US: A Macroeconomic Model of the United States, *Finance and Economics Discussion Series*, 1996-42.
* Brayton, Flint, Morris Davis and Peter Tulip (2000): “Polynomial Adjustment Costs in FRB/US,” *Unpublished manuscript*.
* Brayton, Flint and Peter Tinsley (1996): "A Guide to FRB/US: A Macroeconomic Model of the United States", *Finance and Economics Discussion Series*, 1996-42.
* Brayton, Flint, Morris Davis and Peter Tulip (2000): "Polynomial Adjustment Costs in FRB/US", *Unpublished manuscript*.
* Brooks, Stephen P., and Andrew Gelman (1998): “General methods for monitoring convergence of iterative simulations,” *Journal of Computational and Graphical Statistics*, 7, pp. 434455.
* 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, 1938.
* Christiano, Lawrence J., Martin Eichenbaum and Charles L. Evans (2005): “Nominal Rigidities and the Dynamic Effects of a Shock to Monetary Policy,” *Journal of Political Economy*, 113(1), 145.
* Christiano, Lawrence J., Mathias Trabandt, and Karl Walentin (2010): “DSGE Models for Monetary Policy Analysis,” In: *Handbook of Monetary Economics 3*, 285367.
* 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), 19992041.
* 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, 979999.
* 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, 125139.
* Corana, 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), 262280.
* Cuba-Borda, Pablo, Luca Guerrieri, Matteo Iacoviello, and Molin Zhong (2019): Likelihood evaluation of models with occasionally binding constraints, Journal of Applied Econometrics, 34(7), 1073-1085
* Cuba-Borda, Pablo, Luca Guerrieri, Matteo Iacoviello, and Molin Zhong (2019): "Likelihood evaluation of models with occasionally binding constraints", Journal of Applied Econometrics, 34(7), 1073-1085
* Del Negro, Marco and Frank Schorfheide (2004): “Priors from General Equilibrium Models for VARs”, *International Economic Review*, 45(2), 643673.
* Dennis, Richard (2007): “Optimal Policy In Rational Expectations Models: New Solution Algorithms”, *Macroeconomic Dynamics*, 11(1), 3155.
* Duffie, Darrel and Kenneth J. Singleton (1993): “Simulated Moments Estimation of Markov Models of Asset Prices”, *Econometrica*, 61(4), 929-952.
@ -49,7 +46,6 @@ Bibliography
* Hansen, Lars P. (1982): “Large sample properties of generalized method of moments estimators,” Econometrica, 50(4), 10291054.
* 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, 282291.
* Harvey, Andrew C. and Garry D.A. Phillips (1979): “Maximum likelihood estimation of regression models with autoregressive-moving average disturbances,” *Biometrika*, 66(1), 4958.
* Herbst, Edward and Schorfheide, Frank (2014): “Sequential Monte Carlo Sampling for DSGE Models,” *Journal of Applied Econometrics*, 29, 1073-1098.
* Herbst, Edward (2015): “Using the “Chandrasekhar Recursions” for Likelihood Evaluation of DSGE Models,” *Computational Economics*, 45(4), 693705.
* Ireland, Peter (2004): “A Method for Taking Models to the Data,” *Journal of Economic Dynamics and Control*, 28, 120526.
* Iskrev, Nikolay (2010): “Local identification in DSGE models,” *Journal of Monetary Economics*, 57(2), 189202.
@ -86,5 +82,5 @@ Bibliography
* 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), 11231175.
* Stock, James H. and Mark W. Watson (1999). “Forecasting Inflation,”, *Journal of Monetary Economics*, 44(2), 293335.
* 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, 3061.
* U.S. Census Bureau (2020): “X-13 ARIMA-SEATS Reference Manual, Version 1.1”, Center for Statistical Research and Methodology, U.S. Census Bureau, https://www.census.gov/data/software/x13as.html
* U.S. Census Bureau (2017): “X-13 ARIMA-SEATS Reference Manual”.
* Villemot, Sébastien (2011): “Solving rational expectations models at first order: what Dynare does,” *Dynare Working Papers*, 2, CEPREMAP.

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright © 2018-2024 Dynare Team
# Copyright © 2018-2022 Dynare Team
#
# This file is part of Dynare.
#
@ -31,14 +31,20 @@ 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'19962024 Dynare Team'
copyright = u'19962022 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 = []
@ -71,11 +77,12 @@ latex_elements = {
warningBorderColor={RGB}{255,50,50},OuterLinkColor={RGB}{34,139,34}, \
InnerLinkColor={RGB}{51,51,255},TitleColor={RGB}{51,51,255}',
'papersize': 'a4paper',
'preamble': r'\DeclareUnicodeCharacter{200B}{}', # Part of the workaround for #1707
}
latex_documents = [
(master_doc, 'dynare-manual.tex', u'Dynare Reference Manual',
u'Dynare Team', 'manual'),
u'Dynare team', 'manual'),
]
man_pages = [

View File

@ -8,25 +8,11 @@
Dynare misc commands
####################
.. matcomm:: send_endogenous_variables_to_workspace ;
Puts the simulation results for the endogenous variables stored in ``oo_.endo_simul``
into vectors with the same name as the respective variables into the base workspace.
.. matcomm:: send_exogenous_variables_to_workspace ;
Puts the simulation results for the exogenous variables stored in ``oo_.exo_simul``
into vectors with the same name as the respective variables into the base workspace.
.. matcomm:: send_irfs_to_workspace ;
Puts the IRFs stored in ``oo_.irfs`` into vectors with the same name into the base workspace.
.. command:: prior_function(OPTIONS);
Executes a user-defined function on parameter draws from the prior
|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 :math:`n` cell array named
all draws in an $ndraws$ by $n$ cell array named
``oo_.prior_function_results``.
*Options*
@ -44,11 +30,9 @@ Dynare misc commands
Number of draws used for sampling. Default: 500.
|br|
.. command:: posterior_function(OPTIONS);
Same as the :comm:`prior_function` command but for the
|br| Same as the :comm:`prior_function` command but for the
posterior distribution. Results returned in
``oo_.posterior_function_results``.
@ -62,28 +46,23 @@ Dynare misc commands
See :opt:`prior_function_sampling_draws <sampling_draws = INTEGER>`.
|br|
.. command:: generate_trace_plots(CHAIN_NUMBER);
Generates trace plots of the MCMC draws for all estimated
parameters and the posterior density for the specified Markov Chain(s)
``CHAIN_NUMBER``. If ``CHAIN_NUMBER`` is a vector of integers, the trace plots
will plot contains separate lines for each chain.
|br|
|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
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.
|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*
*Flags*
``--test``
``--test``
Performs the unitary test associated to ROUTINENAME (if this
routine exists and if the matlab/octave ``.m`` file has
@ -100,7 +79,28 @@ Dynare misc commands
>> internals --test ../matlab/fr/ROUTINENAME
``--display-mh-history``
``--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
@ -112,9 +112,9 @@ Dynare misc commands
>> internals --display-mh-history MODFILENAME
``--load-mh-history``
``--load-mh-history``
Loads into the MATLAB/Octaves workspace informations
|br| Loads into the MATLAB/Octaves workspace informations
about the previously saved MCMC draws generated by a ``.mod``
file named MODFILENAME.
@ -167,160 +167,56 @@ Dynare misc commands
A ``1*Nblck`` array of doubles. Current acceptance ratios.
|br|
.. matcomm:: prior [OPTIONS[, ...]];
.. matcomm:: prior [OPTIONS[ ...]];
Prints information about the prior distribution given the provided
options. If no options are provided, the command returns the list of
available options.
Prints information about the prior distribution given the provided
options. If no options are provided, the command returns the list of
available options.
*Options*
*Options*
.. option:: table
.. option:: table
Prints a table describing the marginal prior distributions
(mean, mode, std., lower and upper bounds, HPD interval).
Prints a table describing the marginal prior distributions
(mean, mode, std., lower and upper bounds, HPD interval).
.. option:: moments
.. option:: moments
Computes and displays first and second order moments of the
endogenous variables at the prior mode (considering the
linearized version of the model).
Computes and displays first and second order moments of the
endogenous variables at the prior mode (considering the
linearized version of the model).
.. option:: moments(distribution)
.. option:: 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.
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.
.. option:: optimize
.. option:: 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).
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).
.. option:: simulate
.. option:: 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.
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.
.. option:: plot
.. option:: plot
Plots the marginal prior density.
|br|
.. matcomm:: search VARIABLENAME[ OPTION]
Searches all occurrences of a variable in a model, and prints the
equations where the variable appear in the command line window. If OPTION is
set to `withparamvalues`, the values of the parameters (if available) are
displayed instead of the name of the parameters. Requires the `json` command
line option to be set.
*Example*
Assuming that we already ran a `.mod` file and that the workspace has not
been cleaned after, we can search for all the equations containing variable `X`
::
>> search X
Y = alpha*X/(1-X)+e;
diff(X) = beta*(X(-1)-mX) + gamma1*Z + gamma2*R + u;
To replace the parameters with estimated or calibrated parameters:
::
>> search X withparamvalues
Y = 1.254634*X/(1-X)+e;
diff(X) = -0.031459*(X(-1)-mX) + 0.1*Z - 0.2*R + u;
|br|
.. matcomm:: dplot [OPTION VALUE[ ...]]
Plot expressions extracting data from different dseries objects.
*Options*
.. option:: --expression EXPRESSION
``EXPRESSION`` is a mathematical expression involving variables
available in the dseries objects, dseries methods, numbers or
parameters. All the referenced objects are supposed to be
available in the calling workspace.
.. option:: --dseries NAME
``NAME`` is the name of a dseries object from which the
variables involved in ``EXPRESSION`` will be extracted.
.. option:: --range DATE1:DATE2
This option is not mandatory and allows to plot the expressions
only over a sub-range. ``DATE1`` and ``DATE2`` must be dates as
defined in :ref:`dates in a mod file`.
.. option:: --style MATLAB_SCRIPT_NAME
Name of a Matlab script (without extension) containing Matlab
commands to customize the produced figure.
.. option:: --title MATLAB_STRING
Adds a title to the figure.
.. option:: --with-legend
Prints a legend below the produced plot.
*Remarks*
- More than one --expression argument is allowed, and they must come first.
- For each dseries object we plot all the expressions. We use two
nested loops, the outer loop is over the dseries objects and the
inner loop over the expressions. This determines the ordering of
the plotted lines.
- All dseries objects must be defined in the calling workspace, if a
dseries object is missing the routine throws a warning (we only
build the plots for the available dseries objects), if all dseries
objects are missing the routine throws an error.
- If the range is not provided, the expressions cannot involve leads or lags.
*Example*
::
>> toto = dseries(randn(100,3), dates('2000Q1'), {'x','y','z'});
>> noddy = dseries(randn(100,3), dates('2000Q1'), {'x','y','z'});
>> b = 3;
>> dplot --expression 2/b*cumsum(x/y(-1)-1) --dseries toto --dseries noddy --range 2001Q1:2024Q1 --title 'This is my plot'
will produce plots for ``2/b*cumsum(x/y(-1)-1)``, where ``x`` and
``y`` are variables in dseries objects ``toto`` and ``noddy``, in
the same figure.
Plots the marginal prior density.

View File

@ -5,13 +5,13 @@ Currently the development team of Dynare is composed of:
* Stéphane Adjemian (Le Mans Université, Gains)
* Michel Juillard (Banque de France)
* Sumudu Kankanamge (Le Mans Université and CEPREMAP)
* Sumudu Kankanamge (Toulouse School of Economics and CEPREMAP)
* Frédéric Karamé (Le Mans Université, Gains and CEPREMAP)
* Junior Maih (Norges Bank)
* Willi Mutschler (University of Tübingen)
* Johannes Pfeifer (University of the Bundeswehr Munich)
* Johannes Pfeifer (Universität der Bundeswehr München)
* Marco Ratto (European Commission, Joint Research Centre - JRC)
* Normann Rion (CEPREMAP)
* Normann Rion (CY Cergy Paris Université and CEPREMAP)
* Sébastien Villemot (CEPREMAP)
The following people used to be members of the team:
@ -26,7 +26,7 @@ The following people used to be members of the team:
* Ferhat Mihoubi
* George Perendia
Copyright © 1996-2024, Dynare Team.
Copyright © 1996-2023, 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.

View File

@ -8,14 +8,14 @@ Software requirements
=====================
Packaged versions of Dynare are available for Windows (10 and 11), several
GNU/Linux distributions (Debian, Ubuntu, Linux Mint, Arch Linux), macOS (13
Ventura), and FreeBSD. Dynare should work on other systems, but some
GNU/Linux distributions (Debian, Ubuntu, Linux Mint, Arch Linux), macOS (12
“Monterey”), and FreeBSD. 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, any version ranging from 9.5 (R2018b) to 23.2 (R2023b);
* GNU Octave, any version ranging from 7.1.0 to 8.4.0, with the ``statistics`` package
* MATLAB, any version ranging from 8.3 (R2014a) to 9.13 (R2022b);
* GNU Octave, any version ranging from 6.2.0 to 7.3.0, with the statistics package
from `Octave-Forge`_. Note however that the Dynare installer for Windows
requires a more specific version of Octave, as indicated on the download
page.
@ -26,8 +26,8 @@ extra features, but are in no way required:
* If under MATLAB: the Optimization Toolbox, the Statistics Toolbox,
the Control System Toolbox;
* If under Octave, the following `Octave-Forge`_ packages: ``optim``, ``io``,
``control``.
* If under Octave, the following `Octave-Forge`_ packages: ``optim, io,
control``.
Installation of Dynare
@ -80,12 +80,8 @@ On Arch Linux, the Dynare package is not in the official repositories, but is
available in the `Arch User Repository`_. The needed sources can be
downloaded from the `package status in Arch Linux`_.
There is also a Dynare package for openSUSE, see the `package status in
openSUSE`_.
Dynare will be installed under ``/usr/lib/dynare`` (or ``/usr/lib64/dynare`` on
openSUSE). Documentation will be under ``/usr/share/doc/dynare`` (only on
Debian, Ubuntu and Linux Mint).
Dynare will be installed under ``/usr/lib/dynare``. Documentation will
be under ``/usr/share/doc/dynare`` (only on Debian, Ubuntu and Linux Mint).
On macOS
@ -95,23 +91,29 @@ With MATLAB
^^^^^^^^^^^
To install Dynare for use with MATLAB, execute the automated installer called
``dynare-x.y-arch.pkg`` (where *x.y* is the version number and *arch* is either arm64 for Apple Silicon or x86_64 for Intel architectures),
and follow the instructions.
This installation does not require administrative privileges.
If for some reason admin rights are requested, use *Change Install Location* and select *Install for me only*.
The default installation directory is ``/Applications/Dynare/x.y-arch``.
Installing into ``/Applications/dynare`` might fail if you have older versions of Dynare already installed in ``/Applications/Dynare``.
To fix this, modify the ownership by executing the following command in Terminal.app::
``dynare-x.y.pkg`` (where *x.y* is the version number), and follow the
instructions. The default installation directory is
``/Applications/Dynare/x.y``. After installation, this directory will contain
several sub-directories, among which are ``matlab``, ``mex``, and ``doc``.
sudo chown -R "$USER":staff /Applications/Dynare
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`).
Alternatively, you can modify the installation path in the automated installed using *Customize* and *Location*.
After installation, the folder will contain several sub-directories, among which are ``matlab``, ``mex``, and ``doc``.
Several versions of Dynare can coexist (by default in ``/Applications/Dynare``),
as long as you correctly adjust your path settings (see :ref:`words-warning`).
By default, the installer installs a version of GCC (for use with :opt:`use_dll`)
in the installation directory, under the ``.brew`` folder. To do so, it also
installs a version of Homebrew_ in the same folder and
Xcode Command Line Tools (this is an Apple product) in a system folder.
It is recommended to install the Xcode Command Line Tools (this is an Apple product)
and GCC via Homebrew_ (see :ref:`prerequisites-macos`).
All of this requires a bit of time and hard disk space. The amount of time it
takes will depend on your computing power and internet connection. To reduce
the time the Dynare installer takes, you can install Xcode Command Line Tools
yourself (see :ref:`prerequisites-macos`). Dynare, Homebrew, and GCC use
about 600 MB of disk space while the Xcode Command Line Tools require about 400
MB.
If you do not use the :opt:`use_dll` option, you have the choice to forgo the
installation of GCC and hence Dynare will only take about 50 MB of disk space.
With Octave
^^^^^^^^^^^
@ -186,33 +188,15 @@ Dynare now ships a compilation environment that can be used with the
:opt:`use_dll` option. To install this environment correctly, the Dynare
installer ensures that the Xcode Command Line Tools (an Apple product) have
been installed on a system folder. To install the Xcode Command Line Tools
yourself, simply type ``xcode-select --install`` into the terminal
yourself, simply type ``xcode-select --install`` into the Terminal
(``/Applications/Utilities/Terminal.app``) prompt.
Additionally, to make MATLAB aware that you agree to the terms of Xcode, run the following two commands in the Terminal prompt::
CLT_VERSION=$(pkgutil --pkg-info=com.apple.pkg.CLTools_Executables | grep version | awk '{print $2}' | cut -d'.' -f1-2)
defaults write com.apple.dt.Xcode IDEXcodeVersionForAgreedToGMLicense "${CLT_VERSION}"
defaults read com.apple.dt.Xcode IDEXcodeVersionForAgreedToGMLicense
Otherwise you will see a warning that Xcode is installed, but its license has not been accepted.
You can check this e.g. by running the following command in the MATLAB command window::
mex -setup
Moreover, we recommend making use of optimized compilation flags when using :opt:`use_dll` and for this you need to install GCC via Homebrew_::
brew install gcc
If you already have installed GCC, Dynare will automatically prefer it for :opt:`use_dll`
if the binaries are either in ``/opt/homebrew/bin`` on Apple Silicon (arm64) or in ``/usr/local/bin`` on Intel (x86_64) systems.
Otherwise, it will fall back to Clang in ``/usr/bin/clang``, which works both on arm64 and x86_64 systems.
With Octave
^^^^^^^^^^^
The compiler can be installed via Homebrew_. In a terminal, run::
brew install gcc
brew install gcc-12
Configuration
=============
@ -319,7 +303,6 @@ Dynare unusable.
.. _Package status in Ubuntu: https://launchpad.net/ubuntu/+source/dynare
.. _Package status in Linux Mint: https://community.linuxmint.com/software/view/dynare
.. _Package status in Arch Linux: https://aur.archlinux.org/packages/dynare/
.. _Package status in openSUSE: https://software.opensuse.org/package/dynare
.. _Arch User Repository: https://wiki.archlinux.org/index.php/Arch_User_Repository
.. _Dynare website: https://www.dynare.org/
.. _Dynare wiki: https://git.dynare.org/Dynare/dynare/wikis

View File

@ -94,24 +94,26 @@ 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, Michel Juillard, Frédéric Karamé, Willi Mutschler,
Johannes Pfeifer, Marco Ratto, Normann Rion and Sébastien Villemot (2024),
“Dynare: Reference Manual, Version 6,” *Dynare Working Papers*, 80, CEPREMAP
Stéphane Adjemian, Houtan Bastani, Michel Juillard, Frédéric Karamé,
Ferhat Mihoubi, Willi Mutschler, Johannes Pfeifer, Marco Ratto,
Normann Rion and Sébastien Villemot (2022), “Dynare: Reference Manual,
Version 5,” *Dynare Working Papers*, 72, CEPREMAP
For convenience, you can copy and paste the following into your BibTeX file:
.. code-block:: bibtex
@TechReport{Adjemianetal2024,
author = {Adjemian, St\'ephane and Juillard, Michel and
Karam\'e, Fr\'ederic and Mutschler, Willi and
Pfeifer, Johannes and Ratto, Marco and
@TechReport{Adjemianetal2022,
author = {Adjemian, St\'ephane and Bastani, Houtan and
Juillard, Michel and Karam\'e, Fr\'ederic and
Mihoubi, Ferhat and Mutschler, Willi
and Pfeifer, Johannes and Ratto, Marco and
Rion, Normann and Villemot, S\'ebastien},
title = {Dynare: Reference Manual, Version 6},
year = {2024},
title = {Dynare: Reference Manual Version 5},
year = {2022},
institution = {CEPREMAP},
type = {Dynare Working Papers},
number = {80},
number = {72},
}
If you want to give a URL, use the address of the Dynare website:

View File

@ -204,7 +204,7 @@ by the ``dynare`` command.
.. option:: params_derivs_order=0|1|2
When :comm:`identification`, :comm:`dynare_sensitivity` (with
identification), or :ref:`estimation <estim-comm>` are
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
@ -315,7 +315,7 @@ by the ``dynare`` command.
Prevent Dynare from printing the output of the steps leading up to the
preprocessor as well as the preprocessor output itself.
.. option:: mexext=mex|mexw64|mexmaci64|mexmaca64|mexa64
.. 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`.
@ -363,8 +363,7 @@ by the ``dynare`` command.
For local execution under Windows operating system,
set ``parallel_use_psexec=false`` to use ``start``
instead of ``psexec``, to properly allocate affinity when there are
more than 32 cores in the local machine. This option is also helpful if
``psexec`` cannot be executed due to missing admininstrator privileges. [default=true]
more than 32 cores in the local machine. [default=true]
.. option:: -DMACRO_VARIABLE[=MACRO_EXPRESSION]
@ -409,11 +408,9 @@ by the ``dynare`` command.
.. option:: fast
Dont rewrite the output files otherwise written to the disk by the preprocessor
when re-running the same model file while the lists of variables and the equations
havent changed. Note that the whole model still needs to be preprocessed. This option
is most useful with model option :opt:`use_dll`, because
the time-consuming compilation of the MEX files will be skipped. We use a 32
Only useful with model option :opt:`use_dll`. Dont recompile the
MEX files when running again the same model file and the lists
of variables and the equations havent 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
@ -554,13 +551,13 @@ by the ``dynare`` command.
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
``M_``,``oo_``, and ``options_`` structures are saved in a file
called ``FILENAME_results.mat`` located in the ``MODFILENAME/Output`` folder.
If they exist, ``estim_params_``,
``bayestopt_``, ``dataset_``, ``oo_recursive_`` and
``estimation_info`` are saved in the same file. Note that MATLAB
by default only allows ``.mat`` files up to 2GB. You can lift this
restriction by enabling the ``save -v7.3`` option in
``estimation_info`` are saved in the same file. Note that Matlab
by default only allows ``.mat``-files up to 2GB. You can lift this
restriction by enabling the ``save -v7.3``-option in
``Preferences -> General -> MAT-Files``.
.. matvar:: M_
@ -675,7 +672,7 @@ 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 the ``driver.m`` file then helps with debugging. Such problems most often
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.

View File

@ -15,16 +15,11 @@ 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 configuration file is searched by default under
``dynare/dynare.ini`` in the configuration directories defined by the XDG
specification (typically ``$HOME/.config/dynare/dynare.ini`` for the
user-specific configuration and ``/etc/xdg/dynare/dynare.ini`` for the
system-wide configuration, the former having precedence over the latter). Under
Windows, the configuration file is searched by default in
``%APPDATA%\dynare\dynare.ini`` (typically
``c:\Users\USERNAME\AppData\Roaming\dynare\dynare.ini``). You can specify a non
standard location using the ``conffile`` option of the ``dynare`` command (see
:ref:`dyn-invoc`).
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
@ -59,7 +54,7 @@ conventions such as ``USER_NAME`` have been excluded for concision):
``PATH_AND_FILE``
Indicates a valid path to a file in the underlying operating
system (e.g. ``/usr/local/MATLAB/R2023b/bin/matlab``).
system (e.g. ``/usr/local/MATLAB/R2010b/bin/matlab``).
``BOOLEAN``
@ -81,15 +76,8 @@ processing. Currently, there is only one option available.
.. option:: GlobalInitFile = PATH_AND_FILE
The location of a global initialization file that can be used to
customize some Dynare internals (typically default option values). This
is a MATLAB/Octave script.
If this option is not specified, Dynare will look for a
``global_init.m`` file in its configuration directory (typically
``$HOME/.config/dynare/global_init.m`` under Linux and macOS, and
``c:\Users\USERNAME\AppData\Roaming\dynare\global_init.m`` under
Windows).
The location of the global initialization file to be run at
the end of ``global_initialization.m``.
*Example*
@ -282,42 +270,18 @@ lines starting with a hashtag (#).
.. option:: MatlabOctavePath = PATH_AND_FILE
The path to the MATLAB or Octave executable. The default value
is ``matlab`` as MATLABs executable is typically in the %PATH% environment
variable. When using full paths on Windows, you may need to enclose the path
in quoted strings, e.g. ``MatlabOctavePath="C:\Program Files\MATLAB\R2023b\bin\matlab.exe"``
is ``matlab``.
.. option:: NumberOfThreadsPerJob = INTEGER
This option controls the distribution of jobs (e.g. MCMC chains) across additional MATLAB instances that are run in parallel.
Needs to be an exact divisor of the number of cores.
The formula :opt:`CPUnbr <CPUnbr = INTEGER | [INTEGER:INTEGER]>` divided by :opt:`NumberOfThreadsPerJob <NumberOfThreadsPerJob = INTEGER>`
calculates the number of MATLAB/Octave instances that will be launched in parallel,
where each instance will then execute a certain number of jobs sequentially.
For example, if you run a MCMC estimation with 24 chains on a 12 core machine, setting ``CPUnbr = 12`` and ``NumberOfThreadsPerJob = 4``
will launch 3 MATLAB instances in parallel, each of which will compute 8 chains sequentially.
Note that this option does not dictate the number of maximum threads utilized by each MATLAB/Octave instance,
see related option :opt:`SingleCompThread <SingleCompThread = BOOLEAN>` for this.
Particularly for very large models, setting this option to 2 might distribute the workload in a
more efficient manner, depending on your hardware and task specifics.
Its advisable to experiment with different values to achieve optimal performance.
The default value is ``1``.
For Windows nodes, sets the number of threads assigned to each
remote MATLAB/Octave run. The default value is 1.
.. option:: SingleCompThread = BOOLEAN
This option allows you to enable or disable MATLABs native multithreading capability. When set to ``true``,
the additional MATLAB instances are initiated in single thread mode utilizing the ``-singleCompThread`` startup option,
thereby disabling MATLABs native multithreading. When set to ``false``, MATLABs native multithreading
is enabled, e.g. the actual number of threads utilized by each MATLAB instance is usually determined by the number of CPU cores
(you can check this by running ``maxNumCompThreads`` in MATLABs command window).
Note: While MATLAB aims to accelerate calculations by distributing them across your computers threads,
certain tasks, like MCMC estimations, may exhibit slowdowns with MATLABs multitasking especially when Dynares parallel computing is turned on
as we do not use MATLABs parallel toolbox.
So in many cases it is advisable to set this setting to ``true``.
If you want to have more control, you can manually add the MATLAB command `maxNumCompThreads(N)` at the beginning of `fParallel.m`.
The default value is ``false``. This option is ineffective under Octave.
Whether or not to disable MATLABs native multithreading. The
default value is ``false``. Option meaningless under Octave.
.. option:: OperatingSystem = OPERATING_SYSTEM
The operating system associated with a node. Only necessary
@ -359,9 +323,7 @@ Windows Step-by-Step Guide
==========================
This section outlines the steps necessary on most Windows systems to
set up Dynare for parallel execution. Note that the steps 3 to 6 are
required unless parallel execution is confined to a local pool
with the ``parallel_use_psexec=false`` option.
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

File diff suppressed because it is too large Load Diff

View File

@ -15,15 +15,13 @@ class and methods for dates. Below, you will first find the class and
methods used for creating and dealing with dates and then the class
used for using time series. Dynare also provides an interface to the
X-13 ARIMA-SEATS seasonal adjustment program produced, distributed, and
maintained by the U.S. Census Bureau (2020).
maintained by the US Census Bureau (2017).
Dates
=====
.. highlight:: matlab
.. _dates in a mod file:
Dates in a mod file
-------------------
@ -719,7 +717,7 @@ The dates class
|br| Overloads the MATLAB/Octave ``mtimes`` operator
(``*``). ``A`` and ``B`` are respectively expected to be a
``dates`` object and a scalar integer. Returns ``dates``
``dseries`` object and a scalar integer. Returns ``dates``
object ``A`` replicated ``B`` times.
*Example*
@ -1027,7 +1025,7 @@ The dseries class
``.xls/.xlsx`` (Octave only supports ``.xlsx`` files and the
`io <https://octave.sourceforge.io/io/>`__ package from
Octave-Forge must be installed). The extension of the file
should be explicitly provided.
should be explicitly provided.
A typical ``.m`` file will have the following form::
@ -1054,10 +1052,10 @@ The dseries class
typically usefull if ``INIT__`` is not provided in the data
file.
If an ``.xlsx`` file is used, the first row should be a header
containing the variable names. The first column may contain date
information that must correspond to a valid date format recognized
by Dynare. If such date information is specified in the first column,
If an ``.xlsx`` file is used, the first row should be a header
containing the variable names. The first column may contain date
information that must correspond to a valid date format recognized
by Dynare. If such date information is specified in the first column,
its header name must be left empty.
.. construct:: dseries (DATA_MATRIX[,INITIAL_DATE[,LIST_OF_NAMES[,TEX_NAMES]]])
@ -1965,13 +1963,6 @@ The dseries class
|br| Returns the last period where all the variables in ``dseries`` object ``A`` are observed (non NaN).
.. dseriesmethod:: f = lastobservedperiods (A)
|br| Returns for each variable the last period without missing
observations in ``dseries`` object ``A``. Output argument ``f`` is a
structure, each field name is the name of a variable in ``A``, each field
content is a singleton ``date`` object.
.. dseriesmethod:: B = lead (A[, p])
lead_ (A[, p])
@ -2600,10 +2591,8 @@ The dseries class
.. dseriesmethod:: C = remove (A, B)
remove_ (A, B)
|br| If ``B`` is a row char array, the name of a variable, these methods
are aliases for ``pop`` and ``pop_`` methods with two arguments. They
remove variable ``B`` from ``dseries`` object ``A``. To remove more than
one variable, one can pass a cell of row char arrays for ``B``.
|br| Alias for the ``pop`` method with two arguments. Removes
variable ``B`` from ``dseries`` object ``A``.
*Example*
@ -2957,8 +2946,8 @@ X-13 ARIMA-SEATS interface
|br| The x13 class provides a method for each X-13 command as
documented in the X-13 ARIMA-SEATS reference manual (`x11`,
`automdl`, `estimate`, ...). The respective options (see Chapter 7 of U.S. Census Bureau (2020))
can then be passed by key/value pairs. The ``x13`` class has 22 members:
`automdl`, `estimate`, ...), options can then be passed by
key/value pairs. The ``x13`` class has 22 members:
:arg y: ``dseries`` object with a single variable.
:arg x: ``dseries`` object with an arbitrary number of variables (to be used in the REGRESSION block).
@ -3002,7 +2991,7 @@ X-13 ARIMA-SEATS interface
same time span.
The following methods allow to set sequence of X-13 commands, write an `.spc` file, and run the X-13 binary:
The Following methods allow to set sequence of X-13 commands, write an `.spc` file and run the X-13 binary:
.. x13method:: A = arima (A, key, value[, key, value[, [...]]])
@ -3037,10 +3026,7 @@ X-13 ARIMA-SEATS interface
Interface to the ``transform`` command, see the X-13
ARIMA-SEATS reference manual. All the options must be passed
by key/value pairs. For example, the key/value pair ``function,log``
instructs the use of a multiplicative instead of an additive seasonal pattern,
while ``function,auto`` triggers an automatic selection between the two based
on their fit.
by key/value pairs.
.. x13method:: A = outlier (A, key, value[, key, value[, [...]]])
@ -3148,11 +3134,6 @@ X-13 ARIMA-SEATS interface
``A.results``. When it makes sense these results are saved in
``dseries`` objects (*e.g.* for forecasts or filtered variables).
.. x13method:: clean (A)
Removes the temporary files created by an x13 run that store the intermediate
results. This method allows keeping the main folder clean but will also
delete potentially important debugging information.
*Example*
@ -3170,57 +3151,6 @@ X-13 ARIMA-SEATS interface
>> o.run();
The above example shows a run of X13 with various commands an options specified.
*Example*
::
% 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960
y = [112 115 145 171 196 204 242 284 315 340 360 417 ... % Jan
118 126 150 180 196 188 233 277 301 318 342 391 ... % Feb
132 141 178 193 236 235 267 317 356 362 406 419 ... % Mar
129 135 163 181 235 227 269 313 348 348 396 461 ... % Apr
121 125 172 183 229 234 270 318 355 363 420 472 ... % May
135 149 178 218 243 264 315 374 422 435 472 535 ... % Jun
148 170 199 230 264 302 364 413 465 491 548 622 ... % Jul
148 170 199 242 272 293 347 405 467 505 559 606 ... % Aug
136 158 184 209 237 259 312 355 404 404 463 508 ... % Sep
119 133 162 191 211 229 274 306 347 359 407 461 ... % Oct
104 114 146 172 180 203 237 271 305 310 362 390 ... % Nov
118 140 166 194 201 229 278 306 336 337 405 432 ]'; % Dec
ts = dseries(y,'1949M1');
o = x13(ts);
o.transform('function','auto','savelog','atr');
o.automdl('savelog','all');
o.x11('save','(d11 d10)');
o.run();
o.clean();
y_SA=o.results.d11;
y_seasonal_pattern=o.results.d10;
figure('Name','Comparison raw data and SAed data');
plot(ts.dates,log(o.y.data),ts.dates,log(y_SA.data),ts.dates,log(y_seasonal_pattern.data))
The above example shows how to remove a seasonal pattern from a time series.
``o.transform('function','auto','savelog','atr')`` instructs the subsequent
``o.automdl()`` command to check whether an additional or a multiplicative
pattern fits the data better and to save the result. The result is saved in
`o.results.autotransform`, which in the present example indicates that a
log transformation, i.e. a multiplicative model was preferred. The ``o.automdl('savelog','all')`` automatically selects a fitting
ARIMA model and saves all relevant output to the .log-file. The ``o.x11('save','(d11, d10)')`` instructs
``x11`` to save both the final seasonally adjusted series ``d11`` and the final seasonal factor ``d10``
into ``dseries`` with the respective names in the output structure ``o.results``. ``o.clean()`` removes the
temporary files created by ``o.run()``. Among these are the ``.log``-file storing
summary information, the ``.err``-file storing information on problems encountered,
the ``.out``-file storing the raw output, and the `.spc`-file storing the specification for the `x11` run.
There may be further files depending on the output requested. The last part of the example reads out the
results and plots a comparison of the logged raw data and its log-additive decomposition into a
seasonal pattern and the seasonally adjusted series.
Miscellaneous
=============

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright © 2018-2024 Dynare Team
# Copyright © 2018-2019 Dynare Team
#
# This file is part of Dynare.
#
@ -80,7 +80,9 @@ class DynObject(ObjectDescription):
signode += addnodes.desc_name(name, name)
if self.has_arguments:
if arglist:
if not arglist:
signode += addnodes.desc_parameterlist()
else:
signode += addnodes.desc_addname(arglist,arglist)
return fullname, prefix

View File

@ -60,7 +60,7 @@ class DynareLexer(RegexLexer):
"addSeries","addParagraph","addVspace","write","compile")
operators = (
"STEADY_STATE","EXPECTATION","var_expectation","pac_expectation","pac_target_nonstationary")
"STEADY_STATE","EXPECTATION","var_expectation","pac_expectation")
macro_dirs = (
"@#includepath", "@#include", "@#define", "@#if",
@ -83,8 +83,7 @@ class DynareLexer(RegexLexer):
'osr_params_bounds','ramsey_constraints','irf_calibration',
'moment_calibration','identification','svar_identification',
'matched_moments','occbin_constraints','surprise','overwrite','bind','relax',
'verbatim','end','node','cluster','paths','hooks','target','pac_target_info','auxname_target_nonstationary',
'component', 'growth', 'auxname', 'kind'), prefix=r'\b', suffix=r'\s*\b'),Keyword.Reserved),
'verbatim','end','node','cluster','paths','hooks'), prefix=r'\b', suffix=r'\s*\b'),Keyword.Reserved),
# FIXME: Commands following multiline comments are not highlighted properly.
(words(commands + report_commands,

View File

@ -0,0 +1,2 @@
version = u'@PACKAGE_VERSION@'
release = u'@PACKAGE_VERSION@'

29
doc/parallel/Makefile.am Normal file
View File

@ -0,0 +1,29 @@
if ENABLE_DOC
pdf-local: parallel.pdf
endif
SRC = AvenueParadigm.pdf iVaNo_gain.pdf iVaNo_time_comp.pdf marco.bib \
netbook_complete_comp.pdf netbook_complete_openclose.pdf \
netbook_partial_comp.pdf netbook_partial_openclose.pdf parallel.tex \
quest_complete_comp.pdf quest_complete_openclose.pdf quest_partial_comp.pdf \
quest_partial_openclose.pdf RWMH_quest1_PriorsAndPosteriors1Comp.pdf \
RWMH_quest1_PriorsAndPosteriors2Comp.pdf \
RWMH_quest1_PriorsAndPosteriors3Comp.pdf \
RWMH_quest1_PriorsAndPosteriors4Comp.pdf \
RWMH_quest1_PriorsAndPosteriors5Comp.pdf \
RWMH_quest1_PriorsAndPosteriors6Comp.pdf \
RWMH_quest1_PriorsAndPosteriors7Comp.pdf waitbars1.pdf waitbars2.pdf \
waitbarsP.pdf
EXTRA_DIST = $(SRC)
parallel.pdf: $(SRC)
$(PDFLATEX) parallel
$(BIBTEX) parallel
$(PDFLATEX) parallel
$(PDFLATEX) parallel
$(PDFLATEX) parallel
clean-local:
rm -f *.log *.aux *.toc *.blg *.bbl *.out
rm -f parallel.pdf

File diff suppressed because it is too large Load Diff

11
dynare++/Makefile.am Normal file
View File

@ -0,0 +1,11 @@
SUBDIRS = utils/cc sylv parser/cc tl doc integ kord src tests
EXTRA_DIST = dynare_simul
install-exec-local:
$(MKDIR_P) $(DESTDIR)$(pkglibdir)/dynare++
cp -r dynare_simul/* $(DESTDIR)$(pkglibdir)/dynare++
uninstall-local:
rm -rf $(DESTDIR)$(pkglibdir)/dynare++

20
dynare++/doc/Makefile.am Normal file
View File

@ -0,0 +1,20 @@
EXTRA_DIST = \
dynare++-ramsey.tex \
dynare++-tutorial.tex \
sylvester.tex \
tl.tex \
changelog-old.html \
changelog-sylv-old.html
if ENABLE_DOC
pdf-local: dynare++-ramsey.pdf dynare++-tutorial.pdf sylvester.pdf tl.pdf
endif
%.pdf: %.tex
$(PDFLATEX) $<
$(PDFLATEX) $<
$(PDFLATEX) $<
CLEANFILES = *.pdf *.log *.aux *.out *.toc

View File

@ -0,0 +1,280 @@
<HTML>
<TITLE>
Dynare++ Change Log
</TITLE>
<!-- $Header$ -->
<BODY>
<TABLE CELLSPACING=2 ALIGN="CENTER" BORDER=1>
<TR>
<TD BGCOLOR="#d0d0d0" WIDTH="85"> <b>Revision</b> </TD>
<TD BGCOLOR="#d0d0d0" WIDTH="85"> <b>Version</b></TD>
<TD BGCOLOR="#d0d0d0" WIDTH="80"> <b>Date</b> </TD>
<TD BGCOLOR="#d0d0d0" WIDTH="600"> <b>Description of changes</b></TD>
</TR>
<TR>
<TD>
<TD>1.3.7
<TD>2008/01/15
<TD>
<TR><TD><TD><TD> <TD> Corrected a serious bug in centralizing a
decision rule. This bug implies that all results based on simulations
of the decision rule were wrong. However results based on stochastic
fix points were correct. Thanks to Wouter J. den Haan and Joris de Wind!
<TR><TD><TD><TD> <TD> Added options --centralize and --no-centralize.
<TR><TD><TD><TD> <TD> Corrected an error of a wrong
variance-covariance matrix in real-time simulations (thanks to Pawel
Zabzcyk).
<TR><TD><TD><TD> <TD> Corrected a bug of integer overflow in refined
faa Di Bruno formula if one of refinements is empty. This bug appeared
when solving models without forward looking variables.
<TR><TD><TD><TD> <TD> Corrected a bug in the Sylvester equation
formerly working only for models with forward looking variables.
<TR><TD><TD><TD> <TD> Corrected a bug in global check printout.
<TR><TD><TD><TD> <TD> Added generating a dump file.
<TR><TD><TD><TD> <TD> Fixed a bug of forgetting repeated assignments
(for example in parameter settings and initval).
<TR><TD><TD><TD> <TD> Added a diff operator to the parser.
<TR>
<TD>1539
<TD>1.3.6
<TD>2008/01/03
<TD>
<TR><TD><TD><TD> <TD> Corrected a bug of segmentation faults for long
names and path names.
<TR><TD><TD><TD> <TD> Changed a way how random numbers are
generated. Dynare++ uses a separate instance of Mersenne twister for
each simulation, this corrects a flaw of additional randomness caused
by operating system scheduler. This also corrects a strange behaviour
of random generator on Windows, where each simulation was getting the
same sequence of random numbers.
<TR><TD><TD><TD> <TD> Added calculation of conditional distributions
controlled by --condper and --condsim.
<TR><TD><TD><TD> <TD> Dropped creating unfoled version of decision
rule at the end. This might consume a lot of memory. However,
simulations might be slower for some models.
<TR>
<TD>1368
<TD>1.3.5
<TD>2007/07/11
<TD>
<TR><TD><TD><TD> <TD> Corrected a bug of useless storing all derivative
indices in a parser. This consumed a lot of memory for large models.
<TR><TD><TD><TD> <TD> Added an option <tt>--ss-tol</tt> controlling a
tolerance used for convergence of a non-linear solver.
<TR><TD><TD><TD> <TD> Corrected buggy interaction of optimal policy
and forward looking variables with more than one period.
<TR><TD><TD><TD> <TD> Variance matrices can be positive
semidefinite. This corrects a bug of throwing an error if estimating
approximation errors on ellipse of the state space with a
deterministic variable.
<TR><TD><TD><TD> <TD> Implemented simulations with statistics
calculated in real-time. Options <tt>--rtsim</tt> and <tt>--rtper</tt>.
<TR>
<TD>1282
<TD>1.3.4
<TD>2007/05/15
<TD>
<TR><TD><TD><TD> <TD>Corrected a bug of wrong representation of NaN in generated M-files.
<TR><TD><TD><TD> <TD>Corrected a bug of occassionaly wrong evaluation of higher order derivatives of integer powers.
<TR><TD><TD><TD> <TD>Implemented automatic handling of terms involving multiple leads.
<TR><TD><TD><TD> <TD>Corrected a bug in the numerical integration, i.e. checking of the precision of the solution.
<TR>
<TD>1090
<TD>1.3.3
<TD>2006/11/20
<TD>
<TR><TD><TD><TD> <TD>Corrected a bug of non-registering an auxiliary variable in initval assignments.
<TR>
<TD>988
<TD>1.3.2
<TD>2006/10/11
<TD>
<TR><TD><TD><TD> <TD>Corrected a few not-serious bugs: segfault on
some exception, error in parsing large files, error in parsing
matrices with comments, a bug in dynare_simul.m
<TR><TD><TD><TD> <TD>Added posibility to specify a list of shocks for
which IRFs are calculated
<TR><TD><TD><TD> <TD>Added --order command line switch
<TR><TD><TD><TD> <TD>Added writing two MATLAB files for steady state
calcs
<TR><TD><TD><TD> <TD>Implemented optimal policy using keyword
planner_objective and planner_discount
<TR><TD><TD><TD> <TD>Implemented an R interface to Dynare++ algorithms
(Tamas Papp)
<TR><TD><TD><TD> <TD>Highlevel code reengineered to allow for
different model inputs
<TR>
<TD>799
<TD>1.3.1
<TD>2006/06/13
<TD>
<TR><TD><TD><TD> <TD>Corrected few bugs: in error functions, in linear algebra module.
<TR><TD><TD><TD> <TD>Updated dynare_simul.
<TR><TD><TD><TD> <TD>Updated the tutorial.
<TR><TD><TD><TD> <TD>Corrected an error in summing up tensors where
setting up the decision rule derivatives. Thanks to Michel
Juillard. The previous version was making deterministic effects of
future volatility smaller than they should be.
<TR>
<TD>766
<TD>1.3.0
<TD>2006/05/22
<TD>
<TR><TD><TD><TD> <TD>The non-linear solver replaced with a new one.
<TR><TD><TD><TD> <TD>The parser and derivator replaced with a new
code. Now it is possible to put expressions in parameters and initval
sections.
<TR>
<TD>752
<TD>1.2.2
<TD>2006/05/22
<TD>
<TR><TD><TD><TD> <TD>Added an option triggering/suppressing IRF calcs..
<TR><TD><TD><TD> <TD>Newton algortihm is now used for fix-point calculations.
<TR><TD><TD><TD> <TD> Vertical narrowing of tensors in Faa Di Bruno
formula to avoid multiplication with zeros..
<TR>
<TD>436
<TD>1.2.1
<TD>2005/08/17
<TD>
<TR><TD><TD><TD> <TD>Faa Di Bruno for sparse matrices optimized. The
implementation now accommodates vertical refinement of function stack
in order to fit a corresponding slice to available memory. In
addition, zero slices are identified. For some problems, this implies
significant speedup.
<TR><TD><TD><TD> <TD>Analytic derivator speedup.
<TR><TD><TD><TD> <TD>Corrected a bug in the threading code. The bug
stayed concealed in Linux 2.4.* kernels, and exhibited in Linux 2.6.*,
which has a different scheduling. This correction also allows using
detached threads on Windows.
<TR>
<TD>410
<TD>1.2
<TD>2005/07/29
<TD>
<TR><TD><TD><TD> <TD>Added Dynare++ tutorial.
<TR><TD><TD><TD> <TD>Changed and enriched contents of MAT-4 output
file.
<TR><TD><TD><TD> <TD>Corrected a bug of wrong variable indexation
resulting in an exception. The error occurred if a variable appeared
at time t-1 or t+1 and not at t.
<TR><TD><TD><TD> <TD>Added MATLAB interface, which allows simulation
of a decision rule in MATLAB.
<TR><TD><TD><TD> <TD>Got rid of Matrix Template Library.
<TR><TD><TD><TD> <TD>Added checking of model residuals by the
numerical integration. Three methods: checking along simulation path,
checking along shocks, and on ellipse of states.
<TR><TD><TD><TD> <TD>Corrected a bug in calculation of higher moments
of Normal dist.
<TR><TD><TD><TD> <TD>Corrected a bug of wrong drawing from Normal dist
with non-zero covariances.
<TR><TD><TD><TD>
<TD>Added numerical integration module. Product and Smolyak
quadratures over Gauss-Hermite and Gauss-Legendre, and quasi Monte
Carlo.
<TR>
<TD>152
<TD>1.1
<TD>2005/04/22
<TD>
<TR><TD><TD><TD>
<TD>Added a calculation of approximation at a stochastic steady state
(still experimental).
<TR><TD><TD><TD>
<TD>Corrected a bug in Cholesky decomposition of variance-covariance
matrix with off-diagonal elements.
<TR>
<TD>89
<TD>1.01
<TD>2005/02/23
<TD>
<TR><TD><TD><TD>
<TD>Added version printout.
<TR><TD><TD><TD>
<TD>Corrected the bug of multithreading support for P4 HT processors running on Win32.
<TR><TD><TD><TD>
<TD>Enhanced Kronecker product code resulting in approx. 20% speedup.
<TR><TD><TD><TD>
<TD>Implemented vertical stack container refinement, and another
method for sparse folded Faa Di Bruno (both not used yet).
<TR>
<TD>5
<TD>1.0
<TD>2005/02/23
<TD>The first released version.
</TABLE>
</BODY>
</HTML>

View File

@ -0,0 +1,140 @@
<HTML>
<!-- $Header: /var/lib/cvs/dynare_cpp/sylv/change_log.html,v 1.1.1.1 2004/06/04 13:00:05 kamenik Exp $ -->
<!-- Tag $Name: $ -->
<TITLE>
Sylvester Solver Change Log
</TITLE>
<BODY>
<TABLE CELLSPACING=2 ALIGN="CENTER" BORDER=1>
<TR>
<TD BGCOLOR="#d0d0d0" WIDTH="85"> Tag </TD>
<TD BGCOLOR="#d0d0d0" WIDTH="80"> Date </TD>
<TD BGCOLOR="#d0d0d0" WIDTH="600"> Description/Changes</TD>
</TR>
<TR>
<TD></TD>
<TD>2003/09/10</TD>
<TD>Initial version solving triangular system put to repository</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented solution of general case.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented a memory pool (Paris).</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented MEX interface to the routine (Paris).</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented QuasiTriangularZero (Paris) (not fully used yet).</TD>
</TR>
<TR>
<TD>rel-1</TD>
<TD>2003/10-02</TD>
<TD>Version sent to Michel.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Inheritance streamlined, QuasiTriangular inherits from GeneralMatrix.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented block diagonalization algorithm.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Solution routines rewritten so that the output rewrites input,
considerable memory improvement.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>MEX interface now links with LAPACK library from MATLAB.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Added a hack to MEX library loading in order to avoid MATLAB crash in Wins.</TD>
</TR>
<TR>
<TD>rel-2</TD>
<TD>2003/10/15</TD>
<TD>Version sent to Michel.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>KronUtils now rewrite input by output using less memory.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Added iterative solution algorithm (doubling).</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Introduced abstraction for set of parameters (SylvParams).</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Algorithm enabled to solve problems with singular C.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented a class chooser chossing between QuasiTriangularZero,
and QuasiTriangular (padded with zero) depending on size of the
problem. Full use of QuasiTriangularZero.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Reimplemented QuasiTriangular::solve, offdiagonal elements are
eleiminated by gauss with partial pivoting, not by transformation of
complex eigenvalues. More stable for ill conditioned eigenvalues.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Reimplemented calculation of eliminating vectors, much more
numerically stable now.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented algorithm for ordering of eigenvalues (not used now,
no numerical improvements).</TD>
</TR>
<TR>
<TD>rel-3</TD>
<TD>2003/12/4</TD>
<TD>Version sent to Michel.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>GeneralMatrix separated for use outside, in sylv module we use
its subclass SylvMatrix. Implemented ConstGeneralMatrix (useful outside).
</TD>
</TR>
<TR>
<TD>rel-4</TD>
<TD>2004/6/4</TD>
<TD>Version, which was moved to pythie.cepremap.cnrs.fr repository.</TD>
</TR>
</TABLE>
</BODY>
</HTML>

View File

@ -0,0 +1,157 @@
\documentclass[10pt]{article}
\usepackage{array,natbib,times}
\usepackage{amsmath, amsthm, amssymb}
%\usepackage[pdftex,colorlinks]{hyperref}
\begin{document}
\title{Implementation of Ramsey Optimal Policy in Dynare++, Timeless Perspective}
\author{Ondra Kamen\'\i k}
\date{June 2006}
\maketitle
\textbf{Abstract:} This document provides a derivation of Ramsey
optimal policy from timeless perspective and describes its
implementation in Dynare++.
\section{Derivation of the First Order Conditions}
Let us start with an economy populated by agents who take a number of
variables exogenously, or given. These may include taxes or interest
rates for example. These variables can be understood as decision (or control)
variables of the timeless Ramsey policy (or social planner). The agent's
information set at time $t$ includes mass-point distributions of these
variables for all times after $t$. If $i_t$ denotes an interest rate
for example, then the information set $I_t$ includes
$i_{t|t},i_{t+1|t},\ldots,i_{t+k|t},\ldots$ as numbers. In addition
the information set includes all realizations of past exogenous
innovations $u_\tau$ for $\tau=t,t-1,\ldots$ and distibutions
$u_\tau\sim N(0,\Sigma)$ for $\tau=t+1,\ldots$. These information sets will be denoted $I_t$.
An information set including only the information on past realizations
of $u_\tau$ and future distributions of $u_\tau\sim N(0\sigma)$ will
be denoted $J_t$. We will use the following notation for expectations
through these sets:
\begin{eqnarray*}
E^I_t[X] &=& E(X|I_t)\\
E^J_t[X] &=& E(X|J_t)
\end{eqnarray*}
The agents optimize taking the decision variables of the social
planner at $t$ and future as given. This means that all expectations
they form are conditioned on the set $I_t$. Let $y_t$ denote a vector
of all endogenous variables including the planer's decision
variables. Let the number of endogenous variables be $n$. The economy
can be described by $m$ equations including the first order conditions
and transition equations:
\begin{equation}\label{constr}
E_t^I\left[f(y_{t-1},y_t,y_{t+1},u_t)\right] = 0.
\end{equation}
This lefts $n-m$
the planner's control variables. The solution of this problem is a
decision rule of the form:
\begin{equation}\label{agent_dr}
y_t=g(y_{t-1},u_t,c_{t|t},c_{t+1|t},\ldots,c_{t+k|t},\ldots),
\end{equation}
where $c$ is a vector of planner's control variables.
Each period the social planner chooses the vector $c_t$ to maximize
his objective such that \eqref{agent_dr} holds for all times following
$t$. This would lead to $n-m$ first order conditions with respect to
$c_t$. These first order conditions would contain unknown derivatives
of endogenous variables with respect to $c$, which would have to be
retrieved from the implicit constraints \eqref{constr} since the
explicit form \eqref{agent_dr} is not known.
The other way to proceed is to assume that the planner is so dumb that
he is not sure what are his control variables. So he optimizes with
respect to all $y_t$ given the constraints \eqref{constr}. If the
planner's objective is $b(y_{t-1},y_t,y_{t+1},u_t)$ with a discount rate
$\beta$, then the optimization problem looks as follows:
\begin{align}
\max_{\left\{y_\tau\right\}^\infty_t}&E_t^J
\left[\sum_{\tau=t}^\infty\beta^{\tau-t}b(y_{\tau-1},y_\tau,y_{\tau+1},u_\tau)\right]\notag\\
&\rm{s.t.}\label{planner_optim}\\
&\hskip1cm E^I_\tau\left[f(y_{\tau-1},y_\tau,y_{\tau+1},u_\tau)\right]=0\quad\rm{for\ }
\tau=\ldots,t-1,t,t+1,\ldots\notag
\end{align}
Note two things: First, each constraint \eqref{constr} in
\eqref{planner_optim} is conditioned on $I_\tau$ not $I_t$. This is
very important, since the behaviour of agents at period $\tau=t+k$ is
governed by the constraint using expectations conditioned on $t+k$,
not $t$. The social planner knows that at $t+k$ the agents will use
all information available at $t+k$. Second, the constraints for the
planner's decision made at $t$ include also constraints for agent's
behaviour prior to $t$. This is because the agent's decision rules are
given in the implicit form \eqref{constr} and not in the explicit form
\eqref{agent_dr}.
Using Lagrange multipliers, this can be rewritten as
\begin{align}
\max_{y_t}E_t^J&\left[\sum_{\tau=t}^\infty\beta^{\tau-t}b(y_{\tau-1},y_\tau,y_{\tau+1},u_\tau)\right.\notag\\
&\left.+\sum_{\tau=-\infty}^{\infty}\beta^{\tau-t}\lambda^T_\tau E_\tau^I\left[f(y_{\tau-1},y_\tau,y_{\tau+1},u_\tau)\right]\right],
\label{planner_optim_l}
\end{align}
where $\lambda_t$ is a vector of Lagrange multipliers corresponding to
constraints \eqref{constr}. Note that the multipliers are multiplied
by powers of $\beta$ in order to make them stationary. Taking a
derivative wrt $y_t$ and putting it to zero yields the first order
conditions of the planner's problem:
\begin{align}
E^J_t\left[\vphantom{\frac{\int^(_)}{\int^(\_)}}\right.&\frac{\partial}{\partial y_t}b(y_{t-1},y_t,y_{t+1},u_t)+
\beta L^{+1}\frac{\partial}{\partial y_{t-1}}b(y_{t-1},y_t,y_{t+1},u_t)\notag\\
&+\beta^{-1}\lambda_{t-1}^TE^I_{t-1}\left[L^{-1}\frac{\partial}{\partial y_{t+1}}f(y_{t-1},y_t,y_{t+1},u_t)\right]\notag\\
&+\lambda_t^TE^I_t\left[\frac{\partial}{\partial y_{t}}f(y_{t-1},y_t,y_{t+1},u_t)\right]\notag\\
&+\beta\lambda_{t+1}^TE^I_{t+1}\left[L^{+1}\frac{\partial}{\partial y_{t-1}}f(y_{t-1},y_t,y_{t+1},u_t)\right]
\left.\vphantom{\frac{\int^(_)}{\int^(\_)}}\right]
= 0,\label{planner_optim_foc}
\end{align}
where $L^{+1}$ and $L^{-1}$ are one period lead and lag operators respectively.
Now we have to make a few assertions concerning expectations
conditioned on the different information sets to simplify
\eqref{planner_optim_foc}. Recall the formula for integration through
information on which another expectation is conditioned, this is:
$$E\left[E\left[u|v\right]\right] = E[u],$$
where the outer expectation integrates through $v$. Since $J_t\subset
I_t$, by easy application of the above formula we obtain
\begin{eqnarray}
E^J_t\left[E^I_t\left[X\right]\right] &=& E^J_t\left[X\right]\quad\rm{and}\notag\\
E^J_t\left[E^I_{t-1}\left[X\right]\right] &=& E^J_t\left[X\right]\label{e_iden}\\
E^J_t\left[E^I_{t+1}\left[X\right]\right] &=& E^J_{t+1}\left[X\right]\notag
\end{eqnarray}
Now, the last term of \eqref{planner_optim_foc} needs a special
attention. It is equal to
$E^J_t\left[\beta\lambda^T_{t+1}E^I_{t+1}[X]\right]$. If we assume
that the problem \eqref{planner_optim} has a solution, then there is a
deterministic function from $J_{t+1}$ to $\lambda_{t+1}$ and so
$\lambda_{t+1}\in J_{t+1}\subset I_{t+1}$. And the last term is equal
to $E^J_{t}\left[E^I_{t+1}[\beta\lambda^T_{t+1}X]\right]$, which is
$E^J_{t+1}\left[\beta\lambda^T_{t+1}X\right]$. This term can be
equivalently written as
$E^J_{t}\left[\beta\lambda^T_{t+1}E^J_{t+1}[X]\right]$. The reason why
we write the term in this way will be clear later. All in all, we have
\begin{align}
E^J_t\left[\vphantom{\frac{\int^(_)}{\int^(\_)}}\right.&\frac{\partial}{\partial y_t}b(y_{t-1},y_t,y_{t+1},u_t)+
\beta L^{+1}\frac{\partial}{\partial y_{t-1}}b(y_{t-1},y_t,y_{t+1},u_t)\notag\\
&+\beta^{-1}\lambda_{t-1}^TL^{-1}\frac{\partial}{\partial y_{t+1}}f(y_{t-1},y_t,y_{t+1},u_t)\notag\\
&+\lambda_t^T\frac{\partial}{\partial y_{t}}f(y_{t-1},y_t,y_{t+1},u_t)\notag\\
&+\beta\lambda_{t+1}^TE^J_{t+1}\left[L^{+1}\frac{\partial}{\partial y_{t-1}}f(y_{t-1},y_t,y_{t+1},u_t)\right]
\left.\vphantom{\frac{\int^(_)}{\int^(\_)}}\right]
= 0.\label{planner_optim_foc2}
\end{align}
Note that we have not proved that \eqref{planner_optim_foc} and
\eqref{planner_optim_foc2} are equivalent. We proved only that if
\eqref{planner_optim_foc} has a solution, then
\eqref{planner_optim_foc2} is equivalent (and has the same solution).
%%- \section{Implementation}
%%-
%%- The user inputs $b(y_{t-1},y_t,y_{t+1},u_t)$, $\beta$, and agent's
%%- first order conditions \eqref{constr}. The algorithm has to produce
%%- \eqref{planner_optim_foc2}.
%%-
\end{document}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,176 @@
%
% 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 © 2005-2011, Ondra Kamenik
% Copyright © 2020, Dynare Team
function r = dynare_simul(varargin)
if ~exist('dynare_simul_','file')
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};
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'],'var')
nstat = eval([prefix '_nstat']);
else
error(['Could not find variable ' prefix '_nstat in workspace']);
end
if exist([prefix '_npred'],'var')
npred = eval([prefix '_npred']);
else
error(['Could not find variable ' prefix '_npred in workspace']);
end
if exist([prefix '_nboth'],'var')
nboth = eval([prefix '_nboth']);
else
error(['Could not find variable ' prefix '_nboth in workspace']);
end
if exist([prefix '_nforw'],'var')
nforw = eval([prefix '_nforw']);
else
error(['Could not find variable ' prefix '_nforw in workspace']);
end
if exist([prefix '_ss'],'var')
ss = eval([prefix '_ss']);
else
error(['Could not find variable ' prefix '_ss in workspace']);
end
if exist([prefix '_vcov_exo'],'var')
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,'var')
dr.g_0=zeros(nstat+npred+nboth+nforw,1);
else
dr.g_0=eval(g_zero);
end
% make derstr a string of comma seperated existing prefix_g_*
order = 1;
cont = 1;
while cont == 1
g_ord = [prefix '_g_' num2str(order)];
if exist(g_ord,'var')
dr.(['g_' num2str(order)])=eval(g_ord);
order = order + 1;
else
cont = 0;
end
end
% set seed
seed = ceil(10000*rand(1,1));
% call dynare_simul_
[err,r]=dynare_simul_(order-1,nstat,npred,nboth,nforw,...
nexog,ystart,shocks,vcov_exo,seed,ss,dr);
if err
error('Simulation failed')
end

View File

@ -0,0 +1 @@
SUBDIRS = cc src testing

View File

@ -0,0 +1,15 @@
noinst_LIBRARIES = libinteg.a
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

File diff suppressed because it is too large Load Diff

View File

@ -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 <https://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;
}

View 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 <https://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=(QQ)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

View 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 <https://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)
{
}

View 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 <https://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 wx
¹
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
+
xe^{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
xdx
for level k.
Check precalc_quadrature.hh for available levels. */
class GaussLegendre : public OneDPrecalcQuadrature
{
public:
GaussLegendre();
};
#endif

View File

@ -0,0 +1,214 @@
/*
* 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 <https://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;
}

View File

@ -0,0 +1,256 @@
/*
* Copyright © 2005 Ondra Kamenik
* Copyright © 2019-2022 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 <https://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^{½xx}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,,base1. */
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 RadicalInverses 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;
}
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

View 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 <https://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+d1 and all k are positive integers. This is
equivalent to going through all k such that ld|k|l1 and all k are
non-negative integers. This is equivalent to going through d+1 dimensional
sequences (k,x) such that |(k,x)|=l1 and x=0,,d1. 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;
}

View 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 <https://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
d1
Qf = (1)^{l+d|k|1} (Q¹_kQ¹_{k_d})f
l|k|l+d1 |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:
d1
(1)^{l+d|k|1} (Q¹_kQ¹_{k_d})f
l|k|l+d1 |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

View File

@ -0,0 +1,147 @@
/*
* 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 <https://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
}

View 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 <https://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^{½yy} (2)|A|dy = f(2·Ay)e^{½yy}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

View File

@ -0,0 +1,5 @@
noinst_PROGRAMS = quadrature-points
quadrature_points_SOURCES = quadrature-points.cc
quadrature_points_CPPFLAGS = -I../.. -I../../sylv/cc -I../../integ/cc -I../../tl/cc -I../../utils/cc
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)

View File

@ -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 <https://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;
}

View File

@ -0,0 +1,9 @@
check_PROGRAMS = tests
tests_SOURCES = tests.cc
tests_CPPFLAGS = -I../cc -I../../tl/cc -I../../sylv/cc -I../../utils/cc -I$(top_srcdir)/mex/sources
tests_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_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

View File

@ -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 <https://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;
}

40
dynare++/kord/Makefile.am Normal file
View File

@ -0,0 +1,40 @@
noinst_LIBRARIES = libkord.a
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
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)\"
check_PROGRAMS = tests
tests_SOURCES = tests.cc
tests_CPPFLAGS = -I../sylv/cc -I../tl/cc -I../integ/cc -I../utils/cc -I$(top_srcdir)/mex/sources
tests_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_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
CLEANFILES = out.txt

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2005 Ondra Kamenik
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019-2021 Dynare Team
*
* This file is part of Dynare.
*
@ -20,15 +20,15 @@
#include <utility>
#include "kord_exception.hh"
#include "approximation.hh"
#include "first_order.hh"
#include "kord_exception.hh"
#include "korder_stoch.hh"
ZAuxContainer::ZAuxContainer(const _Ctype* gss, int ngss, int ng, int ny, int nu) :
StackContainer<FGSTensor>(4, 1)
ZAuxContainer::ZAuxContainer(const _Ctype *gss, int ngss, int ng, int ny, int nu)
: StackContainer<FGSTensor>(4, 1)
{
stack_sizes = {ngss, ng, ny, nu};
stack_sizes = { ngss, ng, ny, nu };
conts[0] = gss;
calculateOffsets();
}
@ -37,36 +37,29 @@ ZAuxContainer::ZAuxContainer(const _Ctype* gss, int ngss, int ng, int ny, int nu
argument we return matrix, for other three we return zero. */
ZAuxContainer::itype
ZAuxContainer::getType(int i, const Symmetry& s) const
ZAuxContainer::getType(int i, const Symmetry &s) const
{
if (i == 0)
{
if (s[2] > 0)
return itype::zero;
else
return itype::matrix;
}
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, bool pruned_dr,
double qz_crit) :
model(m),
journal(j),
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},
nvs{ypart.nys(), model.nexog(), model.nexog(), 1},
steps(ns),
dr_centralize(dr_centr),
pruning(pruned_dr),
qz_criterium(qz_crit),
ss(ypart.ny(), steps + 1)
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&
const FoldDecisionRule &
Approximation::getFoldDecisionRule() const
{
KORD_RAISE_IF(!fdr,
@ -74,22 +67,12 @@ Approximation::getFoldDecisionRule() const
return *fdr;
}
/* This just returns fdr_pruning with a check that it is created. */
const UnfoldDecisionRule&
Approximation::getUnfoldDecisionRulePruning() const
{
KORD_RAISE_IF(
!udr_pruning,
"Unfolded decision rule has not been created in Approximation::getUnfoldDecisionRule");
return *udr_pruning;
}
/* This just returns udr with a check that it is created. */
const UnfoldDecisionRule&
const UnfoldDecisionRule &
Approximation::getUnfoldDecisionRule() const
{
KORD_RAISE_IF(
!udr, "Unfolded decision rule has not been created in Approximation::getUnfoldDecisionRule");
KORD_RAISE_IF(!udr,
"Unfolded decision rule has not been created in Approximation::getUnfoldDecisionRule");
return *udr;
}
@ -101,13 +84,15 @@ 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);
FirstOrder fo(model.nstat(), model.npred(), model.nboth(), model.nforw(),
model.nexog(), model.getModelDerivatives().get(Symmetry{1}),
journal, qz_criterium);
if (model.order() >= 2)
{
KOrder korder(model.nstat(), model.npred(), model.nboth(), model.nforw(),
model.getModelDerivatives(), fo.getGy(), fo.getGu(), model.getVcov(), journal);
model.getModelDerivatives(), fo.getGy(), fo.getGu(),
model.getVcov(), journal);
korder.switchToFolded();
for (int k = 2; k <= model.order(); k++)
korder.performStep<Storage::fold>(k);
@ -159,28 +144,27 @@ Approximation::walkStochSteady()
to ss. */
model.solveDeterministicSteady();
approxAtSteady();
Vector steady0 {ss.getCol(0)};
Vector steady0{ss.getCol(0)};
steady0 = model.getSteady();
double sigma_so_far = 0.0;
double dsigma = (steps == 0) ? 0.0 : 1.0 / steps;
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;
pa << "Approximation about stochastic steady for sigma=" << sigma_so_far+dsigma << endrec;
Vector last_steady(const_cast<const Vector&>(model.getSteady()));
Vector last_steady(const_cast<const Vector &>(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(model.getSteady());
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() << ".";
rec << "Fix point calcs: iter=" << fp.getNumIter() << ", newton_iter="
<< fp.getNewtonTotalIter() << ", last_newton_iter=" << fp.getNewtonLastIter() << ".";
if (converged)
rec << " Converged." << endrec;
else
@ -188,7 +172,7 @@ Approximation::walkStochSteady()
rec << " Not converged!!" << endrec;
KORD_RAISE_X("Fix point calculation not converged", KORD_FP_NOT_CONV);
}
Vector steadyi {ss.getCol(i)};
Vector steadyi{ss.getCol(i)};
steadyi = model.getSteady();
// calculate hh as expectations of the last g**
@ -196,11 +180,11 @@ Approximation::walkStochSteady()
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(const_cast<const Vector&>(model.getSteady()));
Vector dy(const_cast<const Vector &>(model.getSteady()));
dy.add(-1.0, last_steady);
StochForwardDerivs<Storage::fold> hh(ypart, model.nexog(), *rule_ders_ss, mom, dy, dsigma,
sigma_so_far);
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;
@ -208,35 +192,29 @@ Approximation::walkStochSteady()
/* 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);
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);
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 (pruning)
{
fdr_pruning = std::make_unique<FoldDecisionRule>(
*rule_ders, ypart, model.nexog(), model.getSteady(), 1.0 - sigma_so_far, pruning);
udr_pruning = std::make_unique<UnfoldDecisionRule>(*fdr_pruning);
}
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(model.getSteady());
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() << ".";
rec << "Fix point calcs: iter=" << fp.getNumIter() << ", newton_iter="
<< fp.getNewtonTotalIter() << ", last_newton_iter=" << fp.getNewtonLastIter() << ".";
if (converged)
rec << " Converged." << endrec;
else
@ -259,17 +237,16 @@ Approximation::walkStochSteady()
from a temporary object and will be destroyed. */
void
Approximation::saveRuleDerivs(const FGSContainer& g)
Approximation::saveRuleDerivs(const FGSContainer &g)
{
rule_ders = std::make_unique<FGSContainer>(g);
rule_ders_s = std::make_unique<FGSContainer>(4);
rule_ders_ss = std::make_unique<FGSContainer>(4);
for (auto& run : *rule_ders)
for (auto &run : *rule_ders)
{
auto ten_s = std::make_unique<FGSTensor>(ypart.nstat, ypart.nys(), *(run.second));
rule_ders_s->insert(std::move(ten_s));
auto ten_ss
= std::make_unique<FGSTensor>(ypart.nstat + ypart.npred, ypart.nyss(), *(run.second));
auto ten_ss = std::make_unique<FGSTensor>(ypart.nstat+ypart.npred, ypart.nyss(), *(run.second));
rule_ders_ss->insert(std::move(ten_ss));
}
}
@ -290,37 +267,39 @@ Approximation::saveRuleDerivs(const FGSContainer& g)
add the σ/d! multiple to the result. */
void
Approximation::calcStochShift(Vector& out, double at_sigma) const
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());
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};
{
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);
}
// 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}));
// 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());
}
out.add(pow(at_sigma, d)/dfac, tmp->getData());
}
}
}
/* This method calculates and reports
@ -344,8 +323,8 @@ Approximation::check(double at_sigma) const
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;
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);
@ -378,12 +357,12 @@ Approximation::check(double at_sigma) const
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});
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));
TwoDMatrix B(const_cast<const TwoDMatrix &>(G));
B.mult(-1.0);
TwoDMatrix C(transpose(G));
TwoDMatrix A(model.numeq(), model.numeq());
@ -393,8 +372,8 @@ Approximation::calcYCov() const
TwoDMatrix X((gu * model.getVcov()) * transpose(gu));
GeneralSylvester gs(1, model.numeq(), model.numeq(), 0, A.getData(), B.getData(), C.getData(),
X.getData());
GeneralSylvester gs(1, model.numeq(), model.numeq(), 0,
A.getData(), B.getData(), C.getData(), X.getData());
gs.solve();
return X;

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2005 Ondra Kamenik
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019-2021 Dynare Team
*
* This file is part of Dynare.
*
@ -61,13 +61,13 @@
calculate also its unfolded versions, to be available for simulations
and so on. */
#ifndef APPROXIMATION_HH
#define APPROXIMATION_HH
#ifndef APPROXIMATION_H
#define APPROXIMATION_H
#include "decision_rule.hh"
#include "dynamic_model.hh"
#include "journal.hh"
#include "decision_rule.hh"
#include "korder.hh"
#include "journal.hh"
#include <memory>
@ -87,8 +87,8 @@ class ZAuxContainer : public StackContainer<FGSTensor>, public FoldedStackContai
public:
using _Ctype = StackContainer<FGSTensor>::_Ctype;
using itype = StackContainer<FGSTensor>::itype;
ZAuxContainer(const _Ctype* gss, int ngss, int ng, int ny, int nu);
[[nodiscard]] itype getType(int i, const Symmetry& s) const override;
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
@ -119,63 +119,57 @@ public:
class Approximation
{
DynamicModel& model;
Journal& journal;
DynamicModel &model;
Journal &journal;
std::unique_ptr<FGSContainer> rule_ders;
std::unique_ptr<FGSContainer> rule_ders_s;
std::unique_ptr<FGSContainer> rule_ders_ss;
std::unique_ptr<FoldDecisionRule> fdr;
std::unique_ptr<FoldDecisionRule> fdr_pruning;
std::unique_ptr<UnfoldDecisionRule> udr;
std::unique_ptr<UnfoldDecisionRule> udr_pruning;
const PartitionY ypart;
const FNormalMoments mom;
IntSequence nvs;
int steps;
bool dr_centralize;
bool pruning;
double qz_criterium;
TwoDMatrix ss;
public:
Approximation(DynamicModel& m, Journal& j, int ns, bool dr_centr, bool pruning, double qz_crit);
Approximation(DynamicModel &m, Journal &j, int ns, bool dr_centr, double qz_crit);
[[nodiscard]] const FoldDecisionRule& getFoldDecisionRule() const;
[[nodiscard]] const UnfoldDecisionRule& getUnfoldDecisionRulePruning() const;
[[nodiscard]] const UnfoldDecisionRule& getUnfoldDecisionRule() const;
[[nodiscard]] const TwoDMatrix&
const FoldDecisionRule &getFoldDecisionRule() const;
const UnfoldDecisionRule &getUnfoldDecisionRule() const;
const TwoDMatrix &
getSS() const
{
return ss;
}
[[nodiscard]] const DynamicModel&
const DynamicModel &
getModel() const
{
return model;
}
void walkStochSteady();
[[nodiscard]] TwoDMatrix calcYCov() const;
[[nodiscard]] const FGSContainer&
TwoDMatrix calcYCov() const;
const FGSContainer &
get_rule_ders() const
{
return *rule_ders;
}
[[nodiscard]] const FGSContainer&
const FGSContainer &
get_rule_ders_s() const
{
return *rule_ders_s;
}
[[nodiscard]] const FGSContainer&
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 calcStochShift(Vector &out, double at_sigma) const;
void saveRuleDerivs(const FGSContainer &g);
void check(double at_sigma) const;
};

View 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 <https://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];
}

File diff suppressed because it is too large Load Diff

View 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 <https://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));
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2005 Ondra Kamenik
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019 Dynare Team
*
* This file is part of Dynare.
*
@ -27,11 +27,11 @@
The interface is defined via pure virtual class DynamicModel. */
#ifndef DYNAMIC_MODEL_HH
#define DYNAMIC_MODEL_HH
#ifndef DYNAMIC_MODEL_H
#define DYNAMIC_MODEL_H
#include "sparse_tensor.hh"
#include "t_container.hh"
#include "sparse_tensor.hh"
#include "Vector.hh"
@ -45,9 +45,11 @@ class NameList
{
public:
virtual ~NameList() = default;
[[nodiscard]] virtual int getNum() const = 0;
[[nodiscard]] virtual const std::string& getName(int i) const = 0;
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
@ -109,34 +111,33 @@ public:
class DynamicModel
{
public:
[[nodiscard]] virtual std::unique_ptr<DynamicModel> clone() const = 0;
virtual std::unique_ptr<DynamicModel> clone() const = 0;
virtual ~DynamicModel() = default;
[[nodiscard]] virtual int nstat() const = 0;
[[nodiscard]] virtual int nboth() const = 0;
[[nodiscard]] virtual int npred() const = 0;
[[nodiscard]] virtual int nforw() const = 0;
[[nodiscard]] virtual int nexog() const = 0;
[[nodiscard]] virtual int order() const = 0;
[[nodiscard]] int
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();
return nstat()+nboth()+npred()+nforw();
}
[[nodiscard]] virtual const NameList& getAllEndoNames() const = 0;
[[nodiscard]] virtual const NameList& getStateNames() const = 0;
[[nodiscard]] virtual const NameList& getExogNames() const = 0;
[[nodiscard]] virtual const TwoDMatrix& getVcov() const = 0;
[[nodiscard]] virtual const TensorContainer<FSSparseTensor>& getModelDerivatives() const = 0;
[[nodiscard]] virtual const Vector& getSteady() const = 0;
virtual Vector& getSteady() = 0;
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 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;
};

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2005 Ondra Kamenik
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019-2022 Dynare Team
*
* This file is part of Dynare.
*
@ -27,8 +27,9 @@
/* 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)
FaaDiBruno::calculate(const StackContainer<FGSTensor> &cont,
const TensorContainer<FSSparseTensor> &f,
FGSTensor &out)
{
out.zeros();
for (int l = 1; l <= out.dimen(); l++)
@ -46,7 +47,8 @@ FaaDiBruno::calculate(const StackContainer<FGSTensor>& cont,
/* 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)
FaaDiBruno::calculate(const FoldedStackContainer &cont, const FGSContainer &g,
FGSTensor &out)
{
out.zeros();
for (int l = 1; l <= out.dimen(); l++)
@ -54,7 +56,7 @@ FaaDiBruno::calculate(const FoldedStackContainer& cont, const FGSContainer& g, F
long int mem = SystemResources::availableMemory();
cont.multAndAdd(l, g, out);
JournalRecord rec(journal);
int mem_mb = mem / 1024 / 1024;
int mem_mb = mem/1024/1024;
rec << "dim=" << l << " avmem=" << mem_mb << endrec;
}
}
@ -63,8 +65,9 @@ FaaDiBruno::calculate(const FoldedStackContainer& cont, const FGSContainer& g, F
/* 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)
FaaDiBruno::calculate(const StackContainer<UGSTensor> &cont,
const TensorContainer<FSSparseTensor> &f,
UGSTensor &out)
{
out.zeros();
for (int l = 1; l <= out.dimen(); l++)
@ -81,7 +84,8 @@ FaaDiBruno::calculate(const StackContainer<UGSTensor>& cont,
// FaaDiBruno::calculate() unfolded dense code
/* Again, no tuning opportunity here. */
void
FaaDiBruno::calculate(const UnfoldedStackContainer& cont, const UGSContainer& g, UGSTensor& out)
FaaDiBruno::calculate(const UnfoldedStackContainer &cont, const UGSContainer &g,
UGSTensor &out)
{
out.zeros();
for (int l = 1; l <= out.dimen(); l++)
@ -89,7 +93,7 @@ FaaDiBruno::calculate(const UnfoldedStackContainer& cont, const UGSContainer& g,
long int mem = SystemResources::availableMemory();
cont.multAndAdd(l, g, out);
JournalRecord rec(journal);
int mem_mb = mem / 1024 / 1024;
int mem_mb = mem/1024/1024;
rec << "dim=" << l << " avmem=" << mem_mb << endrec;
}
}
@ -125,21 +129,21 @@ FaaDiBruno::calculate(const UnfoldedStackContainer& cont, const UGSContainer& g,
do something. */
std::tuple<int, int, int>
FaaDiBruno::estimRefinement(const TensorDimens& tdims, int nr, int l)
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 per_size = sizeof(double)*nr
*static_cast<long>(lambda*per_size1+(1-lambda)*per_size2);
long mem = SystemResources::availableMemory();
int max = 0;
if (double num_cols {static_cast<double>(mem - magic_mult * nthreads * per_size) / nthreads
/ sizeof(double) / nr};
num_cols > 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);
double maxd = std::pow(num_cols, 1.0/l);
max = static_cast<int>(std::floor(maxd));
}
if (max == 0)
@ -151,7 +155,7 @@ FaaDiBruno::estimRefinement(const TensorDimens& tdims, int nr, int l)
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};
int avmem_mb = mem/1024/1024;
int tmpmem_mb = nthreads*per_size/1024/1024;
return { max, avmem_mb, tmpmem_mb };
}

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2005 Ondra Kamenik
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019 Dynare Team
*
* This file is part of Dynare.
*
@ -29,34 +29,35 @@
where s is a general symmetry of dimension k and z is a stack of
functions. */
#ifndef FAA_DI_BRUNO_HH
#define FAA_DI_BRUNO_HH
#ifndef FAA_DI_BRUNO_H
#define FAA_DI_BRUNO_H
#include "gs_tensor.hh"
#include "journal.hh"
#include "sparse_tensor.hh"
#include "stack_container.hh"
#include "t_container.hh"
#include "sparse_tensor.hh"
#include "gs_tensor.hh"
#include <tuple>
class FaaDiBruno
{
Journal& journal;
Journal &journal;
public:
FaaDiBruno(Journal& jr) : journal(jr)
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);
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);
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;

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2004 Ondra Kamenik
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019-2022 Dynare Team
*
* This file is part of Dynare.
*
@ -18,10 +18,8 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <vector>
#include "first_order.hh"
#include "kord_exception.hh"
#include "first_order.hh"
#include <dynlapack.h>
@ -33,10 +31,9 @@ std::mutex FirstOrder::mut;
criterium). */
lapack_int
FirstOrder::order_eigs(const double* alphar, const double* alphai, const double* beta)
FirstOrder::order_eigs(const double *alphar, const double *alphai, const double *beta)
{
return (*alphar * *alphar + *alphai * *alphai
< *beta * *beta * qz_criterium_global * qz_criterium_global);
return (*alphar **alphar + *alphai **alphai < *beta **beta * qz_criterium_global * qz_criterium_global);
}
/* Here we solve the linear approximation. The result are the matrices
@ -52,7 +49,7 @@ FirstOrder::order_eigs(const double* alphar, const double* alphai, const double*
and partitioning of the vector y (from object). */
void
FirstOrder::solve(const TwoDMatrix& fd)
FirstOrder::solve(const TwoDMatrix &fd)
{
JournalRecordPair pa(journal);
pa << "Recovering first order derivatives " << endrec;
@ -144,16 +141,17 @@ FirstOrder::solve(const TwoDMatrix& fd)
ConstTwoDMatrix fymins(fd, off, ypart.nys());
off += ypart.nys();
ConstTwoDMatrix fuzero(fd, off, nu);
off += nu;
// Form matrix D
lapack_int n = ypart.ny() + ypart.nboth;
lapack_int n = ypart.ny()+ypart.nboth;
TwoDMatrix matD(n, n);
matD.zeros();
matD.place(fypzero, 0, 0);
matD.place(fybzero, 0, ypart.npred);
matD.place(fyplus, 0, ypart.nys() + ypart.nstat);
matD.place(fyplus, 0, ypart.nys()+ypart.nstat);
for (int i = 0; i < ypart.nboth; i++)
matD.get(ypart.ny() + i, ypart.npred + i) = 1.0;
matD.get(ypart.ny()+i, ypart.npred+i) = 1.0;
lapack_int ldb = matD.getLD();
// Form matrix E
@ -161,9 +159,9 @@ FirstOrder::solve(const TwoDMatrix& fd)
matE.zeros();
matE.place(fymins, 0, 0);
matE.place(fyszero, 0, ypart.nys());
matE.place(fyfzero, 0, ypart.nys() + ypart.nstat + ypart.nboth);
matE.place(fyfzero, 0, ypart.nys()+ypart.nstat+ypart.nboth);
for (int i = 0; i < ypart.nboth; i++)
matE.get(ypart.ny() + i, ypart.nys() + ypart.nstat + i) = -1.0;
matE.get(ypart.ny()+i, ypart.nys()+ypart.nstat+i) = -1.0;
matE.mult(-1.0);
lapack_int lda = matE.getLD();
@ -171,28 +169,30 @@ FirstOrder::solve(const TwoDMatrix& fd)
TwoDMatrix vsl(n, n);
TwoDMatrix vsr(n, n);
lapack_int ldvsl = vsl.getLD(), ldvsr = vsr.getLD();
lapack_int lwork = 100 * n + 16;
lapack_int lwork = 100*n+16;
Vector work(lwork);
std::vector<lapack_int> bwork(n);
auto bwork = std::make_unique<lapack_int[]>(n);
lapack_int info;
lapack_int sdim2 = sdim;
{
std::lock_guard<std::mutex> lk {mut};
std::lock_guard<std::mutex> lk{mut};
qz_criterium_global = qz_criterium;
dgges("N", "V", "S", order_eigs, &n, matE.getData().base(), &lda, matD.getData().base(), &ldb,
&sdim2, alphar.base(), alphai.base(), beta.base(), vsl.getData().base(), &ldvsl,
vsr.getData().base(), &ldvsr, work.base(), &lwork, bwork.data(), &info);
dgges("N", "V", "S", order_eigs, &n, matE.getData().base(), &lda,
matD.getData().base(), &ldb, &sdim2, alphar.base(), alphai.base(),
beta.base(), vsl.getData().base(), &ldvsl, vsr.getData().base(), &ldvsr,
work.base(), &lwork, bwork.get(), &info);
}
if (info)
throw KordException(__FILE__, __LINE__, "DGGES returns an error in FirstOrder::solve");
throw KordException(__FILE__, __LINE__,
"DGGES returns an error in FirstOrder::solve");
sdim = sdim2;
bk_cond = (sdim == ypart.nys());
// Setup submatrices of Z
ConstGeneralMatrix z11(vsr, 0, 0, ypart.nys(), ypart.nys());
ConstGeneralMatrix z12(vsr, 0, ypart.nys(), ypart.nys(), n - ypart.nys());
ConstGeneralMatrix z21(vsr, ypart.nys(), 0, n - ypart.nys(), ypart.nys());
ConstGeneralMatrix z22(vsr, ypart.nys(), ypart.nys(), n - ypart.nys(), n - ypart.nys());
ConstGeneralMatrix z12(vsr, 0, ypart.nys(), ypart.nys(), n-ypart.nys());
ConstGeneralMatrix z21(vsr, ypart.nys(), 0, n-ypart.nys(), ypart.nys());
ConstGeneralMatrix z22(vsr, ypart.nys(), ypart.nys(), n-ypart.nys(), n-ypart.nys());
// Calculate derivatives of static and forward
/* Here we calculate X=Z₂₂⁻ᵀZ₁₂ᵀ, where X is sfder in the code. */
@ -214,12 +214,11 @@ FirstOrder::solve(const TwoDMatrix& fd)
gy.place(preder, ypart.nstat, 0);
GeneralMatrix sder(sfder, 0, 0, ypart.nstat, ypart.nys());
gy.place(sder, 0, 0);
GeneralMatrix fder(sfder, ypart.nstat + ypart.nboth, 0, ypart.nforw, ypart.nys());
gy.place(fder, ypart.nstat + ypart.nys(), 0);
GeneralMatrix fder(sfder, ypart.nstat+ypart.nboth, 0, ypart.nforw, ypart.nys());
gy.place(fder, ypart.nstat+ypart.nys(), 0);
// Check difference for derivatives of both
GeneralMatrix bder(const_cast<const GeneralMatrix&>(sfder), ypart.nstat, 0, ypart.nboth,
ypart.nys());
GeneralMatrix bder(const_cast<const GeneralMatrix &>(sfder), ypart.nstat, 0, ypart.nboth, ypart.nys());
GeneralMatrix bder2(preder, ypart.npred, 0, ypart.nboth, ypart.nys());
bder.add(-1, bder2);
b_error = bder.getData().getMax();
@ -238,7 +237,7 @@ FirstOrder::solve(const TwoDMatrix& fd)
is matA in the code. */
GeneralMatrix matA(ypart.ny(), ypart.ny());
matA.zeros();
ConstGeneralMatrix gss(gy, ypart.nstat + ypart.npred, 0, ypart.nyss(), ypart.nys());
ConstGeneralMatrix gss(gy, ypart.nstat+ypart.npred, 0, ypart.nyss(), ypart.nys());
matA.place(fyplus * gss, 0, ypart.nstat);
ConstGeneralMatrix fyzero(fd, 0, ypart.nyss(), ypart.ny(), ypart.ny());
matA.add(1.0, fyzero);
@ -248,7 +247,9 @@ FirstOrder::solve(const TwoDMatrix& fd)
journalEigs();
KORD_RAISE_IF_X(!bk_cond, "The model is not Blanchard-Kahn stable", KORD_MD_NOT_STABLE);
KORD_RAISE_IF_X(!bk_cond,
"The model is not Blanchard-Kahn stable",
KORD_MD_NOT_STABLE);
if (!gy.isFinite() || !gu.isFinite())
throw KordException(__FILE__, __LINE__,
"NaN or Inf asserted in first order derivatives in FirstOrder::solve()");
@ -282,9 +283,9 @@ FirstOrder::journalEigs()
jr << endrec;
}
JournalRecord jr(journal);
double mod = std::sqrt(alphar[i] * alphar[i] + alphai[i] * alphai[i]);
mod = mod / std::round(100000 * std::abs(beta[i])) * 100000;
jr << i << "\t(" << alphar[i] << "," << alphai[i] << ") / " << beta[i] << " \t" << mod
<< endrec;
double mod = std::sqrt(alphar[i]*alphar[i]+alphai[i]*alphai[i]);
mod = mod/std::round(100000*std::abs(beta[i]))*100000;
jr << i << "\t(" << alphar[i] << "," << alphai[i] << ") / " << beta[i]
<< " \t" << mod << endrec;
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2004 Ondra Kamenik
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019 Dynare Team
*
* This file is part of Dynare.
*
@ -20,8 +20,8 @@
// First order at deterministic steady state
#ifndef FIRST_ORDER_HH
#define FIRST_ORDER_HH
#ifndef FIRST_ORDER_H
#define FIRST_ORDER_H
#include "korder.hh"
@ -44,10 +44,10 @@ class FirstOrder
Vector alphai;
Vector beta;
double qz_criterium;
Journal& journal;
Journal &journal;
// Passed to LAPACK's DGGES
static lapack_int order_eigs(const double* alphar, const double* alphai, const double* beta);
static lapack_int order_eigs(const double *alphar, const double *alphai, const double *beta);
// The value of qz_criterium_global used by the order_eigs function
/* NB: we have no choice but to use a global variable, since LAPACK won't
@ -56,35 +56,33 @@ class FirstOrder
// Protects the static qz_criterium_global
static std::mutex mut;
public:
FirstOrder(int num_stat, int num_pred, int num_both, int num_forw, int num_u,
const FSSparseTensor& f, Journal& jr, double qz_crit) :
ypart(num_stat, num_pred, num_both, num_forw),
FirstOrder(int num_stat, int num_pred, int num_both, int num_forw,
int num_u, const FSSparseTensor &f, Journal &jr, double qz_crit)
: ypart(num_stat, num_pred, num_both, num_forw),
nu(num_u),
gy(ypart.ny(), ypart.nys()),
gu(ypart.ny(), nu),
alphar(ypart.ny() + ypart.nboth),
alphai(ypart.ny() + ypart.nboth),
beta(ypart.ny() + ypart.nboth),
alphar(ypart.ny()+ypart.nboth),
alphai(ypart.ny()+ypart.nboth),
beta(ypart.ny()+ypart.nboth),
qz_criterium(qz_crit),
journal(jr)
{
solve(FFSTensor(f));
}
[[nodiscard]] const TwoDMatrix&
const TwoDMatrix &
getGy() const
{
return gy;
}
[[nodiscard]] const TwoDMatrix&
const TwoDMatrix &
getGu() const
{
return gu;
}
protected:
void solve(const TwoDMatrix& f);
void solve(const TwoDMatrix &f);
void journalEigs();
};
@ -95,16 +93,15 @@ template<Storage t>
class FirstOrderDerivs : public ctraits<t>::Tg
{
public:
FirstOrderDerivs(const FirstOrder& fo) : ctraits<t>::Tg(4)
FirstOrderDerivs(const FirstOrder &fo)
: ctraits<t>::Tg(4)
{
IntSequence nvs {fo.ypart.nys(), fo.nu, fo.nu, 1};
auto ten = std::make_unique<typename ctraits<t>::Ttensor>(
fo.ypart.ny(), TensorDimens(Symmetry {1, 0, 0, 0}, nvs));
IntSequence nvs{fo.ypart.nys(), fo.nu, fo.nu, 1};
auto ten = std::make_unique<typename ctraits<t>::Ttensor>(fo.ypart.ny(), TensorDimens(Symmetry{1, 0, 0, 0}, nvs));
ten->zeros();
ten->add(1.0, fo.gy);
this->insert(std::move(ten));
ten = std::make_unique<typename ctraits<t>::Ttensor>(fo.ypart.ny(),
TensorDimens(Symmetry {0, 1, 0, 0}, nvs));
ten = std::make_unique<typename ctraits<t>::Ttensor>(fo.ypart.ny(), TensorDimens(Symmetry{0, 1, 0, 0}, nvs));
ten->zeros();
ten->add(1.0, fo.gu);
this->insert(std::move(ten));

View File

@ -0,0 +1,384 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "SymSchurDecomp.hh"
#include "global_check.hh"
#include "seed_generator.hh"
#include "smolyak.hh"
#include "product.hh"
#include "quasi_mcarlo.hh"
#include <utility>
#include <cmath>
/* Here we just set a reference to the approximation, and create a new
DynamicModel. */
ResidFunction::ResidFunction(const Approximation &app)
: VectorFunction(app.getModel().nexog(), app.getModel().numeq()), approx(app),
model(app.getModel().clone())
{
}
ResidFunction::ResidFunction(const ResidFunction &rf)
: VectorFunction(rf), approx(rf.approx), model(rf.model->clone())
{
if (rf.yplus)
yplus = std::make_unique<Vector>(*(rf.yplus));
if (rf.ystar)
ystar = std::make_unique<Vector>(*(rf.ystar));
if (rf.u)
u = std::make_unique<Vector>(*(rf.u));
if (rf.hss)
hss = std::make_unique<FTensorPolynomial>(*(rf.hss));
}
/* This sets y* and u. We have to create ystar, u, yplus and hss. */
void
ResidFunction::setYU(const ConstVector &ys, const ConstVector &xx)
{
ystar = std::make_unique<Vector>(ys);
u = std::make_unique<Vector>(xx);
yplus = std::make_unique<Vector>(model->numeq());
approx.getFoldDecisionRule().evaluate(DecisionRule::emethod::horner,
*yplus, *ystar, *u);
// make a tensor polynomial of in-place subtensors from decision rule
/* Note that the non-const polynomial will be used for a construction of
hss and will be used in a const context. So this const cast is safe.
Note, that there is always a folded decision rule in Approximation. */
const FoldDecisionRule &dr = approx.getFoldDecisionRule();
FTensorPolynomial dr_ss(model->nstat()+model->npred(), model->nboth()+model->nforw(),
const_cast<FoldDecisionRule &>(dr));
// make ytmp_star be a difference of yplus from steady
Vector ytmp_star(ConstVector(*yplus, model->nstat(), model->npred()+model->nboth()));
ConstVector ysteady_star(dr.getSteady(), model->nstat(),
model->npred()+model->nboth());
ytmp_star.add(-1.0, ysteady_star);
// make hss and add steady to it
/* Here is the const context of dr_ss. */
hss = std::make_unique<FTensorPolynomial>(dr_ss, ytmp_star);
ConstVector ysteady_ss(dr.getSteady(), model->nstat()+model->npred(),
model->nboth()+model->nforw());
if (hss->check(Symmetry{0}))
hss->get(Symmetry{0}).getData().add(1.0, ysteady_ss);
else
{
auto ten = std::make_unique<FFSTensor>(hss->nrows(), hss->nvars(), 0);
ten->getData() = ysteady_ss;
hss->insert(std::move(ten));
}
}
/* Here we evaluate the residual F(y*,u,u). We have to evaluate hss for
u=point and then we evaluate the system f. */
void
ResidFunction::eval(const Vector &point, const ParameterSignal &sig, Vector &out)
{
KORD_RAISE_IF(point.length() != hss->nvars(),
"Wrong dimension of input vector in ResidFunction::eval");
KORD_RAISE_IF(out.length() != model->numeq(),
"Wrong dimension of output vector in ResidFunction::eval");
Vector yss(hss->nrows());
hss->evalHorner(yss, point);
model->evaluateSystem(out, *ystar, *yplus, yss, *u);
}
/* This checks the 𝔼[F(y*,u,u)] for a given y* and u by integrating with a
given quadrature. Note that the input ys is y* not whole y. */
void
GlobalChecker::check(const Quadrature &quad, int level,
const ConstVector &ys, const ConstVector &x, Vector &out)
{
for (int ifunc = 0; ifunc < vfs.getNum(); ifunc++)
dynamic_cast<GResidFunction &>(vfs.getFunc(ifunc)).setYU(ys, x);
quad.integrate(vfs, level, out);
}
/* This method is a bulk version of GlobalChecker::check() vector code. It
decides between Smolyak and product quadrature according to max_evals
constraint.
Note that y can be either full (all endogenous variables including static
and forward looking), or just y* (state variables). The method is able to
recognize it. */
void
GlobalChecker::check(int max_evals, const ConstTwoDMatrix &y,
const ConstTwoDMatrix &x, TwoDMatrix &out)
{
JournalRecordPair pa(journal);
pa << "Checking approximation error for " << y.ncols()
<< " states with at most " << max_evals << " evaluations" << endrec;
// Decide about which type of quadrature
GaussHermite gh;
SmolyakQuadrature dummy_sq(model.nexog(), 1, gh);
int smol_evals;
int smol_level;
dummy_sq.designLevelForEvals(max_evals, smol_level, smol_evals);
ProductQuadrature dummy_pq(model.nexog(), gh);
int prod_evals;
int prod_level;
dummy_pq.designLevelForEvals(max_evals, prod_level, prod_evals);
bool take_smolyak = (smol_evals < prod_evals) && (smol_level >= prod_level-1);
std::unique_ptr<Quadrature> quad;
int lev;
// Create the quadrature and report the decision
if (take_smolyak)
{
quad = std::make_unique<SmolyakQuadrature>(model.nexog(), smol_level, gh);
lev = smol_level;
JournalRecord rec(journal);
rec << "Selected Smolyak (level,evals)=(" << smol_level << ","
<< smol_evals << ") over product (" << prod_level << ","
<< prod_evals << ")" << endrec;
}
else
{
quad = std::make_unique<ProductQuadrature>(model.nexog(), gh);
lev = prod_level;
JournalRecord rec(journal);
rec << "Selected product (level,evals)=(" << prod_level << ","
<< prod_evals << ") over Smolyak (" << smol_level << ","
<< smol_evals << ")" << endrec;
}
// Check all columns of y and x
int first_row = (y.nrows() == model.numeq()) ? model.nstat() : 0;
ConstTwoDMatrix ysmat(y, first_row, 0, model.npred()+model.nboth(), y.ncols());
for (int j = 0; j < y.ncols(); j++)
{
ConstVector yj{ysmat.getCol(j)};
ConstVector xj{x.getCol(j)};
Vector outj{out.getCol(j)};
check(*quad, lev, yj, xj, outj);
}
}
/* This method checks an error of the approximation by evaluating residual
𝔼[F(y*,u,u) | y*,u] for y* equal to the steady state, and changing u. We go
through all elements of u and vary them from mult·σ to mult·σ in m
steps. */
void
GlobalChecker::checkAlongShocksAndSave(mat_t *fd, const std::string &prefix,
int m, double mult, int max_evals)
{
JournalRecordPair pa(journal);
pa << "Calculating errors along shocks +/- "
<< mult << " std errors, granularity " << m << endrec;
// Setup y_mat of steady states for checking
TwoDMatrix y_mat(model.numeq(), 2*m*model.nexog()+1);
for (int j = 0; j < 2*m*model.nexog()+1; j++)
{
Vector yj{y_mat.getCol(j)};
yj = model.getSteady();
}
// Setup exo_mat for checking
TwoDMatrix exo_mat(model.nexog(), 2*m*model.nexog()+1);
exo_mat.zeros();
for (int ishock = 0; ishock < model.nexog(); ishock++)
{
double max_sigma = sqrt(model.getVcov().get(ishock, ishock));
for (int j = 0; j < 2*m; j++)
{
int jmult = (j < m) ? j-m : j-m+1;
exo_mat.get(ishock, 1+2*m*ishock+j) = mult*jmult*max_sigma/m;
}
}
TwoDMatrix errors(model.numeq(), 2*m*model.nexog()+1);
check(max_evals, y_mat, exo_mat, errors);
// Report errors along shock and save them
TwoDMatrix res(model.nexog(), 2*m+1);
JournalRecord rec(journal);
rec << "Shock value error" << endrec;
ConstVector err0{errors.getCol(0)};
for (int ishock = 0; ishock < model.nexog(); ishock++)
{
TwoDMatrix err_out(model.numeq(), 2*m+1);
for (int j = 0; j < 2*m+1; j++)
{
int jj;
Vector error{err_out.getCol(j)};
if (j != m)
{
if (j < m)
jj = 1 + 2*m*ishock+j;
else
jj = 1 + 2*m*ishock+j-1;
ConstVector coljj{errors.getCol(jj)};
error = coljj;
}
else
{
jj = 0;
error = err0;
}
JournalRecord rec1(journal);
std::string shockname{model.getExogNames().getName(ishock)};
shockname.resize(8, ' ');
rec1 << shockname << ' ' << exo_mat.get(ishock, jj)
<< "\t" << error.getMax() << endrec;
}
err_out.writeMat(fd, prefix + "_shock_" + model.getExogNames().getName(ishock) + "_errors");
}
}
/* This method checks errors on ellipse of endogenous states (predetermined
variables). The ellipse is shaped according to covariance matrix of
endogenous variables based on the first order approximation and scaled by
mult. The points on the ellipse are chosen as polar images of the low
discrepancy grid in a cube.
The method works as follows. First we calculate symmetric Schur factor of
covariance matrix of the states. Second we generate low discrepancy points
on the unit sphere. Third we transform the sphere with the
variance-covariance matrix factor and multiplier mult and initialize
matrix of u to zeros. Fourth we run the check() method and save the
results. */
void
GlobalChecker::checkOnEllipseAndSave(mat_t *fd, const std::string &prefix,
int m, double mult, int max_evals)
{
JournalRecordPair pa(journal);
pa << "Calculating errors at " << m
<< " ellipse points scaled by " << mult << endrec;
// Make factor of covariance of variables
/* Here we set ycovfac to the symmetric Schur decomposition factor of a
submatrix of covariances of all endogenous variables. The submatrix
corresponds to state variables (predetermined plus both). */
TwoDMatrix ycov{approx.calcYCov()};
TwoDMatrix ycovpred(const_cast<const TwoDMatrix &>(ycov), model.nstat(), model.nstat(),
model.npred()+model.nboth(), model.npred()+model.nboth());
SymSchurDecomp ssd(ycovpred);
ssd.correctDefinitness(1.e-05);
TwoDMatrix ycovfac(ycovpred.nrows(), ycovpred.ncols());
KORD_RAISE_IF(!ssd.isPositiveSemidefinite(),
"Covariance matrix of the states not positive \
semidefinite in GlobalChecker::checkOnEllipseAndSave");
ssd.getFactor(ycovfac);
// Put low discrepancy sphere points to ymat
/* Here we first calculate dimension d of the sphere, which is a number of
state variables minus one. We go through the d-dimensional cube [0,1]
by QMCarloCubeQuadrature and make a polar transformation to the sphere.
The polar transformation f can be written recursively w.r.t. the
dimension i as:
f() = [1]
cos(2πx)·f¹(x,,x)
f(x,,x) = sin(2πx)
*/
int d = model.npred()+model.nboth()-1;
TwoDMatrix ymat(model.npred()+model.nboth(), (d == 0) ? 2 : m);
if (d == 0)
{
ymat.get(0, 0) = 1;
ymat.get(0, 1) = -1;
}
else
{
int icol = 0;
ReversePerScheme ps;
QMCarloCubeQuadrature qmc(d, m, ps);
qmcpit beg = qmc.start(m);
qmcpit end = qmc.end(m);
for (qmcpit run = beg; run != end; ++run, icol++)
{
Vector ycol{ymat.getCol(icol)};
Vector x(run.point());
x.mult(2*M_PI);
ycol[0] = 1;
for (int i = 0; i < d; i++)
{
Vector subsphere(ycol, 0, i+1);
subsphere.mult(cos(x[i]));
ycol[i+1] = sin(x[i]);
}
}
}
// Transform sphere ymat and prepare umat for checking
/* Here we multiply the sphere points in ymat with the Cholesky factor to
obtain the ellipse, scale the ellipse by the given mult, and initialize
matrix of shocks umat to zero. */
TwoDMatrix umat(model.nexog(), ymat.ncols());
umat.zeros();
ymat.mult(mult);
ymat.multLeft(ycovfac);
ConstVector ys(model.getSteady(), model.nstat(),
model.npred()+model.nboth());
for (int icol = 0; icol < ymat.ncols(); icol++)
{
Vector ycol{ymat.getCol(icol)};
ycol.add(1.0, ys);
}
// Check on ellipse and save
/* Here we check the points and save the results to MAT-4 file. */
TwoDMatrix out(model.numeq(), ymat.ncols());
check(max_evals, ymat, umat, out);
ymat.writeMat(fd, prefix + "_ellipse_points");
out.writeMat(fd, prefix + "_ellipse_errors");
}
/* Here we check the errors along a simulation. We simulate, then set x to
zeros, check and save results. */
void
GlobalChecker::checkAlongSimulationAndSave(mat_t *fd, const std::string &prefix,
int m, int max_evals)
{
JournalRecordPair pa(journal);
pa << "Calculating errors at " << m
<< " simulated points" << endrec;
RandomShockRealization sr(model.getVcov(), seed_generator::get_new_seed());
TwoDMatrix y{approx.getFoldDecisionRule().simulate(DecisionRule::emethod::horner,
m, model.getSteady(), sr)};
TwoDMatrix x(model.nexog(), m);
x.zeros();
TwoDMatrix out(model.numeq(), m);
check(max_evals, y, x, out);
y.writeMat(fd, prefix + "_simul_points");
out.writeMat(fd, prefix + "_simul_errors");
}

View File

@ -0,0 +1,171 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
// Global check
/* The purpose of this file is to provide classes for checking error of
approximation. If y=g(y*,u) is an approximate solution, then we check
for the error of residuals of the system equations. Let
F(y*,u,u)=f(g**(g*(y*,u),u),g(y*,u),y*,u), then we calculate the integral:
𝔼[F(y*,u,u)]
which we want to be zero for all y* and u.
There are a few possibilities how and where the integral is evaluated.
Currently we offer the following ones:
Along shocks. The y* is set to the steady state, and u is set to zero but
one element is going from minus through plus shocks in few steps. The user
gives the scaling factor, for instance the interval [3σ,3σ] (where σ is
one standard error of the shock), and a number of steps. This is repeated
for each shock (element of the u vector).
Along simulation. Some random simulation is run, and for each realization
of y* and u along the path we evaluate the residual.
On ellipse. Let V=AA be a covariance matrix of the predetermined
variables y* based on linear approximation, then we calculate integral for
points on the ellipse { Ax | x=1 }. The points are selected by means of
low discrepancy method and polar transformation. The shock u are zeros.
Unconditional distribution.
*/
#ifndef GLOBAL_CHECK_H
#define GLOBAL_CHECK_H
#include <matio.h>
#include <memory>
#include "vector_function.hh"
#include "quadrature.hh"
#include "dynamic_model.hh"
#include "journal.hh"
#include "approximation.hh"
/* This is a class for implementing the VectorFunction interface evaluating the
residual of equations, this is F(y*,u,u)=f(g**(g*(y*,u),u),y*,u) is
written as a function of u.
When the object is constructed, one has to specify (y*,u), this is done by
the setYU() method. The object has basically two states. One is after
construction and before the call to setYU(). The second is after the call to
setYU(). We distinguish between the two states, an object in the second
state contains yplus, ystar, u, and hss.
The vector yplus is g*(y*,u). ystar is y*, and polynomial hss is
partially evaluated g**(yplus, u).
The pointer to DynamicModel is important, since the DynamicModel evaluates
the function f. When copying the object, we have to make also a copy of
DynamicModel. */
class ResidFunction : public VectorFunction
{
protected:
const Approximation &approx;
std::unique_ptr<DynamicModel> model;
std::unique_ptr<Vector> yplus, ystar, u;
std::unique_ptr<FTensorPolynomial> hss;
public:
ResidFunction(const Approximation &app);
ResidFunction(const ResidFunction &rf);
std::unique_ptr<VectorFunction>
clone() const override
{
return std::make_unique<ResidFunction>(*this);
}
void eval(const Vector &point, const ParameterSignal &sig, Vector &out) override;
void setYU(const ConstVector &ys, const ConstVector &xx);
};
/* This is a ResidFunction wrapped with GaussConverterFunction. */
class GResidFunction : public GaussConverterFunction
{
public:
GResidFunction(const Approximation &app)
: GaussConverterFunction(std::make_unique<ResidFunction>(app), app.getModel().getVcov())
{
}
std::unique_ptr<VectorFunction>
clone() const override
{
return std::make_unique<GResidFunction>(*this);
}
void
setYU(const ConstVector &ys, const ConstVector &xx)
{
dynamic_cast<ResidFunction *>(func)->setYU(ys, xx);
}
};
/* This is a class encapsulating checking algorithms. Its core routine is
check(), which calculates integral 𝔼[F(y*,u,u) | y*,u] for given
realizations of y* and u. The both are given in matrices. The methods
checking along shocks, on ellipse and anlong a simulation path, just fill
the matrices and call the core check().
The method checkUnconditionalAndSave() evaluates unconditional 𝔼[F(y,u,u)].
The object also maintains a set of GResidFunction functions vfs in order
to save (possibly expensive) copying of DynamicModels. */
class GlobalChecker
{
const Approximation &approx;
const DynamicModel &model;
Journal &journal;
GResidFunction rf;
VectorFunctionSet vfs;
public:
GlobalChecker(const Approximation &app, int n, Journal &jr)
: approx(app), model(approx.getModel()), journal(jr),
rf(approx), vfs(rf, n)
{
}
void check(int max_evals, const ConstTwoDMatrix &y,
const ConstTwoDMatrix &x, TwoDMatrix &out);
void checkAlongShocksAndSave(mat_t *fd, const std::string &prefix,
int m, double mult, int max_evals);
void checkOnEllipseAndSave(mat_t *fd, const std::string &prefix,
int m, double mult, int max_evals);
void checkAlongSimulationAndSave(mat_t *fd, const std::string &prefix,
int m, int max_evals);
void checkUnconditionalAndSave(mat_t *fd, const std::string &prefix,
int m, int max_evals);
protected:
void check(const Quadrature &quad, int level,
const ConstVector &y, const ConstVector &x, Vector &out);
};
/* Signalled resid function. Not implemented yet. todo: */
class ResidFunctionSig : public ResidFunction
{
public:
ResidFunctionSig(const Approximation &app, const Vector &ys, const Vector &xx);
};
#endif

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2004-2011 Ondra Kamenik
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019-2022 Dynare Team
*
* This file is part of Dynare.
*
@ -21,31 +21,30 @@
#include "journal.hh"
#include "kord_exception.hh"
#include <iomanip>
#include <cmath>
#include <ctime>
#include <iomanip>
#include <limits>
#include <thread>
#ifndef _WIN32
# include <cstdlib> // For getloadavg()
# include <sys/resource.h> // For getrusage()
# include <sys/time.h> // For getrusage()
# include <sys/resource.h> // For getrusage()
# include <sys/utsname.h> // For uname()
# include <cstdlib> // For getloadavg()
# include <unistd.h> // For sysconf()
# ifdef __APPLE__
# include <sys/sysctl.h>
# include <sys/types.h>
# include <sys/sysctl.h>
# endif
#else
# ifndef NOMINMAX
# define NOMINMAX // Do not define "min" and "max" macros
# define NOMINMAX // Do not define "min" and "max" macros
# endif
# include <windows.h> // For GlobalMemoryStatus()
# include <windows.h> // For GlobalMemoryStatus()
#endif
const std::chrono::time_point<std::chrono::high_resolution_clock> SystemResources::start
= std::chrono::high_resolution_clock::now();
const std::chrono::time_point<std::chrono::high_resolution_clock> SystemResources::start = std::chrono::high_resolution_clock::now();
#ifndef _WIN32
long
@ -59,11 +58,11 @@ long
SystemResources::availableMemory()
{
#if !defined(_WIN32) && !defined(__APPLE__)
return sysconf(_SC_AVPHYS_PAGES) * pageSize();
return sysconf(_SC_AVPHYS_PAGES)*pageSize();
#elif defined(__APPLE__)
unsigned long usermem = 0;
size_t len = sizeof usermem;
static int mib[2] = {CTL_HW, HW_USERMEM};
static int mib[2] = { CTL_HW, HW_USERMEM };
int retval = sysctl(mib, 2, &usermem, &len, NULL, 0);
if (retval == 0)
return static_cast<long>(usermem);
@ -84,8 +83,8 @@ SystemResources::SystemResources()
#ifndef _WIN32
struct rusage rus;
getrusage(RUSAGE_SELF, &rus);
utime = rus.ru_utime.tv_sec + rus.ru_utime.tv_usec * 1.0e-6;
stime = rus.ru_stime.tv_sec + rus.ru_stime.tv_usec * 1.0e-6;
utime = rus.ru_utime.tv_sec+rus.ru_utime.tv_usec*1.0e-6;
stime = rus.ru_stime.tv_sec+rus.ru_stime.tv_usec*1.0e-6;
idrss = rus.ru_idrss;
majflt = rus.ru_majflt * pageSize();
#else
@ -105,7 +104,7 @@ SystemResources::SystemResources()
}
void
SystemResources::diff(const SystemResources& pre)
SystemResources::diff(const SystemResources &pre)
{
utime -= pre.utime;
stime -= pre.stime;
@ -115,14 +114,14 @@ SystemResources::diff(const SystemResources& pre)
}
// JournalRecord::operator<<() symmetry code
JournalRecord&
JournalRecord::operator<<(const IntSequence& s)
JournalRecord &
JournalRecord::operator<<(const IntSequence &s)
{
operator<<('[');
for (int i = 0; i < s.size(); i++)
{
operator<<(s[i]);
if (i < s.size() - 1)
if (i < s.size()-1)
operator<<(',');
}
operator<<(']');
@ -130,49 +129,49 @@ JournalRecord::operator<<(const IntSequence& s)
}
void
JournalRecord::writeFloatTabular(std::ostream& s, double d, int width)
JournalRecord::writeFloatTabular(std::ostream &s, double d, int width)
{
// Number of digits of integer part
int intdigits = std::max(static_cast<int>(std::floor(log10(d)) + 1), 1);
int intdigits = std::max(static_cast<int>(std::floor(log10(d))+1), 1);
int prec = std::max(width - 1 - intdigits, 0);
s << std::fixed << std::setw(width) << std::setprecision(prec) << d;
}
void
JournalRecord::writePrefix(const SystemResources& f)
JournalRecord::writePrefix(const SystemResources &f)
{
constexpr double mb = 1024 * 1024;
constexpr double mb = 1024*1024;
std::ostringstream s;
s << std::setfill('0');
writeFloatTabular(s, f.elapsed, 7);
s << "" << recChar << std::setw(5) << ord << "";
writeFloatTabular(s, f.load_avg, 3);
s << "";
writeFloatTabular(s, f.mem_avail / mb, 5);
writeFloatTabular(s, f.mem_avail/mb, 5);
s << "│ │ ";
for (int i = 0; i < 2 * journal.getDepth(); i++)
for (int i = 0; i < 2*journal.getDepth(); i++)
s << ' ';
prefix = s.str();
}
void
JournalRecordPair::writePrefixForEnd(const SystemResources& f)
JournalRecordPair::writePrefixForEnd(const SystemResources &f)
{
constexpr double mb = 1024 * 1024;
constexpr double mb = 1024*1024;
SystemResources difnow;
difnow.diff(f);
std::ostringstream s;
s << std::setfill('0');
writeFloatTabular(s, f.elapsed + difnow.elapsed, 7);
writeFloatTabular(s, f.elapsed+difnow.elapsed, 7);
s << "│E" << std::setw(5) << ord << "";
writeFloatTabular(s, difnow.load_avg, 3);
s << "";
writeFloatTabular(s, difnow.mem_avail / mb, 5);
writeFloatTabular(s, difnow.mem_avail/mb, 5);
s << "";
writeFloatTabular(s, difnow.majflt / mb, 6);
writeFloatTabular(s, difnow.majflt/mb, 6);
s << "";
for (int i = 0; i < 2 * journal.getDepth(); i++)
for (int i = 0; i < 2*journal.getDepth(); i++)
s << ' ';
prefix_end = s.str();
}
@ -187,8 +186,8 @@ JournalRecordPair::~JournalRecordPair()
journal.flush();
}
JournalRecord&
endrec(JournalRecord& rec)
JournalRecord &
endrec(JournalRecord &rec)
{
rec.journal << rec.prefix;
rec.journal << rec.mes;
@ -201,15 +200,24 @@ endrec(JournalRecord& rec)
void
Journal::printHeader()
{
*this << "Dynare, version " << PACKAGE_VERSION << '\n' << '\n' << "System info: ";
*this << "Dynare++ v. " << VERSION << '\n'
<< '\n'
<< "Copyright © 2004-2011 Ondra Kamenik\n"
<< "Copyright © 2019-2020 Dynare Team\n"
<< "Dynare++ comes with ABSOLUTELY NO WARRANTY and is distributed under the GNU GPL,\n"
<< "version 3 or later (see https://www.gnu.org/licenses/gpl.html)\n"
<< "\n\n"
<< "System info: ";
#ifndef _WIN32
utsname info;
uname(&info);
*this << info.sysname << " " << info.release << " " << info.version << " " << info.machine;
*this << info.sysname << " " << info.release << " " << info.version << " "
<< info.machine;
#else
*this << "Windows";
#endif
*this << ", processors online: " << std::thread::hardware_concurrency() << "\n\nStart time: ";
*this << ", processors online: " << std::thread::hardware_concurrency()
<< "\n\nStart time: ";
std::time_t t = std::time(nullptr);
// NB: in the date/time string, we avoid using locale-specific strings (#1751)
*this << std::put_time(std::localtime(&t),

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2004 Ondra Kamenik
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019-2020 Dynare Team
*
* This file is part of Dynare.
*
@ -20,16 +20,16 @@
// Resource usage journal
#ifndef JOURNAL_HH
#define JOURNAL_HH
#ifndef JOURNAL_H
#define JOURNAL_H
#include "int_sequence.hh"
#include <chrono>
#include <fstream>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <chrono>
/* Implement static methods for accessing some system resources. An instance of
this class is a photograph of these resources at the time of instantiation. */
@ -52,23 +52,23 @@ struct SystemResources
long majflt;
SystemResources();
void diff(const SystemResources& pre);
void diff(const SystemResources &pre);
};
class Journal : public std::ofstream
{
int ord {0};
int depth {0};
int ord{0};
int depth{0};
public:
explicit Journal(const std::string& fname) : std::ofstream(fname)
explicit Journal(const std::string &fname)
: std::ofstream(fname)
{
printHeader();
}
/* Constructor that does not initialize the std::ofstream. To be used when an
on-disk journal is not wanted. */
Journal() = default;
Journal& operator=(Journal&&) = default;
Journal &operator=(Journal &&) = default;
~Journal() override
{
flush();
@ -102,64 +102,63 @@ public:
};
class JournalRecord;
JournalRecord& endrec(JournalRecord&);
JournalRecord &endrec(JournalRecord &);
class JournalRecord
{
protected:
char recChar;
int ord;
public:
Journal& journal;
Journal &journal;
std::string prefix;
std::string mes;
SystemResources flash;
using _Tfunc = JournalRecord& (*)(JournalRecord&);
using _Tfunc = JournalRecord &(*)(JournalRecord &);
explicit JournalRecord(Journal& jr, char rc = 'M') : recChar(rc), ord(jr.getOrd()), journal(jr)
explicit JournalRecord(Journal &jr, char rc = 'M')
: recChar(rc), ord(jr.getOrd()), journal(jr)
{
writePrefix(flash);
}
virtual ~JournalRecord() = default;
JournalRecord& operator<<(const IntSequence& s);
JournalRecord&
JournalRecord &operator<<(const IntSequence &s);
JournalRecord &
operator<<(_Tfunc f)
{
(*f)(*this);
return *this;
}
JournalRecord&
JournalRecord &
operator<<(char c)
{
mes += c;
return *this;
}
JournalRecord&
operator<<(const std::string& s)
JournalRecord &
operator<<(const std::string &s)
{
mes += s;
return *this;
}
JournalRecord&
JournalRecord &
operator<<(int i)
{
mes += std::to_string(i);
return *this;
}
JournalRecord&
JournalRecord &
operator<<(double d)
{
mes += std::to_string(d);
return *this;
}
protected:
void writePrefix(const SystemResources& f);
void writePrefix(const SystemResources &f);
/* Writes a floating point number as a field of exactly width characters
large. Note that the width will not be respected if the integer part is
too large. */
static void writeFloatTabular(std::ostream& s, double d, int width);
static void writeFloatTabular(std::ostream &s, double d, int width);
};
/*
@ -171,16 +170,15 @@ protected:
class JournalRecordPair : public JournalRecord
{
std::string prefix_end;
public:
explicit JournalRecordPair(Journal& jr) : JournalRecord(jr, 'S')
explicit JournalRecordPair(Journal &jr)
: JournalRecord(jr, 'S')
{
journal.incrementDepth();
}
~JournalRecordPair() override;
private:
void writePrefixForEnd(const SystemResources& f);
void writePrefixForEnd(const SystemResources &f);
};
#endif

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2005 Ondra Kamenik
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019 Dynare Team
*
* This file is part of Dynare.
*
@ -22,24 +22,24 @@
/* This is a simple code defining an exception and two convenience macros. */
#ifndef KORD_EXCEPTION_HH
#define KORD_EXCEPTION_HH
#include <iostream>
#include <string>
#include <iostream>
#define KORD_RAISE(mes) throw KordException(__FILE__, __LINE__, mes);
#ifndef KORD_EXCEPTION_H
# define KORD_EXCEPTION_H
#define KORD_RAISE_IF(expr, mes) \
if (expr) \
# define KORD_RAISE(mes) \
throw KordException(__FILE__, __LINE__, mes);
#define KORD_RAISE_X(mes, c) throw KordException(__FILE__, __LINE__, mes, c);
# define KORD_RAISE_IF(expr, mes) \
if (expr) throw KordException(__FILE__, __LINE__, mes);
#define KORD_RAISE_IF_X(expr, mes, c) \
if (expr) \
# define KORD_RAISE_X(mes, c) \
throw KordException(__FILE__, __LINE__, mes, c);
# define KORD_RAISE_IF_X(expr, mes, c) \
if (expr) throw KordException(__FILE__, __LINE__, mes, c);
class KordException
{
protected:
@ -47,10 +47,9 @@ protected:
int lnum;
std::string message;
int cd;
public:
KordException(std::string f, int l, std::string mes, int c = 255) :
fname {std::move(f)}, lnum {l}, message {std::move(mes)}, cd {c}
KordException(std::string f, int l, std::string mes, int c = 255)
: fname{std::move(f)}, lnum{l}, message{std::move(mes)}, cd{c}
{
}
virtual ~KordException() = default;
@ -59,12 +58,12 @@ public:
{
std::cout << "At " << fname << ':' << lnum << ":(" << cd << "):" << message << '\n';
}
[[nodiscard]] virtual int
virtual int
code() const
{
return cd;
}
[[nodiscard]] const std::string&
const std::string &
get_message() const
{
return message;

View File

@ -18,8 +18,8 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include "korder.hh"
#include "kord_exception.hh"
#include "korder.hh"
/* Here we set ipiv and inv members of the PLUMatrix depending on its
content. It is assumed that subclasses will call this method at the end of
@ -30,23 +30,26 @@ PLUMatrix::calcPLU()
{
lapack_int info;
lapack_int rows = nrows(), lda = ld;
inv = const_cast<const Vector&>(getData());
inv = const_cast<const Vector &>(getData());
dgetrf(&rows, &rows, inv.base(), &lda, ipiv.data(), &info);
}
/* Here we just call the LAPACK machinery to multiply by the inverse. */
void
PLUMatrix::multInv(TwoDMatrix& m) const
PLUMatrix::multInv(TwoDMatrix &m) const
{
KORD_RAISE_IF(m.nrows() != ncols(), "The matrix is not square in PLUMatrix::multInv");
KORD_RAISE_IF(m.nrows() != ncols(),
"The matrix is not square in PLUMatrix::multInv");
lapack_int info;
lapack_int lda = ld;
lapack_int mcols = m.ncols();
lapack_int mrows = m.nrows();
lapack_int ldb = m.getLD();
dgetrs("N", &mrows, &mcols, inv.base(), &lda, ipiv.data(), m.getData().base(), &ldb, &info);
KORD_RAISE_IF(info != 0, "Info!=0 in PLUMatrix::multInv");
dgetrs("N", &mrows, &mcols, inv.base(), &lda, ipiv.data(),
m.getData().base(), &ldb, &info);
KORD_RAISE_IF(info != 0,
"Info!=0 in PLUMatrix::multInv");
}
/* Here we construct the matrix A. Its dimension is ny, and it is
@ -56,17 +59,17 @@ PLUMatrix::multInv(TwoDMatrix& m) const
where the first zero spans nstat columns, and last zero spans nforw
columns. */
MatrixA::MatrixA(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatrix& gy,
const PartitionY& ypart) :
PLUMatrix(ypart.ny())
MatrixA::MatrixA(const FSSparseTensor &f, const IntSequence &ss,
const TwoDMatrix &gy, const PartitionY &ypart)
: PLUMatrix(ypart.ny())
{
zeros();
IntSequence c {1};
IntSequence c{1};
FGSTensor f_y(f, ss, c, TensorDimens(ss, c));
add(1.0, f_y);
ConstTwoDMatrix gss_ys(ypart.nstat + ypart.npred, ypart.nyss(), gy);
ConstTwoDMatrix gss_ys(ypart.nstat+ypart.npred, ypart.nyss(), gy);
c[0] = 0;
FGSTensor f_yss(f, ss, c, TensorDimens(ss, c));
TwoDMatrix sub(*this, ypart.nstat, ypart.nys());
@ -82,23 +85,23 @@ MatrixA::MatrixA(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatri
It is, in fact, the matrix A plus the third summand. The first zero in the
summand spans nstat columns, the second zero spans npred columns. */
MatrixS::MatrixS(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatrix& gy,
const PartitionY& ypart) :
PLUMatrix(ypart.ny())
MatrixS::MatrixS(const FSSparseTensor &f, const IntSequence &ss,
const TwoDMatrix &gy, const PartitionY &ypart)
: PLUMatrix(ypart.ny())
{
zeros();
IntSequence c {1};
IntSequence c{1};
FGSTensor f_y(f, ss, c, TensorDimens(ss, c));
add(1.0, f_y);
ConstTwoDMatrix gss_ys(ypart.nstat + ypart.npred, ypart.nyss(), gy);
ConstTwoDMatrix gss_ys(ypart.nstat+ypart.npred, ypart.nyss(), gy);
c[0] = 0;
FGSTensor f_yss(f, ss, c, TensorDimens(ss, c));
TwoDMatrix sub(*this, ypart.nstat, ypart.nys());
sub.multAndAdd(ConstTwoDMatrix(f_yss), gss_ys);
TwoDMatrix sub2(*this, ypart.nstat + ypart.npred, ypart.nyss());
TwoDMatrix sub2(*this, ypart.nstat+ypart.npred, ypart.nyss());
sub2.add(1.0, f_yss);
calcPLU();
@ -109,169 +112,169 @@ MatrixS::MatrixS(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatri
interesting here. */
template<>
ctraits<Storage::unfold>::Tg&
ctraits<Storage::unfold>::Tg &
KOrder::g<Storage::unfold>()
{
return _ug;
}
template<>
const ctraits<Storage::unfold>::Tg&
const ctraits<Storage::unfold>::Tg &
KOrder::g<Storage::unfold>() const
{
return _ug;
}
template<>
ctraits<Storage::fold>::Tg&
ctraits<Storage::fold>::Tg &
KOrder::g<Storage::fold>()
{
return _fg;
}
template<>
const ctraits<Storage::fold>::Tg&
const ctraits<Storage::fold>::Tg &
KOrder::g<Storage::fold>() const
{
return _fg;
}
template<>
ctraits<Storage::unfold>::Tgs&
ctraits<Storage::unfold>::Tgs &
KOrder::gs<Storage::unfold>()
{
return _ugs;
}
template<>
const ctraits<Storage::unfold>::Tgs&
const ctraits<Storage::unfold>::Tgs &
KOrder::gs<Storage::unfold>() const
{
return _ugs;
}
template<>
ctraits<Storage::fold>::Tgs&
ctraits<Storage::fold>::Tgs &
KOrder::gs<Storage::fold>()
{
return _fgs;
}
template<>
const ctraits<Storage::fold>::Tgs&
const ctraits<Storage::fold>::Tgs &
KOrder::gs<Storage::fold>() const
{
return _fgs;
}
template<>
ctraits<Storage::unfold>::Tgss&
ctraits<Storage::unfold>::Tgss &
KOrder::gss<Storage::unfold>()
{
return _ugss;
}
template<>
const ctraits<Storage::unfold>::Tgss&
const ctraits<Storage::unfold>::Tgss &
KOrder::gss<Storage::unfold>() const
{
return _ugss;
}
template<>
ctraits<Storage::fold>::Tgss&
ctraits<Storage::fold>::Tgss &
KOrder::gss<Storage::fold>()
{
return _fgss;
}
template<>
const ctraits<Storage::fold>::Tgss&
const ctraits<Storage::fold>::Tgss &
KOrder::gss<Storage::fold>() const
{
return _fgss;
}
template<>
ctraits<Storage::unfold>::TG&
ctraits<Storage::unfold>::TG &
KOrder::G<Storage::unfold>()
{
return _uG;
}
template<>
const ctraits<Storage::unfold>::TG&
const ctraits<Storage::unfold>::TG &
KOrder::G<Storage::unfold>() const
{
return _uG;
}
template<>
ctraits<Storage::fold>::TG&
ctraits<Storage::fold>::TG &
KOrder::G<Storage::fold>()
{
return _fG;
}
template<>
const ctraits<Storage::fold>::TG&
const ctraits<Storage::fold>::TG &
KOrder::G<Storage::fold>() const
{
return _fG;
}
template<>
ctraits<Storage::unfold>::TZstack&
ctraits<Storage::unfold>::TZstack &
KOrder::Zstack<Storage::unfold>()
{
return _uZstack;
}
template<>
const ctraits<Storage::unfold>::TZstack&
const ctraits<Storage::unfold>::TZstack &
KOrder::Zstack<Storage::unfold>() const
{
return _uZstack;
}
template<>
ctraits<Storage::fold>::TZstack&
ctraits<Storage::fold>::TZstack &
KOrder::Zstack<Storage::fold>()
{
return _fZstack;
}
template<>
const ctraits<Storage::fold>::TZstack&
const ctraits<Storage::fold>::TZstack &
KOrder::Zstack<Storage::fold>() const
{
return _fZstack;
}
template<>
ctraits<Storage::unfold>::TGstack&
ctraits<Storage::unfold>::TGstack &
KOrder::Gstack<Storage::unfold>()
{
return _uGstack;
}
template<>
const ctraits<Storage::unfold>::TGstack&
const ctraits<Storage::unfold>::TGstack &
KOrder::Gstack<Storage::unfold>() const
{
return _uGstack;
}
template<>
ctraits<Storage::fold>::TGstack&
ctraits<Storage::fold>::TGstack &
KOrder::Gstack<Storage::fold>()
{
return _fGstack;
}
template<>
const ctraits<Storage::fold>::TGstack&
const ctraits<Storage::fold>::TGstack &
KOrder::Gstack<Storage::fold>() const
{
return _fGstack;
}
template<>
ctraits<Storage::unfold>::Tm&
ctraits<Storage::unfold>::Tm &
KOrder::m<Storage::unfold>()
{
return _um;
}
template<>
const ctraits<Storage::unfold>::Tm&
const ctraits<Storage::unfold>::Tm &
KOrder::m<Storage::unfold>() const
{
return _um;
}
template<>
ctraits<Storage::fold>::Tm&
ctraits<Storage::fold>::Tm &
KOrder::m<Storage::fold>()
{
return _fm;
}
template<>
const ctraits<Storage::fold>::Tm&
const ctraits<Storage::fold>::Tm &
KOrder::m<Storage::fold>() const
{
return _fm;
@ -290,58 +293,56 @@ KOrder::m<Storage::fold>() const
to comply to preconditions of performStep(). */
KOrder::KOrder(int num_stat, int num_pred, int num_both, int num_forw,
const TensorContainer<FSSparseTensor>& fcont, const TwoDMatrix& gy,
const TwoDMatrix& gu, const TwoDMatrix& v, Journal& jr) :
ypart(num_stat, num_pred, num_both, num_forw),
ny(ypart.ny()),
nu(gu.ncols()),
maxk(fcont.getMaxDim()),
nvs {ypart.nys(), nu, nu, 1},
_ug(4),
_fg(4),
_ugs(4),
_fgs(4),
_ugss(4),
_fgss(4),
_uG(4),
_fG(4),
const TensorContainer<FSSparseTensor> &fcont,
const TwoDMatrix &gy, const TwoDMatrix &gu, const TwoDMatrix &v,
Journal &jr)
: ypart(num_stat, num_pred, num_both, num_forw),
ny(ypart.ny()), nu(gu.ncols()), maxk(fcont.getMaxDim()),
nvs{ypart.nys(), nu, nu, 1},
_ug(4), _fg(4), _ugs(4), _fgs(4), _ugss(4), _fgss(4),
_uG(4), _fG(4),
_uZstack(&_uG, ypart.nyss(), &_ug, ny, ypart.nys(), nu),
_fZstack(&_fG, ypart.nyss(), &_fg, ny, ypart.nys(), nu),
_uGstack(&_ugs, ypart.nys(), nu),
_fGstack(&_fgs, ypart.nys(), nu),
_um(maxk, v),
_fm(_um),
f(fcont),
matA(f.get(Symmetry {1}), _uZstack.getStackSizes(), gy, ypart),
matS(f.get(Symmetry {1}), _uZstack.getStackSizes(), gy, ypart),
matB(f.get(Symmetry {1}), _uZstack.getStackSizes()),
_um(maxk, v), _fm(_um), f(fcont),
matA(f.get(Symmetry{1}), _uZstack.getStackSizes(), gy, ypart),
matS(f.get(Symmetry{1}), _uZstack.getStackSizes(), gy, ypart),
matB(f.get(Symmetry{1}), _uZstack.getStackSizes()),
journal(jr)
{
KORD_RAISE_IF(gy.ncols() != ypart.nys(), "Wrong number of columns in gy in KOrder constructor");
KORD_RAISE_IF(v.ncols() != nu, "Wrong number of columns of Vcov in KOrder constructor");
KORD_RAISE_IF(nu != v.nrows(), "Wrong number of rows of Vcov in KOrder constructor");
KORD_RAISE_IF(maxk < 2, "Order of approximation must be at least 2 in KOrder constructor");
KORD_RAISE_IF(gy.nrows() != ypart.ny(), "Wrong number of rows in gy in KOrder constructor");
KORD_RAISE_IF(gu.nrows() != ypart.ny(), "Wrong number of rows in gu in KOrder constructor");
KORD_RAISE_IF(gu.ncols() != nu, "Wrong number of columns in gu in KOrder constructor");
KORD_RAISE_IF(gy.ncols() != ypart.nys(),
"Wrong number of columns in gy in KOrder constructor");
KORD_RAISE_IF(v.ncols() != nu,
"Wrong number of columns of Vcov in KOrder constructor");
KORD_RAISE_IF(nu != v.nrows(),
"Wrong number of rows of Vcov in KOrder constructor");
KORD_RAISE_IF(maxk < 2,
"Order of approximation must be at least 2 in KOrder constructor");
KORD_RAISE_IF(gy.nrows() != ypart.ny(),
"Wrong number of rows in gy in KOrder constructor");
KORD_RAISE_IF(gu.nrows() != ypart.ny(),
"Wrong number of rows in gu in KOrder constructor");
KORD_RAISE_IF(gu.ncols() != nu,
"Wrong number of columns in gu in KOrder constructor");
// Put g_y and gᵤ in the container
/* Note that g_σ is zero by construction and we do not insert it to the
container. We insert a new physical copies. */
auto tgy = std::make_unique<UGSTensor>(ny, TensorDimens(Symmetry {1, 0, 0, 0}, nvs));
auto tgy = std::make_unique<UGSTensor>(ny, TensorDimens(Symmetry{1, 0, 0, 0}, nvs));
tgy->getData() = gy.getData();
insertDerivative<Storage::unfold>(std::move(tgy));
auto tgu = std::make_unique<UGSTensor>(ny, TensorDimens(Symmetry {0, 1, 0, 0}, nvs));
auto tgu = std::make_unique<UGSTensor>(ny, TensorDimens(Symmetry{0, 1, 0, 0}, nvs));
tgu->getData() = gu.getData();
insertDerivative<Storage::unfold>(std::move(tgu));
// Put G_y, G_u and G_u in the container
/* Also note that since g_σ is zero, so is G_σ. */
auto tGy = faaDiBrunoG<Storage::unfold>(Symmetry {1, 0, 0, 0});
auto tGy = faaDiBrunoG<Storage::unfold>(Symmetry{1, 0, 0, 0});
G<Storage::unfold>().insert(std::move(tGy));
auto tGu = faaDiBrunoG<Storage::unfold>(Symmetry {0, 1, 0, 0});
auto tGu = faaDiBrunoG<Storage::unfold>(Symmetry{0, 1, 0, 0});
G<Storage::unfold>().insert(std::move(tGu));
auto tGup = faaDiBrunoG<Storage::unfold>(Symmetry {0, 0, 1, 0});
auto tGup = faaDiBrunoG<Storage::unfold>(Symmetry{0, 0, 1, 0});
G<Storage::unfold>().insert(std::move(tGup));
}
@ -360,16 +361,19 @@ KOrder::KOrder(int num_stat, int num_pred, int num_both, int num_forw,
template<>
void
KOrder::sylvesterSolve<Storage::unfold>(ctraits<Storage::unfold>::Ttensor& der) const
KOrder::sylvesterSolve<Storage::unfold>(ctraits<Storage::unfold>::Ttensor &der) const
{
JournalRecordPair pa(journal);
pa << "Sylvester equation for dimension = " << der.getSym()[0] << endrec;
if (ypart.nys() > 0 && ypart.nyss() > 0)
{
KORD_RAISE_IF(!der.isFinite(), "RHS of Sylverster is not finite");
TwoDMatrix gs_y(gs<Storage::unfold>().get(Symmetry {1, 0, 0, 0}));
GeneralSylvester sylv(der.getSym()[0], ny, ypart.nys(), ypart.nstat + ypart.npred,
matA.getData(), matB.getData(), gs_y.getData(), der.getData());
KORD_RAISE_IF(!der.isFinite(),
"RHS of Sylverster is not finite");
TwoDMatrix gs_y(gs<Storage::unfold>().get(Symmetry{1, 0, 0, 0}));
GeneralSylvester sylv(der.getSym()[0], ny, ypart.nys(),
ypart.nstat+ypart.npred,
matA.getData(), matB.getData(),
gs_y.getData(), der.getData());
sylv.solve();
}
else if (ypart.nys() > 0 && ypart.nyss() == 0)
@ -383,12 +387,12 @@ KOrder::sylvesterSolve<Storage::unfold>(ctraits<Storage::unfold>::Ttensor& der)
template<>
void
KOrder::sylvesterSolve<Storage::fold>(ctraits<Storage::fold>::Ttensor& der) const
KOrder::sylvesterSolve<Storage::fold>(ctraits<Storage::fold>::Ttensor &der) const
{
ctraits<Storage::unfold>::Ttensor tmp(der);
sylvesterSolve<Storage::unfold>(tmp);
ctraits<Storage::fold>::Ttensor ftmp(tmp);
der.getData() = const_cast<const Vector&>(ftmp.getData());
der.getData() = const_cast<const Vector &>(ftmp.getData());
}
void
@ -399,7 +403,7 @@ KOrder::switchToFolded()
int maxdim = g<Storage::unfold>().getMaxDim();
for (int dim = 1; dim <= maxdim; dim++)
for (auto& si : SymmetrySet(dim, 4))
for (auto &si : SymmetrySet(dim, 4))
{
if (si[2] == 0 && g<Storage::unfold>().check(si))
{

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2004 Ondra Kamenik
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019-2022 Dynare Team
*
* This file is part of Dynare.
*
@ -38,22 +38,22 @@
PartitionY, MatrixA, MatrixS and MatrixB.
*/
#ifndef KORDER_HH
#define KORDER_HH
#ifndef KORDER_H
#define KORDER_H
#include "faa_di_bruno.hh"
#include "int_sequence.hh"
#include "fs_tensor.hh"
#include "gs_tensor.hh"
#include "int_sequence.hh"
#include "journal.hh"
#include "normal_moments.hh"
#include "pascal_triangle.hh"
#include "stack_container.hh"
#include "t_container.hh"
#include "stack_container.hh"
#include "normal_moments.hh"
#include "t_polynomial.hh"
#include "faa_di_bruno.hh"
#include "journal.hh"
#include "pascal_triangle.hh"
#include "GeneralSylvester.hh"
#include "kord_exception.hh"
#include "GeneralSylvester.hh"
#include <dynlapack.h>
@ -61,11 +61,7 @@
#include <type_traits>
// The enum class passed as template parameter for many data structures
enum class Storage
{
fold,
unfold
};
enum class Storage { fold, unfold };
/* In ctraits we define a number of types. We have a type for tensor Ttensor,
and types for each pair of folded/unfolded containers used as a member in
@ -94,10 +90,8 @@ public:
using TGstack = std::conditional_t<type == Storage::fold, FoldedGContainer, UnfoldedGContainer>;
using Tm = std::conditional_t<type == Storage::fold, FNormalMoments, UNormalMoments>;
using Tpol = std::conditional_t<type == Storage::fold, FTensorPolynomial, UTensorPolynomial>;
using TZXstack
= std::conditional_t<type == Storage::fold, FoldedZXContainer, UnfoldedZXContainer>;
using TGXstack
= std::conditional_t<type == Storage::fold, FoldedGXContainer, UnfoldedGXContainer>;
using TZXstack = std::conditional_t<type == Storage::fold, FoldedZXContainer, UnfoldedZXContainer>;
using TGXstack = std::conditional_t<type == Storage::fold, FoldedGXContainer, UnfoldedGXContainer>;
};
/* The PartitionY class defines the partitioning of state variables y. The
@ -123,27 +117,27 @@ struct PartitionY
const int npred;
const int nboth;
const int nforw;
PartitionY() : PartitionY(0, 0, 0, 0)
PartitionY() : PartitionY(0,0,0,0) {}
PartitionY(int num_stat, int num_pred,
int num_both, int num_forw)
: nstat(num_stat), npred(num_pred),
nboth(num_both), nforw(num_forw)
{
}
PartitionY(int num_stat, int num_pred, int num_both, int num_forw) :
nstat(num_stat), npred(num_pred), nboth(num_both), nforw(num_forw)
{
}
[[nodiscard]] int
int
ny() const
{
return nstat + npred + nboth + nforw;
return nstat+npred+nboth+nforw;
}
[[nodiscard]] int
int
nys() const
{
return npred + nboth;
return npred+nboth;
}
[[nodiscard]] int
int
nyss() const
{
return nboth + nforw;
return nboth+nforw;
}
};
@ -157,15 +151,16 @@ struct PartitionY
class PLUMatrix : public TwoDMatrix
{
public:
PLUMatrix(int n) : TwoDMatrix(n, n), inv(nrows() * ncols()), ipiv(nrows())
PLUMatrix(int n)
: TwoDMatrix(n, n),
inv(nrows()*ncols()),
ipiv(nrows())
{
}
void multInv(TwoDMatrix& m) const;
void multInv(TwoDMatrix &m) const;
private:
Vector inv;
std::vector<lapack_int> ipiv;
protected:
void calcPLU();
};
@ -176,8 +171,8 @@ protected:
class MatrixA : public PLUMatrix
{
public:
MatrixA(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatrix& gy,
const PartitionY& ypart);
MatrixA(const FSSparseTensor &f, const IntSequence &ss,
const TwoDMatrix &gy, const PartitionY &ypart);
};
/* The class MatrixS slightly differs from MatrixA. It is used for
@ -187,8 +182,8 @@ public:
class MatrixS : public PLUMatrix
{
public:
MatrixS(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatrix& gy,
const PartitionY& ypart);
MatrixS(const FSSparseTensor &f, const IntSequence &ss,
const TwoDMatrix &gy, const PartitionY &ypart);
};
/* The B matrix is equal to [f_y**₊]. We have just a constructor. */
@ -196,8 +191,9 @@ public:
class MatrixB : public TwoDMatrix
{
public:
MatrixB(const FSSparseTensor& f, const IntSequence& ss) :
TwoDMatrix(FGSTensor(f, ss, IntSequence(1, 0), TensorDimens(ss, IntSequence(1, 0))))
MatrixB(const FSSparseTensor &f, const IntSequence &ss)
: TwoDMatrix(FGSTensor(f, ss, IntSequence(1, 0),
TensorDimens(ss, IntSequence(1, 0))))
{
}
};
@ -250,7 +246,7 @@ protected:
/* Dynamic model derivatives: just a reference to the container of sparse
tensors of the system derivatives, lives outside the class */
const TensorContainer<FSSparseTensor>& f;
const TensorContainer<FSSparseTensor> &f;
/* Matrices: matrix A, matrix S, and matrix B, see MatrixA and MatrixB class
declarations */
@ -262,46 +258,46 @@ protected:
containers. We declare template methods for accessing containers depending
on fold and unfold flag, we implement their specializations*/
template<Storage t>
typename ctraits<t>::Tg& g();
typename ctraits<t>::Tg &g();
template<Storage t>
const typename ctraits<t>::Tg& g() const;
const typename ctraits<t>::Tg &g() const;
template<Storage t>
typename ctraits<t>::Tgs& gs();
typename ctraits<t>::Tgs &gs();
template<Storage t>
const typename ctraits<t>::Tgs& gs() const;
const typename ctraits<t>::Tgs &gs() const;
template<Storage t>
typename ctraits<t>::Tgss& gss();
typename ctraits<t>::Tgss &gss();
template<Storage t>
const typename ctraits<t>::Tgss& gss() const;
const typename ctraits<t>::Tgss &gss() const;
template<Storage t>
typename ctraits<t>::TG& G();
typename ctraits<t>::TG &G();
template<Storage t>
const typename ctraits<t>::TG& G() const;
const typename ctraits<t>::TG &G() const;
template<Storage t>
typename ctraits<t>::TZstack& Zstack();
typename ctraits<t>::TZstack &Zstack();
template<Storage t>
const typename ctraits<t>::TZstack& Zstack() const;
const typename ctraits<t>::TZstack &Zstack() const;
template<Storage t>
typename ctraits<t>::TGstack& Gstack();
typename ctraits<t>::TGstack &Gstack();
template<Storage t>
const typename ctraits<t>::TGstack& Gstack() const;
const typename ctraits<t>::TGstack &Gstack() const;
template<Storage t>
typename ctraits<t>::Tm& m();
typename ctraits<t>::Tm &m();
template<Storage t>
const typename ctraits<t>::Tm& m() const;
Journal& journal;
const typename ctraits<t>::Tm &m() const;
Journal &journal;
public:
KOrder(int num_stat, int num_pred, int num_both, int num_forw,
const TensorContainer<FSSparseTensor>& fcont, const TwoDMatrix& gy, const TwoDMatrix& gu,
const TwoDMatrix& v, Journal& jr);
const TensorContainer<FSSparseTensor> &fcont,
const TwoDMatrix &gy, const TwoDMatrix &gu, const TwoDMatrix &v,
Journal &jr);
/* Performs k-order step provided that k=2 or the k1-th step has been
run, this is the core method */
@ -311,27 +307,27 @@ public:
/* Calculates residuals of all solved equations for k-order and reports their
sizes, it is runnable after k-order performStep() has been run */
template<Storage t>
[[nodiscard]] double check(int dim) const;
double check(int dim) const;
template<Storage t>
[[nodiscard]] Vector calcStochShift(int order, double sigma) const;
Vector calcStochShift(int order, double sigma) const;
void switchToFolded();
[[nodiscard]] const PartitionY&
const PartitionY &
getPartY() const
{
return ypart;
}
[[nodiscard]] const FGSContainer&
const FGSContainer &
getFoldDers() const
{
return _fg;
}
[[nodiscard]] const UGSContainer&
const UGSContainer &
getUnfoldDers() const
{
return _ug;
}
[[nodiscard]] const FGSContainer&
const FGSContainer &
getFoldDersS() const
{
return _fgs;
@ -341,7 +337,6 @@ public:
{
return i % 2 == 0;
}
protected:
/* Inserts a g derivative to the g container and also creates subtensors and
insert them to g_y* and g_y** containers */
@ -350,17 +345,17 @@ protected:
/* Solves the sylvester equation (templated fold, and unfold) */
template<Storage t>
void sylvesterSolve(typename ctraits<t>::Ttensor& der) const;
void sylvesterSolve(typename ctraits<t>::Ttensor &der) const;
/* Calculates derivatives of F by Faà Di Bruno for the sparse container of
system derivatives and Z stack container */
template<Storage t>
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoZ(const Symmetry& sym) const;
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoZ(const Symmetry &sym) const;
/* Calculates derivatives of G by Faà Di Bruno for the dense container g**
and G stack */
template<Storage t>
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoG(const Symmetry& sym) const;
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoG(const Symmetry &sym) const;
// Recovers g_y*ⁱ
template<Storage t>
@ -407,9 +402,8 @@ KOrder::insertDerivative(std::unique_ptr<typename ctraits<t>::Ttensor> der)
{
auto der_ptr = der.get();
g<t>().insert(std::move(der));
gs<t>().insert(
std::make_unique<typename ctraits<t>::Ttensor>(ypart.nstat, ypart.nys(), *der_ptr));
gss<t>().insert(std::make_unique<typename ctraits<t>::Ttensor>(ypart.nstat + ypart.npred,
gs<t>().insert(std::make_unique<typename ctraits<t>::Ttensor>(ypart.nstat, ypart.nys(), *der_ptr));
gss<t>().insert(std::make_unique<typename ctraits<t>::Ttensor>(ypart.nstat+ypart.npred,
ypart.nyss(), *der_ptr));
}
@ -423,7 +417,7 @@ KOrder::insertDerivative(std::unique_ptr<typename ctraits<t>::Ttensor> der)
template<Storage t>
std::unique_ptr<typename ctraits<t>::Ttensor>
KOrder::faaDiBrunoZ(const Symmetry& sym) const
KOrder::faaDiBrunoZ(const Symmetry &sym) const
{
JournalRecordPair pa(journal);
pa << "Faà Di Bruno Z container for " << sym << endrec;
@ -437,7 +431,7 @@ KOrder::faaDiBrunoZ(const Symmetry& sym) const
template<Storage t>
std::unique_ptr<typename ctraits<t>::Ttensor>
KOrder::faaDiBrunoG(const Symmetry& sym) const
KOrder::faaDiBrunoG(const Symmetry &sym) const
{
JournalRecordPair pa(journal);
pa << "Faà Di Bruno G container for " << sym << endrec;
@ -462,7 +456,7 @@ template<Storage t>
void
KOrder::recover_y(int i)
{
Symmetry sym {i, 0, 0, 0};
Symmetry sym{i, 0, 0, 0};
JournalRecordPair pa(journal);
pa << "Recovering symmetry " << sym << endrec;
@ -477,9 +471,9 @@ KOrder::recover_y(int i)
insertDerivative<t>(std::move(g_yi));
auto& gss_y = gss<t>().get(Symmetry {1, 0, 0, 0});
auto &gss_y = gss<t>().get(Symmetry{1, 0, 0, 0});
gs<t>().multAndAdd(gss_y, *G_yi_ptr);
auto& gss_yi = gss<t>().get(sym);
auto &gss_yi = gss<t>().get(sym);
gs<t>().multAndAdd(gss_yi, *G_yi_ptr);
}
@ -496,7 +490,7 @@ template<Storage t>
void
KOrder::recover_yu(int i, int j)
{
Symmetry sym {i, j, 0, 0};
Symmetry sym{i, j, 0, 0};
JournalRecordPair pa(journal);
pa << "Recovering symmetry " << sym << endrec;
@ -509,7 +503,7 @@ KOrder::recover_yu(int i, int j)
matA.multInv(*g_yiuj);
insertDerivative<t>(std::move(g_yiuj));
gs<t>().multAndAdd(gss<t>().get(Symmetry {1, 0, 0, 0}), *G_yiuj_ptr);
gs<t>().multAndAdd(gss<t>().get(Symmetry{1, 0, 0, 0}), *G_yiuj_ptr);
}
/* Here we solve [F_yⁱσʲ]+[Dᵢⱼ]+[Eᵢⱼ]=0 to obtain g_yⁱσʲ. We calculate
@ -529,7 +523,7 @@ template<Storage t>
void
KOrder::recover_ys(int i, int j)
{
Symmetry sym {i, 0, 0, j};
Symmetry sym{i, 0, 0, j};
JournalRecordPair pa(journal);
pa << "Recovering symmetry " << sym << endrec;
@ -561,7 +555,7 @@ KOrder::recover_ys(int i, int j)
insertDerivative<t>(std::move(g_yisj));
Gstack<t>().multAndAdd(1, gss<t>(), *G_yisj_ptr);
Gstack<t>().multAndAdd(i + j, gss<t>(), *G_yisj_ptr);
Gstack<t>().multAndAdd(i+j, gss<t>(), *G_yisj_ptr);
}
}
@ -582,7 +576,7 @@ template<Storage t>
void
KOrder::recover_yus(int i, int j, int k)
{
Symmetry sym {i, j, 0, k};
Symmetry sym{i, j, 0, k};
JournalRecordPair pa(journal);
pa << "Recovering symmetry " << sym << endrec;
@ -640,7 +634,7 @@ template<Storage t>
void
KOrder::recover_s(int i)
{
Symmetry sym {0, 0, 0, i};
Symmetry sym{0, 0, 0, i};
JournalRecordPair pa(journal);
pa << "Recovering symmetry " << sym << endrec;
@ -683,9 +677,9 @@ void
KOrder::fillG(int i, int j, int k)
{
for (int m = 1; m <= k; m++)
if (is_even(k - m))
if (is_even(k-m))
{
auto G_yiujupms = faaDiBrunoG<t>(Symmetry {i, j, m, k - m});
auto G_yiujupms = faaDiBrunoG<t>(Symmetry{i, j, m, k-m});
G<t>().insert(std::move(G_yiujupms));
}
}
@ -700,12 +694,12 @@ template<Storage t>
typename ctraits<t>::Ttensor
KOrder::calcD_ijk(int i, int j, int k) const
{
typename ctraits<t>::Ttensor res(ny, TensorDimens(Symmetry {i, j, 0, 0}, nvs));
typename ctraits<t>::Ttensor res(ny, TensorDimens(Symmetry{i, j, 0, 0}, nvs));
res.zeros();
if (is_even(k))
{
auto tmp = faaDiBrunoZ<t>(Symmetry {i, j, k, 0});
tmp->contractAndAdd(2, res, m<t>().get(Symmetry {k}));
auto tmp = faaDiBrunoZ<t>(Symmetry{i, j, k, 0});
tmp->contractAndAdd(2, res, m<t>().get(Symmetry{k}));
}
return res;
}
@ -720,13 +714,13 @@ template<Storage t>
typename ctraits<t>::Ttensor
KOrder::calcE_ijk(int i, int j, int k) const
{
typename ctraits<t>::Ttensor res(ny, TensorDimens(Symmetry {i, j, 0, 0}, nvs));
typename ctraits<t>::Ttensor res(ny, TensorDimens(Symmetry{i, j, 0, 0}, nvs));
res.zeros();
for (int n = 2; n <= k - 1; n += 2)
for (int n = 2; n <= k-1; n += 2)
{
auto tmp = faaDiBrunoZ<t>(Symmetry {i, j, n, k - n});
auto tmp = faaDiBrunoZ<t>(Symmetry{i, j, n, k-n});
tmp->mult(static_cast<double>(PascalTriangle::noverk(k, n)));
tmp->contractAndAdd(2, res, m<t>().get(Symmetry {n}));
tmp->contractAndAdd(2, res, m<t>().get(Symmetry{n}));
}
return res;
}
@ -783,24 +777,25 @@ template<Storage t>
void
KOrder::performStep(int order)
{
KORD_RAISE_IF(order - 1 != g<t>().getMaxDim(), "Wrong order for KOrder::performStep");
KORD_RAISE_IF(order-1 != g<t>().getMaxDim(),
"Wrong order for KOrder::performStep");
JournalRecordPair pa(journal);
pa << "Performing step for order = " << order << endrec;
recover_y<t>(order);
for (int i = 0; i < order; i++)
recover_yu<t>(i, order - i);
recover_yu<t>(i, order-i);
for (int j = 1; j < order; j++)
{
for (int i = j - 1; i >= 1; i--)
recover_yus<t>(order - j, i, j - i);
recover_ys<t>(order - j, j);
for (int i = j-1; i >= 1; i--)
recover_yus<t>(order-j, i, j-i);
recover_ys<t>(order-j, j);
}
for (int i = order - 1; i >= 1; i--)
recover_yus<t>(0, i, order - i);
for (int i = order-1; i >= 1; i--)
recover_yus<t>(0, i, order-i);
recover_s<t>(order);
}
@ -813,7 +808,8 @@ template<Storage t>
double
KOrder::check(int dim) const
{
KORD_RAISE_IF(dim > g<t>().getMaxDim(), "Wrong dimension for KOrder::check");
KORD_RAISE_IF(dim > g<t>().getMaxDim(),
"Wrong dimension for KOrder::check");
JournalRecordPair pa(journal);
pa << "Checking residuals for order = " << dim << endrec;
@ -822,7 +818,7 @@ KOrder::check(int dim) const
// Check for F_yⁱuʲ=0
for (int i = 0; i <= dim; i++)
{
Symmetry sym {dim - i, i, 0, 0};
Symmetry sym{dim-i, i, 0, 0};
auto r = faaDiBrunoZ<t>(sym);
double err = r->getData().getMax();
JournalRecord(journal) << "\terror for symmetry " << sym << "\tis " << err << endrec;
@ -830,14 +826,14 @@ KOrder::check(int dim) const
}
// Check for F_yⁱuʲuᵏ+Dᵢⱼₖ+Eᵢⱼₖ=0
for (auto& si : SymmetrySet(dim, 3))
for (auto &si : SymmetrySet(dim, 3))
{
int i = si[0];
int j = si[1];
int k = si[2];
if (i + j > 0 && k > 0)
if (i+j > 0 && k > 0)
{
Symmetry sym {i, j, 0, k};
Symmetry sym{i, j, 0, k};
auto r = faaDiBrunoZ<t>(sym);
auto D_ijk = calcD_ijk<t>(i, j, k);
r->add(1.0, D_ijk);
@ -850,13 +846,13 @@ KOrder::check(int dim) const
}
// Check for F_σⁱ+Dᵢ+Eᵢ=0
auto r = faaDiBrunoZ<t>(Symmetry {0, 0, 0, dim});
auto r = faaDiBrunoZ<t>(Symmetry{0, 0, 0, dim});
auto D_k = calcD_k<t>(dim);
r->add(1.0, D_k);
auto E_k = calcE_k<t>(dim);
r->add(1.0, E_k);
double err = r->getData().getMax();
Symmetry sym {0, 0, 0, dim};
Symmetry sym{0, 0, 0, dim};
JournalRecord(journal) << "\terror for symmetry " << sym << "\tis " << err << endrec;
maxerror = std::max(err, maxerror);
@ -874,7 +870,7 @@ KOrder::calcStochShift(int order, double sigma) const
if (is_even(j))
{
auto ten = calcD_k<t>(j);
res.add(std::pow(sigma, j) / jfac, ten.getData());
res.add(std::pow(sigma, j)/jfac, ten.getData());
}
return res;
}

View File

@ -23,13 +23,13 @@
/* Same as MatrixA constructor, but the submatrix gss_ys is passed
directly. */
MatrixAA::MatrixAA(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatrix& gss_ys,
const PartitionY& ypart) :
PLUMatrix(ypart.ny())
MatrixAA::MatrixAA(const FSSparseTensor &f, const IntSequence &ss,
const TwoDMatrix &gss_ys, const PartitionY &ypart)
: PLUMatrix(ypart.ny())
{
zeros();
IntSequence c {1};
IntSequence c{1};
FGSTensor f_y(f, ss, c, TensorDimens(ss, c));
add(1.0, f_y);
@ -42,180 +42,168 @@ MatrixAA::MatrixAA(const FSSparseTensor& f, const IntSequence& ss, const TwoDMat
}
// KOrderStoch folded constructor code
KOrderStoch::KOrderStoch(const PartitionY& yp, int nu, const TensorContainer<FSSparseTensor>& fcont,
const FGSContainer& hh, Journal& jr) :
nvs {yp.nys(), nu, nu, 1},
ypart(yp),
journal(jr),
_ug(4),
_fg(4),
_ugs(4),
_fgs(4),
_uG(4),
_fG(4),
_uh(nullptr),
_fh(&hh),
KOrderStoch::KOrderStoch(const PartitionY &yp, int nu,
const TensorContainer<FSSparseTensor> &fcont,
const FGSContainer &hh, Journal &jr)
: nvs{yp.nys(), nu, nu, 1}, ypart(yp), journal(jr),
_ug(4), _fg(4), _ugs(4), _fgs(4), _uG(4), _fG(4),
_uh(nullptr), _fh(&hh),
_uZstack(&_uG, ypart.nyss(), &_ug, ypart.ny(), ypart.nys(), nu),
_fZstack(&_fG, ypart.nyss(), &_fg, ypart.ny(), ypart.nys(), nu),
_uGstack(&_ugs, ypart.nys(), nu),
_fGstack(&_fgs, ypart.nys(), nu),
f(fcont),
matA(fcont.get(Symmetry {1}), _uZstack.getStackSizes(), hh.get(Symmetry {1, 0, 0, 0}), ypart)
matA(fcont.get(Symmetry{1}), _uZstack.getStackSizes(), hh.get(Symmetry{1, 0, 0, 0}),
ypart)
{
}
// KOrderStoch unfolded constructor code
KOrderStoch::KOrderStoch(const PartitionY& yp, int nu, const TensorContainer<FSSparseTensor>& fcont,
const UGSContainer& hh, Journal& jr) :
nvs {yp.nys(), nu, nu, 1},
ypart(yp),
journal(jr),
_ug(4),
_fg(4),
_ugs(4),
_fgs(4),
_uG(4),
_fG(4),
_uh(&hh),
_fh(nullptr),
KOrderStoch::KOrderStoch(const PartitionY &yp, int nu,
const TensorContainer<FSSparseTensor> &fcont,
const UGSContainer &hh, Journal &jr)
: nvs{yp.nys(), nu, nu, 1}, ypart(yp), journal(jr),
_ug(4), _fg(4), _ugs(4), _fgs(4), _uG(4), _fG(4),
_uh(&hh), _fh(nullptr),
_uZstack(&_uG, ypart.nyss(), &_ug, ypart.ny(), ypart.nys(), nu),
_fZstack(&_fG, ypart.nyss(), &_fg, ypart.ny(), ypart.nys(), nu),
_uGstack(&_ugs, ypart.nys(), nu),
_fGstack(&_fgs, ypart.nys(), nu),
f(fcont),
matA(fcont.get(Symmetry {1}), _uZstack.getStackSizes(), hh.get(Symmetry {1, 0, 0, 0}), ypart)
matA(fcont.get(Symmetry{1}), _uZstack.getStackSizes(), hh.get(Symmetry{1, 0, 0, 0}),
ypart)
{
}
// KOrderStoch convenience method specializations
template<>
ctraits<Storage::unfold>::Tg&
ctraits<Storage::unfold>::Tg &
KOrderStoch::g<Storage::unfold>()
{
return _ug;
}
template<>
const ctraits<Storage::unfold>::Tg&
const ctraits<Storage::unfold>::Tg &
KOrderStoch::g<Storage::unfold>() const
{
return _ug;
}
template<>
ctraits<Storage::fold>::Tg&
ctraits<Storage::fold>::Tg &
KOrderStoch::g<Storage::fold>()
{
return _fg;
}
template<>
const ctraits<Storage::fold>::Tg&
const ctraits<Storage::fold>::Tg &
KOrderStoch::g<Storage::fold>() const
{
return _fg;
}
template<>
ctraits<Storage::unfold>::Tgs&
ctraits<Storage::unfold>::Tgs &
KOrderStoch::gs<Storage::unfold>()
{
return _ugs;
}
template<>
const ctraits<Storage::unfold>::Tgs&
const ctraits<Storage::unfold>::Tgs &
KOrderStoch::gs<Storage::unfold>() const
{
return _ugs;
}
template<>
ctraits<Storage::fold>::Tgs&
ctraits<Storage::fold>::Tgs &
KOrderStoch::gs<Storage::fold>()
{
return _fgs;
}
template<>
const ctraits<Storage::fold>::Tgs&
const ctraits<Storage::fold>::Tgs &
KOrderStoch::gs<Storage::fold>() const
{
return _fgs;
}
template<>
const ctraits<Storage::unfold>::Tgss&
const ctraits<Storage::unfold>::Tgss &
KOrderStoch::h<Storage::unfold>() const
{
return *_uh;
}
template<>
const ctraits<Storage::fold>::Tgss&
const ctraits<Storage::fold>::Tgss &
KOrderStoch::h<Storage::fold>() const
{
return *_fh;
}
template<>
ctraits<Storage::unfold>::TG&
ctraits<Storage::unfold>::TG &
KOrderStoch::G<Storage::unfold>()
{
return _uG;
}
template<>
const ctraits<Storage::unfold>::TG&
const ctraits<Storage::unfold>::TG &
KOrderStoch::G<Storage::unfold>() const
{
return _uG;
}
template<>
ctraits<Storage::fold>::TG&
ctraits<Storage::fold>::TG &
KOrderStoch::G<Storage::fold>()
{
return _fG;
}
template<>
const ctraits<Storage::fold>::TG&
const ctraits<Storage::fold>::TG &
KOrderStoch::G<Storage::fold>() const
{
return _fG;
}
template<>
ctraits<Storage::unfold>::TZXstack&
ctraits<Storage::unfold>::TZXstack &
KOrderStoch::Zstack<Storage::unfold>()
{
return _uZstack;
}
template<>
const ctraits<Storage::unfold>::TZXstack&
const ctraits<Storage::unfold>::TZXstack &
KOrderStoch::Zstack<Storage::unfold>() const
{
return _uZstack;
}
template<>
ctraits<Storage::fold>::TZXstack&
ctraits<Storage::fold>::TZXstack &
KOrderStoch::Zstack<Storage::fold>()
{
return _fZstack;
}
template<>
const ctraits<Storage::fold>::TZXstack&
const ctraits<Storage::fold>::TZXstack &
KOrderStoch::Zstack<Storage::fold>() const
{
return _fZstack;
}
template<>
ctraits<Storage::unfold>::TGXstack&
ctraits<Storage::unfold>::TGXstack &
KOrderStoch::Gstack<Storage::unfold>()
{
return _uGstack;
}
template<>
const ctraits<Storage::unfold>::TGXstack&
const ctraits<Storage::unfold>::TGXstack &
KOrderStoch::Gstack<Storage::unfold>() const
{
return _uGstack;
}
template<>
ctraits<Storage::fold>::TGXstack&
ctraits<Storage::fold>::TGXstack &
KOrderStoch::Gstack<Storage::fold>()
{
return _fGstack;
}
template<>
const ctraits<Storage::fold>::TGXstack&
const ctraits<Storage::fold>::TGXstack &
KOrderStoch::Gstack<Storage::fold>() const
{
return _fGstack;

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2005 Ondra Kamenik
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019-2022 Dynare Team
*
* This file is part of Dynare.
*
@ -38,14 +38,11 @@
h as an extrapolation based on an approximation to g at lower σ.
*/
#ifndef KORDER_STOCH_HH
#define KORDER_STOCH_HH
#include <memory>
#include "korder.hh"
#include "faa_di_bruno.hh"
#include "journal.hh"
#include "korder.hh"
#include "pascal_triangle.hh"
/* This class is a container, which has a specialized constructor integrating
@ -55,8 +52,8 @@ template<Storage t>
class IntegDerivs : public ctraits<t>::Tgss
{
public:
IntegDerivs(int r, const IntSequence& nvs, const typename ctraits<t>::Tgss& g,
const typename ctraits<t>::Tm& mom, double at_sigma);
IntegDerivs(int r, const IntSequence &nvs, const typename ctraits<t>::Tgss &g,
const typename ctraits<t>::Tm &mom, double at_sigma);
};
/* This constructor integrates a rule (namely its g** part) with respect to
@ -105,17 +102,17 @@ public:
and this is exactly what the code does.
*/
template<Storage t>
IntegDerivs<t>::IntegDerivs(int r, const IntSequence& nvs, const typename ctraits<t>::Tgss& g,
const typename ctraits<t>::Tm& mom, double at_sigma) :
ctraits<t>::Tgss(4)
IntegDerivs<t>::IntegDerivs(int r, const IntSequence &nvs, const typename ctraits<t>::Tgss &g,
const typename ctraits<t>::Tm &mom, double at_sigma)
: ctraits<t>::Tgss(4)
{
int maxd = g.getMaxDim();
for (int d = 1; d <= maxd; d++)
{
for (int i = 0; i <= d; i++)
{
int p = d - i;
Symmetry sym {i, 0, 0, p};
int p = d-i;
Symmetry sym{i, 0, 0, p};
auto ten = std::make_unique<typename ctraits<t>::Ttensor>(r, TensorDimens(sym, nvs));
// Calculate derivative h_yⁱσ
@ -130,20 +127,20 @@ IntegDerivs<t>::IntegDerivs(int r, const IntSequence& nvs, const typename ctrait
ten->zeros();
for (int n = 0; n <= p; n++)
{
int k = p - n;
int k = p-n;
int povern = PascalTriangle::noverk(p, n);
int mfac = 1;
for (int m = 0; i + m + n + k <= maxd; m++, mfac *= m)
for (int m = 0; i+m+n+k <= maxd; m++, mfac *= m)
{
double mult = (pow(at_sigma, m) * povern) / mfac;
Symmetry sym_mn {i, m + n, 0, k};
if (m + n == 0 && g.check(sym_mn))
double mult = (pow(at_sigma, m)*povern)/mfac;
Symmetry sym_mn{i, m+n, 0, k};
if (m+n == 0 && g.check(sym_mn))
ten->add(mult, g.get(sym_mn));
if (m + n > 0 && KOrder::is_even(m + n) && g.check(sym_mn))
if (m+n > 0 && KOrder::is_even(m+n) && g.check(sym_mn))
{
typename ctraits<t>::Ttensor gtmp(g.get(sym_mn));
gtmp.mult(mult);
gtmp.contractAndAdd(1, *ten, mom.get(Symmetry {m + n}));
gtmp.contractAndAdd(1, *ten, mom.get(Symmetry{m+n}));
}
}
}
@ -163,8 +160,9 @@ template<Storage t>
class StochForwardDerivs : public ctraits<t>::Tgss
{
public:
StochForwardDerivs(const PartitionY& ypart, int nu, const typename ctraits<t>::Tgss& g,
const typename ctraits<t>::Tm& m, const Vector& ydelta, double sdelta,
StochForwardDerivs(const PartitionY &ypart, int nu,
const typename ctraits<t>::Tgss &g, const typename ctraits<t>::Tm &m,
const Vector &ydelta, double sdelta,
double at_sigma);
};
@ -183,11 +181,12 @@ public:
Recover general symmetry tensors from the (full symmetric) polynomial
*/
template<Storage t>
StochForwardDerivs<t>::StochForwardDerivs(const PartitionY& ypart, int nu,
const typename ctraits<t>::Tgss& g,
const typename ctraits<t>::Tm& m, const Vector& ydelta,
double sdelta, double at_sigma) :
ctraits<t>::Tgss(4)
StochForwardDerivs<t>::StochForwardDerivs(const PartitionY &ypart, int nu,
const typename ctraits<t>::Tgss &g,
const typename ctraits<t>::Tm &m,
const Vector &ydelta, double sdelta,
double at_sigma)
: ctraits<t>::Tgss(4)
{
int maxd = g.getMaxDim();
int r = ypart.nyss();
@ -197,21 +196,24 @@ StochForwardDerivs<t>::StochForwardDerivs(const PartitionY& ypart, int nu,
the tensors has zero dimensions for shocks, this is because we need to
y*
make easily stacks of the form σ in the next step. */
IntSequence nvs {ypart.nys(), 0, 0, 1};
IntSequence nvs{ypart.nys(), 0, 0, 1};
IntegDerivs<t> g_int(r, nvs, g, m, at_sigma);
// Make g_int_sym be full symmetric polynomial from g_int
/* Here we just form a polynomial whose unique variable corresponds to
y*
σ stack. */
typename ctraits<t>::Tpol g_int_sym(r, ypart.nys() + 1);
typename ctraits<t>::Tpol g_int_sym(r, ypart.nys()+1);
for (int d = 1; d <= maxd; d++)
{
auto ten = std::make_unique<typename ctraits<t>::Ttensym>(r, ypart.nys() + 1, d);
auto ten = std::make_unique<typename ctraits<t>::Ttensym>(r, ypart.nys()+1, d);
ten->zeros();
for (int i = 0; i <= d; i++)
if (int k {d - i}; g_int.check(Symmetry {i, 0, 0, k}))
ten->addSubTensor(g_int.get(Symmetry {i, 0, 0, k}));
{
int k = d-i;
if (g_int.check(Symmetry{i, 0, 0, k}))
ten->addSubTensor(g_int.get(Symmetry{i, 0, 0, k}));
}
g_int_sym.insert(std::move(ten));
}
@ -220,15 +222,15 @@ StochForwardDerivs<t>::StochForwardDerivs(const PartitionY& ypart, int nu,
was centralized about (,σ~). This is done by derivating and evaluating
the derivated polynomial at (ȳ,σ¯-σ~). The stack of this vector is
delta in the code. */
Vector delta(ypart.nys() + 1);
Vector delta(ypart.nys()+1);
Vector dy(delta, 0, ypart.nys());
ConstVector dy_in(ydelta, ypart.nstat, ypart.nys());
dy = dy_in;
delta[ypart.nys()] = sdelta;
typename ctraits<t>::Tpol g_int_cent(r, ypart.nys() + 1);
typename ctraits<t>::Tpol g_int_cent(r, ypart.nys()+1);
for (int d = 1; d <= maxd; d++)
{
g_int_sym.derivative(d - 1);
g_int_sym.derivative(d-1);
auto der = g_int_sym.evalPartially(d, delta);
g_int_cent.insert(std::move(der));
}
@ -236,19 +238,20 @@ StochForwardDerivs<t>::StochForwardDerivs(const PartitionY& ypart, int nu,
// Pull out general symmetry tensors from g_int_cent
/* Here we only recover the general symmetry derivatives from the full
symmetric polynomial. Note that the derivative get the true nvs. */
IntSequence ss {ypart.nys(), 0, 0, 1};
IntSequence pp {0, 1, 2, 3};
IntSequence ss{ypart.nys(), 0, 0, 1};
IntSequence pp{0, 1, 2, 3};
IntSequence true_nvs(nvs);
true_nvs[1] = nu;
true_nvs[2] = nu;
for (int d = 1; d <= maxd; d++)
if (g_int_cent.check(Symmetry {d}))
if (g_int_cent.check(Symmetry{d}))
for (int i = 0; i <= d; i++)
{
Symmetry sym {i, 0, 0, d - i};
Symmetry sym{i, 0, 0, d-i};
IntSequence coor(pp.unfold(sym));
auto ten = std::make_unique<typename ctraits<t>::Ttensor>(
g_int_cent.get(Symmetry {d}), ss, coor, TensorDimens(sym, true_nvs));
auto ten = std::make_unique<typename ctraits<t>::Ttensor>(g_int_cent.get(Symmetry{d}),
ss, coor,
TensorDimens(sym, true_nvs));
this->insert(std::move(ten));
}
}
@ -264,10 +267,11 @@ public:
using _Stype = StackContainerInterface<_Ttype>;
using _Ctype = typename StackContainer<_Ttype>::_Ctype;
using itype = typename StackContainer<_Ttype>::itype;
GXContainer(const _Ctype* gs, int ngs, int nu) : GContainer<_Ttype>(gs, ngs, nu)
GXContainer(const _Ctype *gs, int ngs, int nu)
: GContainer<_Ttype>(gs, ngs, nu)
{
}
itype getType(int i, const Symmetry& s) const override;
itype getType(int i, const Symmetry &s) const override;
};
/* This routine corresponds to this stack:
@ -278,26 +282,22 @@ public:
*/
template<class _Ttype>
typename GXContainer<_Ttype>::itype
GXContainer<_Ttype>::getType(int i, const Symmetry& s) const
GXContainer<_Ttype>::getType(int i, const Symmetry &s) const
{
if (i == 0)
{
if (s[2] > 0)
return itype::zero;
else
return itype::matrix;
}
if (s[2] > 0)
return itype::zero;
else
return itype::matrix;
if (i == 1)
return itype::zero;
if (i == 2)
return itype::zero;
if (i == 3)
{
if (s == Symmetry {0, 0, 0, 1})
return itype::unit;
else
return itype::zero;
}
if (s == Symmetry{0, 0, 0, 1})
return itype::unit;
else
return itype::zero;
KORD_RAISE("Wrong stack index in GXContainer::getType");
}
@ -313,11 +313,11 @@ public:
using _Stype = StackContainerInterface<_Ttype>;
using _Ctype = typename StackContainer<_Ttype>::_Ctype;
using itype = typename StackContainer<_Ttype>::itype;
ZXContainer(const _Ctype* gss, int ngss, const _Ctype* g, int ng, int ny, int nu) :
ZContainer<_Ttype>(gss, ngss, g, ng, ny, nu)
ZXContainer(const _Ctype *gss, int ngss, const _Ctype *g, int ng, int ny, int nu)
: ZContainer<_Ttype>(gss, ngss, g, ng, ny, nu)
{
}
itype getType(int i, const Symmetry& s) const override;
itype getType(int i, const Symmetry &s) const override;
};
/* This getType() method corresponds to this stack:
@ -328,36 +328,28 @@ public:
*/
template<class _Ttype>
typename ZXContainer<_Ttype>::itype
ZXContainer<_Ttype>::getType(int i, const Symmetry& s) const
ZXContainer<_Ttype>::getType(int i, const Symmetry &s) const
{
if (i == 0)
{
if (s[2] > 0)
return itype::zero;
else
return itype::matrix;
}
if (s[2] > 0)
return itype::zero;
else
return itype::matrix;
if (i == 1)
{
if (s[2] > 0)
return itype::zero;
else
return itype::matrix;
}
if (s[2] > 0)
return itype::zero;
else
return itype::matrix;
if (i == 2)
{
if (s == Symmetry {1, 0, 0, 0})
return itype::unit;
else
return itype::zero;
}
if (s == Symmetry{1, 0, 0, 0})
return itype::unit;
else
return itype::zero;
if (i == 3)
{
if (s == Symmetry {0, 1, 0, 0})
return itype::unit;
else
return itype::zero;
}
if (s == Symmetry{0, 1, 0, 0})
return itype::unit;
else
return itype::zero;
KORD_RAISE("Wrong stack index in ZXContainer::getType");
}
@ -366,7 +358,8 @@ class UnfoldedGXContainer : public GXContainer<UGSTensor>, public UnfoldedStackC
{
public:
using _Ctype = TensorContainer<UGSTensor>;
UnfoldedGXContainer(const _Ctype* gs, int ngs, int nu) : GXContainer<UGSTensor>(gs, ngs, nu)
UnfoldedGXContainer(const _Ctype *gs, int ngs, int nu)
: GXContainer<UGSTensor>(gs, ngs, nu)
{
}
};
@ -375,7 +368,8 @@ class FoldedGXContainer : public GXContainer<FGSTensor>, public FoldedStackConta
{
public:
using _Ctype = TensorContainer<FGSTensor>;
FoldedGXContainer(const _Ctype* gs, int ngs, int nu) : GXContainer<FGSTensor>(gs, ngs, nu)
FoldedGXContainer(const _Ctype *gs, int ngs, int nu)
: GXContainer<FGSTensor>(gs, ngs, nu)
{
}
};
@ -384,8 +378,8 @@ class UnfoldedZXContainer : public ZXContainer<UGSTensor>, public UnfoldedStackC
{
public:
using _Ctype = TensorContainer<UGSTensor>;
UnfoldedZXContainer(const _Ctype* gss, int ngss, const _Ctype* g, int ng, int ny, int nu) :
ZXContainer<UGSTensor>(gss, ngss, g, ng, ny, nu)
UnfoldedZXContainer(const _Ctype *gss, int ngss, const _Ctype *g, int ng, int ny, int nu)
: ZXContainer<UGSTensor>(gss, ngss, g, ng, ny, nu)
{
}
};
@ -394,8 +388,8 @@ class FoldedZXContainer : public ZXContainer<FGSTensor>, public FoldedStackConta
{
public:
using _Ctype = TensorContainer<FGSTensor>;
FoldedZXContainer(const _Ctype* gss, int ngss, const _Ctype* g, int ng, int ny, int nu) :
ZXContainer<FGSTensor>(gss, ngss, g, ng, ny, nu)
FoldedZXContainer(const _Ctype *gss, int ngss, const _Ctype *g, int ng, int ny, int nu)
: ZXContainer<FGSTensor>(gss, ngss, g, ng, ny, nu)
{
}
};
@ -411,8 +405,8 @@ public:
class MatrixAA : public PLUMatrix
{
public:
MatrixAA(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatrix& gyss,
const PartitionY& ypart);
MatrixAA(const FSSparseTensor &f, const IntSequence &ss,
const TwoDMatrix &gyss, const PartitionY &ypart);
};
/* This class calculates derivatives of g given implicitly by
@ -432,79 +426,77 @@ class KOrderStoch
protected:
IntSequence nvs;
PartitionY ypart;
Journal& journal;
Journal &journal;
UGSContainer _ug;
FGSContainer _fg;
UGSContainer _ugs;
FGSContainer _fgs;
UGSContainer _uG;
FGSContainer _fG;
const UGSContainer* _uh;
const FGSContainer* _fh;
const UGSContainer *_uh;
const FGSContainer *_fh;
UnfoldedZXContainer _uZstack;
FoldedZXContainer _fZstack;
UnfoldedGXContainer _uGstack;
FoldedGXContainer _fGstack;
const TensorContainer<FSSparseTensor>& f;
const TensorContainer<FSSparseTensor> &f;
MatrixAA matA;
public:
KOrderStoch(const PartitionY& ypart, int nu, const TensorContainer<FSSparseTensor>& fcont,
const FGSContainer& hh, Journal& jr);
KOrderStoch(const PartitionY& ypart, int nu, const TensorContainer<FSSparseTensor>& fcont,
const UGSContainer& hh, Journal& jr);
KOrderStoch(const PartitionY &ypart, int nu, const TensorContainer<FSSparseTensor> &fcont,
const FGSContainer &hh, Journal &jr);
KOrderStoch(const PartitionY &ypart, int nu, const TensorContainer<FSSparseTensor> &fcont,
const UGSContainer &hh, Journal &jr);
template<Storage t>
void performStep(int order);
[[nodiscard]] const FGSContainer&
const FGSContainer &
getFoldDers() const
{
return _fg;
}
[[nodiscard]] const UGSContainer&
const UGSContainer &
getUnfoldDers() const
{
return _ug;
}
[[nodiscard]] const FGSContainer&
const FGSContainer &
getFoldDersS() const
{
return _fgs;
}
protected:
template<Storage t>
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoZ(const Symmetry& sym) const;
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoZ(const Symmetry &sym) const;
template<Storage t>
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoG(const Symmetry& sym) const;
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoG(const Symmetry &sym) const;
// Convenience access methods
template<Storage t>
typename ctraits<t>::Tg& g();
typename ctraits<t>::Tg &g();
template<Storage t>
const typename ctraits<t>::Tg& g() const;
const typename ctraits<t>::Tg &g() const;
template<Storage t>
typename ctraits<t>::Tgs& gs();
typename ctraits<t>::Tgs &gs();
template<Storage t>
const typename ctraits<t>::Tgs& gs() const;
const typename ctraits<t>::Tgs &gs() const;
template<Storage t>
const typename ctraits<t>::Tgss& h() const;
const typename ctraits<t>::Tgss &h() const;
template<Storage t>
typename ctraits<t>::TG& G();
typename ctraits<t>::TG &G();
template<Storage t>
const typename ctraits<t>::TG& G() const;
const typename ctraits<t>::TG &G() const;
template<Storage t>
typename ctraits<t>::TZXstack& Zstack();
typename ctraits<t>::TZXstack &Zstack();
template<Storage t>
const typename ctraits<t>::TZXstack& Zstack() const;
const typename ctraits<t>::TZXstack &Zstack() const;
template<Storage t>
typename ctraits<t>::TGXstack& Gstack();
typename ctraits<t>::TGXstack &Gstack();
template<Storage t>
const typename ctraits<t>::TGXstack& Gstack() const;
const typename ctraits<t>::TGXstack &Gstack() const;
};
/* This calculates a derivative of f(G(y,u,σ),g(y,u,σ),y,u) of a given
@ -512,7 +504,7 @@ protected:
template<Storage t>
std::unique_ptr<typename ctraits<t>::Ttensor>
KOrderStoch::faaDiBrunoZ(const Symmetry& sym) const
KOrderStoch::faaDiBrunoZ(const Symmetry &sym) const
{
JournalRecordPair pa(journal);
pa << "Faà Di Bruno ZX container for " << sym << endrec;
@ -527,7 +519,7 @@ KOrderStoch::faaDiBrunoZ(const Symmetry& sym) const
template<Storage t>
std::unique_ptr<typename ctraits<t>::Ttensor>
KOrderStoch::faaDiBrunoG(const Symmetry& sym) const
KOrderStoch::faaDiBrunoG(const Symmetry &sym) const
{
JournalRecordPair pa(journal);
pa << "Faà Di Bruno GX container for " << sym << endrec;
@ -553,9 +545,9 @@ void
KOrderStoch::performStep(int order)
{
int maxd = g<t>().getMaxDim();
KORD_RAISE_IF(order - 1 != maxd && (order != 1 || maxd != -1),
KORD_RAISE_IF(order-1 != maxd && (order != 1 || maxd != -1),
"Wrong order for KOrderStoch::performStep");
for (auto& si : SymmetrySet(order, 4))
for (auto &si : SymmetrySet(order, 4))
if (si[2] == 0)
{
JournalRecordPair pa(journal);
@ -570,11 +562,9 @@ KOrderStoch::performStep(int order)
g_sym->mult(-1.0);
matA.multInv(*g_sym);
g<t>().insert(std::move(g_sym));
gs<t>().insert(
std::make_unique<typename ctraits<t>::Ttensor>(ypart.nstat, ypart.nys(), *g_sym_ptr));
gs<t>().insert(std::make_unique<typename ctraits<t>::Ttensor>(ypart.nstat, ypart.nys(),
*g_sym_ptr));
Gstack<t>().multAndAdd(1, h<t>(), *G_sym_ptr);
}
}
#endif

View File

@ -0,0 +1,123 @@
/*
* Copyright © 2007 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 <https://www.gnu.org/licenses/>.
*/
#include "normal_conjugate.hh"
#include "kord_exception.hh"
// NormalConj diffuse prior constructor
NormalConj::NormalConj(int d)
: mu(d), kappa(0), nu(-1), lambda(d, d)
{
mu.zeros();
lambda.zeros();
}
// NormalConj data update constructor
NormalConj::NormalConj(const ConstTwoDMatrix &ydata)
: mu(ydata.nrows()), kappa(ydata.ncols()), nu(ydata.ncols()-1),
lambda(ydata.nrows(), ydata.nrows())
{
mu.zeros();
for (int i = 0; i < ydata.ncols(); i++)
mu.add(1.0/ydata.ncols(), ydata.getCol(i));
lambda.zeros();
for (int i = 0; i < ydata.ncols(); i++)
{
Vector diff{ydata.getCol(i)};
diff.add(-1, mu);
lambda.addOuter(diff);
}
}
// NormalConj::update() one observation code
/* The method performs the following:
κ 1
μ = μ + y
κ+1 κ+1
κ = κ + 1
ν = ν + 1
κ
Λ = Λ + (y μ)(y μ)
κ+1
*/
void
NormalConj::update(const ConstVector &y)
{
KORD_RAISE_IF(y.length() != mu.length(),
"Wrong length of a vector in NormalConj::update");
mu.mult(kappa/(1.0+kappa));
mu.add(1.0/(1.0+kappa), y);
Vector diff(y);
diff.add(-1, mu);
lambda.addOuter(diff, kappa/(1.0+kappa));
kappa++;
nu++;
}
// NormalConj::update() multiple observations code
/* The method evaluates the formula in the header file. */
void
NormalConj::update(const ConstTwoDMatrix &ydata)
{
NormalConj nc(ydata);
update(nc);
}
// NormalConj::update() with NormalConj code
void
NormalConj::update(const NormalConj &nc)
{
double wold = static_cast<double>(kappa)/(kappa+nc.kappa);
double wnew = 1-wold;
mu.mult(wold);
mu.add(wnew, nc.mu);
Vector diff(nc.mu);
diff.add(-1, mu);
lambda.add(1.0, nc.lambda);
lambda.addOuter(diff);
kappa = kappa + nc.kappa;
nu = nu + nc.kappa;
}
/* This returns 1/(νd1)·Λ, which is the mean of the variance in the posterior
distribution. If the number of degrees of freedom is less than d, then NaNs
are returned. */
void
NormalConj::getVariance(TwoDMatrix &v) const
{
if (nu > getDim()+1)
{
v = const_cast<const TwoDMatrix &>(lambda);
v.mult(1.0/(nu-getDim()-1));
}
else
v.nans();
}

View File

@ -0,0 +1,105 @@
/*
* Copyright © 2007 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 <https://www.gnu.org/licenses/>.
*/
// Conjugate family for normal distribution
/* The main purpose here is to implement a class representing conjugate
distributions for mean and variance of the normal distribution. The class
has two main methods: the first one is to update itself with respect to one
observation, the second one is to update itself with respect to anothe
object of the class. In the both methods, the previous state of the class
corresponds to the prior distribution, and the final state corresponds to
the posterior distribution.
The algebra can be found in Gelman, Carlin, Stern, Rubin (p.87). It goes as
follows. Prior conjugate distribution takes the following form:
Σ InvWishart_ν(Λ¹)
μ|Σ 𝒩(μ,Σ/κ)
If the observations are yy, then the posterior distribution has the same
form with the following parameters:
κ n
μ = μ + ȳ
κ+n κ+n
κ = κ + n
ν = ν + n
κ·n
Λ = Λ + S + (ȳ μ)(ȳ μ)
κ+n
where
1
ȳ = y
n ¹
S = (y ȳ)(y ȳ)
¹
*/
#ifndef NORMAL_CONJUGATE_H
#define NORMAL_CONJUGATE_H
#include "twod_matrix.hh"
/* The class is described by the four parameters: μ, κ, ν and Λ. */
class NormalConj
{
protected:
Vector mu;
int kappa;
int nu;
TwoDMatrix lambda;
public:
/* We provide the following constructors: The first constructs diffuse
(Jeffreys) prior. It sets κ and Λ to zeros, ν to 1 and also the mean μ
to zero (it should not be referenced). The second constructs the posterior
using the diffuse prior and the observed data (columnwise). The third is a
copy constructor. */
NormalConj(int d);
NormalConj(const ConstTwoDMatrix &ydata);
NormalConj(const NormalConj &) = default;
NormalConj(NormalConj &&) = default;
virtual ~NormalConj() = default;
void update(const ConstVector &y);
void update(const ConstTwoDMatrix &ydata);
void update(const NormalConj &nc);
int
getDim() const
{
return mu.length();
}
const Vector &
getMean() const
{
return mu;
}
void getVariance(TwoDMatrix &v) const;
};
#endif

View File

@ -0,0 +1,47 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "seed_generator.hh"
#include <limits>
#include <mutex>
namespace seed_generator
{
std::mutex mut;
std::mt19937 rng;
std::uniform_int_distribution<std::mt19937::result_type> seed_generator(std::numeric_limits<std::mt19937::result_type>::min(),
std::numeric_limits<std::mt19937::result_type>::max());
std::mt19937::result_type
get_new_seed()
{
std::lock_guard<std::mutex> lk{mut};
return seed_generator(rng);
}
void
set_meta_seed(std::mt19937::result_type s)
{
std::lock_guard<std::mutex> lk{mut};
rng.seed(s);
}
};

View File

@ -1,5 +1,4 @@
/*
* Copyright © 2005 Ondra Kamenik
* Copyright © 2019 Dynare Team
*
* This file is part of Dynare.
@ -18,14 +17,18 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include "dynamic_model.hh"
#ifndef RANDOM_H
#define RANDOM_H
#include <algorithm>
#include <iostream>
#include <random>
void
NameList::print() const
namespace seed_generator
{
for (int i = 0; i < getNum(); i++)
std::cout << getName(i) << '\n';
}
// Produces seeds that can be used with Mersenne-Twister generators (thread-safe)
std::mt19937::result_type get_new_seed();
// Sets the seed for the seed generator (!)
void set_meta_seed(std::mt19937::result_type s);
};
#endif

487
dynare++/kord/tests.cc Normal file
View File

@ -0,0 +1,487 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
#include <chrono>
#include <random>
#include <string>
#include <utility>
#include <iostream>
#include <iomanip>
#include <vector>
#include <memory>
#include "korder.hh"
#include "SylvException.hh"
struct Rand
{
static std::mt19937 mtgen;
static std::uniform_real_distribution<> dis;
static void init(int n1, int n2, int n3, int n4, int n5);
static double get(double m);
static int get(int m);
static bool discrete(double prob); // answers true with given probability
};
std::mt19937 Rand::mtgen;
std::uniform_real_distribution<> Rand::dis;
ConstTwoDMatrix
make_matrix(int rows, int cols, const double *p)
{
return ConstTwoDMatrix{rows, cols, ConstVector{p, rows*cols}};
}
void
Rand::init(int n1, int n2, int n3, int n4, int n5)
{
decltype(mtgen)::result_type seed = n1;
seed = 256*seed+n2;
seed = 256*seed+n3;
seed = 256*seed+n4;
seed = 256*seed+n5;
mtgen.seed(seed);
}
double
Rand::get(double m)
{
return 2*m*(dis(mtgen)-0.5);
}
int
Rand::get(int m)
{
return static_cast<int>(get(0.9999*m));
}
bool
Rand::discrete(double prob)
{
return dis(mtgen) < prob;
}
struct SparseGenerator
{
static std::unique_ptr<FSSparseTensor> makeTensor(int dim, int nv, int r,
double fill, double m);
static void fillContainer(TensorContainer<FSSparseTensor> &c,
int maxdim, int nv, int r, double m);
};
std::unique_ptr<FSSparseTensor>
SparseGenerator::makeTensor(int dim, int nv, int r,
double fill, double m)
{
auto res = std::make_unique<FSSparseTensor>(dim, nv, r);
FFSTensor dummy(0, nv, dim);
for (Tensor::index fi = dummy.begin(); fi != dummy.end(); ++fi)
for (int i = 0; i < r; i++)
if (Rand::discrete(fill))
{
double x = Rand::get(m);
res->insert(fi.getCoor(), i, x);
}
return res;
}
void
SparseGenerator::fillContainer(TensorContainer<FSSparseTensor> &c,
int maxdim, int nv, int r,
double m)
{
Rand::init(maxdim, nv, r, static_cast<int>(5*m), 0);
double fill = 0.5;
for (int d = 1; d <= maxdim; d++)
{
c.insert(makeTensor(d, nv, r, fill, m));
fill *= 0.3;
}
}
const double vdata[] =
{ // 3x3
0.1307870268, 0.1241940078, 0.1356703123,
0.1241940078, 0.1986920419, 0.2010160581,
0.1356703123, 0.2010160581, 0.2160336975
};
const double gy_data[] =
{ // 8x4
0.3985178619, -0.5688233582, 0.9572900437, -0.6606847776, 0.1453004017,
0.3025310675, -0.8627437750, -0.6903410191, 0.4751910580, -0.7270018589,
-0.0939612498, -0.1463831989, 0.6742110220, 0.6046671043, 0.5215893126,
-1.0412969986, -0.3524898417, -1.0986703430, 0.8006531522, 0.8879776376,
-0.1037608317, -0.5587378073, -0.1010366945, 0.9462411248, -0.2439199881,
1.3420621236, -0.7820285935, 0.3205293447, 0.3606124791, 0.2975422208,
-0.5452861965, 1.6320340279
};
const double gu_data[] =
{ // just some numbers, no structure
1.8415286914, -0.2638743845, 1.7690713274, 0.9668585956, 0.2303143646,
-0.2229624279, -0.4381991822, 1.0082401405, -0.3186555860, -0.0624691529,
-0.5189085756, 1.4269672156, 0.1163282969, 1.4020183445, -0.0952660426,
0.2099097124, 0.6912400502, -0.5180935114, 0.5288316624, 0.2188053448,
0.5715516767, 0.7813893410, -0.6385073106, 0.8335131513, 0.3605202168,
-1.1167944865, -1.2263750934, 0.6113636081, 0.6964915482, -0.6451217688,
0.4062810500, -2.0552251116, -1.6383406284, 0.0198915095, 0.0111014458,
-1.2421792262, -1.0724161722, -0.4276904972, 0.1801494950, -2.0716473264
};
const double vdata2[] =
{ // 10×10 positive definite
0.79666, -0.15536, 0.05667, -0.21026, 0.20262, 0.28505, 0.60341, -0.09703, 0.32363, 0.13299,
-0.15536, 0.64380, -0.01131, 0.00980, 0.03755, 0.43791, 0.21784, -0.31755, -0.55911, -0.29655,
0.05667, -0.01131, 0.56165, -0.34357, -0.40584, 0.20990, 0.28348, 0.20398, -0.19856, 0.35820,
-0.21026, 0.00980, -0.34357, 0.56147, 0.10972, -0.34146, -0.49906, -0.19685, 0.21088, -0.31560,
0.20262, 0.03755, -0.40584, 0.10972, 0.72278, 0.02155, 0.04089, -0.19696, 0.03446, -0.12919,
0.28505, 0.43791, 0.20990, -0.34146, 0.02155, 0.75867, 0.77699, -0.31125, -0.55141, -0.02155,
0.60341, 0.21784, 0.28348, -0.49906, 0.04089, 0.77699, 1.34553, -0.18613, -0.25811, -0.19016,
-0.09703, -0.31755, 0.20398, -0.19685, -0.19696, -0.31125, -0.18613, 0.59470, 0.08386, 0.41750,
0.32363, -0.55911, -0.19856, 0.21088, 0.03446, -0.55141, -0.25811, 0.08386, 0.98917, -0.12992,
0.13299, -0.29655, 0.35820, -0.31560, -0.12919, -0.02155, -0.19016, 0.41750, -0.12992, 0.89608
};
const double gy_data2[] =
{ // 600 items make gy 30×20, whose gy(6:25,:) has spectrum within unit
0.39414, -0.29766, 0.08948, -0.19204, -0.00750, 0.21159, 0.05494, 0.06225, 0.01771, 0.21913,
-0.01373, 0.20086, -0.06086, -0.10955, 0.14424, -0.08390, 0.03948, -0.14713, 0.11674, 0.05091,
0.24039, 0.28307, -0.11835, 0.13030, 0.11682, -0.27444, -0.19311, -0.16654, 0.12867, 0.25116,
-0.19781, 0.45242, -0.15862, 0.24428, -0.11966, 0.11483, -0.32279, 0.29727, 0.20934, -0.18190,
-0.15080, -0.09477, -0.30551, -0.02672, -0.26919, 0.11165, -0.06390, 0.03449, -0.26622, 0.22197,
0.45141, -0.41683, 0.09760, 0.31094, -0.01652, 0.05809, -0.04514, -0.05645, 0.00554, 0.47980,
0.11726, 0.42459, -0.13136, -0.30902, -0.14648, 0.11455, 0.02947, -0.03835, -0.04044, 0.03559,
-0.26575, -0.01783, 0.31243, -0.14412, -0.13218, -0.05080, 0.18576, 0.13840, -0.05560, 0.35530,
-0.25573, -0.11560, 0.15187, -0.18431, 0.08193, -0.32278, 0.17560, -0.05529, -0.10020, -0.23088,
-0.20979, -0.49245, 0.09915, -0.16909, -0.03443, 0.19497, 0.18473, 0.25662, 0.29605, -0.20531,
-0.39244, -0.43369, 0.05588, 0.24823, -0.14236, -0.08311, 0.16371, -0.19975, 0.30605, -0.17087,
-0.01270, 0.00123, -0.22426, -0.13810, 0.05079, 0.06971, 0.01922, -0.09952, -0.23177, -0.41962,
-0.41991, 0.41430, -0.04247, -0.13706, -0.12048, -0.28906, -0.22813, -0.25057, -0.18579, -0.20642,
-0.47976, 0.25490, -0.05138, -0.30794, 0.31651, 0.02034, 0.12954, -0.20110, 0.13336, -0.40775,
-0.30195, -0.13704, 0.12396, 0.28152, 0.02986, 0.27669, 0.24623, 0.08635, -0.11956, -0.02949,
0.37401, 0.20838, 0.24801, -0.26872, 0.11195, 0.00315, -0.19069, 0.12839, -0.23036, -0.48228,
0.08434, -0.39872, -0.28896, -0.28754, 0.24668, 0.23285, 0.25437, 0.10456, -0.14124, 0.20483,
-0.19117, -0.33836, -0.24875, 0.08207, -0.03930, 0.20364, 0.15384, -0.15270, 0.24372, -0.11199,
-0.46591, 0.30319, 0.05745, 0.09084, 0.06058, 0.31884, 0.05071, -0.28899, -0.30793, -0.03566,
0.02286, 0.28178, 0.00736, -0.31378, -0.18144, -0.22346, -0.27239, 0.31043, -0.26228, 0.22181,
-0.15096, -0.36953, -0.06032, 0.21496, 0.29545, -0.13112, 0.16420, -0.07573, -0.43111, -0.43057,
0.26716, -0.31209, -0.05866, -0.29101, -0.27437, -0.18727, 0.28732, -0.19014, 0.08837, 0.30405,
0.06103, -0.35612, 0.00173, 0.25134, -0.08987, -0.22766, -0.03254, -0.18662, -0.08491, 0.49401,
-0.12145, -0.02961, -0.03668, -0.30043, -0.08555, 0.01701, -0.12544, 0.10969, -0.48202, 0.07245,
0.20673, 0.11408, 0.04343, -0.01815, -0.31594, -0.23632, -0.06258, -0.27474, 0.12180, 0.16613,
-0.37931, 0.30219, 0.15765, 0.25489, 0.17529, -0.17020, -0.30060, 0.22058, -0.02450, -0.42143,
0.49642, 0.46899, -0.28552, -0.22549, -0.01333, 0.21567, 0.22251, 0.21639, -0.19194, -0.19140,
-0.24106, 0.10952, -0.11019, 0.29763, -0.02039, -0.25748, 0.23169, 0.01357, 0.09802, -0.19022,
0.37604, -0.40777, 0.18131, -0.10258, 0.29573, -0.31773, 0.09069, -0.02198, -0.26594, 0.48302,
-0.10041, 0.20210, -0.05609, -0.01169, -0.17339, 0.17862, -0.22502, 0.29009, -0.45160, 0.19771,
0.27634, 0.31695, -0.09993, 0.17167, 0.12394, 0.28088, -0.12502, -0.16967, -0.06296, -0.17036,
0.27320, 0.01595, 0.16955, 0.30146, -0.15173, -0.29807, 0.08178, -0.06811, 0.21655, 0.26348,
0.06316, 0.45661, -0.29756, -0.05742, -0.14715, -0.03037, -0.16656, -0.08768, 0.38078, 0.40679,
-0.32779, -0.09106, 0.16107, -0.07301, 0.07700, -0.22694, -0.15692, -0.02548, 0.38749, -0.12203,
-0.02980, -0.22067, 0.00680, -0.23058, -0.29112, 0.23032, -0.16026, 0.23392, -0.09990, 0.03628,
-0.42592, -0.33474, -0.09499, -0.17442, -0.20110, 0.24618, -0.06418, -0.06715, 0.40754, 0.29377,
0.29543, -0.16832, -0.08468, 0.06491, -0.01410, 0.19988, 0.24950, 0.14626, -0.27851, 0.06079,
0.48134, -0.13475, 0.25398, 0.11738, 0.23369, -0.00661, -0.16811, -0.04557, -0.12030, -0.39527,
-0.35760, 0.01840, -0.15941, 0.03290, 0.09988, -0.08307, 0.06644, -0.24637, 0.34112, -0.08026,
0.00951, 0.27656, 0.16247, 0.28217, 0.17198, -0.16389, -0.03835, -0.02675, -0.08032, -0.21045,
-0.38946, 0.23207, 0.10987, -0.31674, -0.28653, -0.27430, -0.29109, -0.00648, 0.38431, -0.38478,
-0.41195, -0.19364, -0.20977, -0.05524, 0.05558, -0.20109, 0.11803, -0.19884, 0.43318, -0.39255,
0.26612, -0.21771, 0.12471, 0.12856, -0.15104, -0.11676, 0.17582, -0.25330, 0.00298, -0.31712,
0.21532, -0.20319, 0.14507, -0.04588, -0.22995, -0.06470, 0.18849, -0.13444, 0.37107, 0.07387,
-0.14008, 0.09896, 0.13727, -0.28417, -0.09461, -0.18703, 0.04080, 0.02343, -0.49988, 0.17993,
0.23189, -0.30581, -0.18334, -0.09667, -0.27699, -0.05998, 0.09118, -0.32453, 0.46251, 0.41500,
-0.45314, -0.00544, 0.08529, 0.29099, -0.00937, -0.31650, 0.26163, 0.14506, 0.37498, -0.16454,
0.35215, 0.31642, -0.09161, -0.31452, -0.04792, -0.04677, -0.19523, 0.27998, 0.05491, 0.44461,
-0.01258, -0.27887, 0.18361, -0.04539, -0.02977, 0.30821, 0.29454, -0.17932, 0.16193, 0.23934,
0.47923, 0.25373, 0.23258, 0.31484, -0.17958, -0.01136, 0.17681, 0.12869, 0.03235, 0.43762,
0.13734, -0.09433, -0.03735, 0.17949, 0.14122, -0.17814, 0.06359, 0.16044, 0.12249, -0.22314,
0.40775, 0.05147, 0.12389, 0.04290, -0.01642, 0.00082, -0.18056, 0.02875, 0.32690, 0.17712,
0.34001, -0.21581, -0.01086, -0.18180, 0.17480, -0.17774, -0.07503, 0.28438, -0.19747, 0.29595,
-0.28002, -0.02073, -0.16522, -0.18234, -0.20565, 0.29620, 0.07502, 0.01429, -0.31418, 0.43693,
-0.12212, 0.11178, -0.28503, 0.04683, 0.00072, 0.05566, 0.18857, 0.26101, -0.38891, -0.21216,
-0.21850, -0.15147, -0.30749, -0.23762, 0.14984, 0.03535, -0.02862, -0.00105, -0.39907, -0.06909,
-0.36094, 0.21717, 0.15930, -0.18924, 0.13741, 0.01039, 0.13613, 0.00659, 0.07676, -0.13711,
0.24285, -0.07564, -0.28349, -0.15658, 0.03135, -0.30909, -0.22534, 0.17363, -0.19376, 0.26038,
0.05546, -0.22607, 0.32420, -0.02552, -0.05400, 0.13388, 0.04643, -0.31535, -0.06181, 0.30237,
-0.04680, -0.29441, 0.12231, 0.03960, -0.01188, 0.01406, 0.25402, 0.03315, 0.25026, -0.10922
};
const double gu_data2[] =
{ // raw data 300 items
0.26599, 0.41329, 0.31846, 0.92590, 0.43050, 0.17466, 0.02322, 0.72621, 0.37921, 0.70597,
0.97098, 0.14023, 0.57619, 0.09938, 0.02281, 0.92341, 0.72654, 0.71000, 0.76687, 0.70182,
0.88752, 0.49524, 0.42549, 0.42806, 0.57615, 0.76051, 0.15341, 0.47457, 0.60066, 0.40880,
0.20668, 0.41949, 0.97620, 0.94318, 0.71491, 0.56402, 0.23553, 0.94387, 0.78567, 0.06362,
0.85252, 0.86262, 0.25190, 0.03274, 0.93216, 0.37971, 0.08797, 0.14596, 0.73871, 0.06574,
0.67447, 0.28575, 0.43911, 0.92133, 0.12327, 0.87762, 0.71060, 0.07141, 0.55443, 0.53310,
0.91529, 0.25121, 0.07593, 0.94490, 0.28656, 0.82174, 0.68887, 0.67337, 0.99291, 0.03316,
0.02849, 0.33891, 0.25594, 0.90071, 0.01248, 0.67871, 0.65953, 0.65369, 0.97574, 0.31578,
0.23678, 0.39220, 0.06706, 0.80943, 0.57694, 0.08220, 0.18151, 0.19969, 0.37096, 0.37858,
0.70153, 0.46816, 0.76511, 0.02520, 0.39387, 0.25527, 0.39050, 0.60141, 0.30322, 0.46195,
0.12025, 0.33616, 0.04174, 0.00196, 0.68886, 0.74445, 0.15869, 0.18994, 0.95195, 0.62874,
0.82874, 0.53369, 0.34383, 0.50752, 0.97023, 0.22695, 0.62407, 0.25840, 0.71279, 0.28785,
0.31611, 0.20391, 0.19702, 0.40760, 0.85158, 0.68369, 0.63760, 0.09879, 0.11924, 0.32920,
0.53052, 0.15900, 0.21229, 0.84080, 0.33933, 0.93651, 0.42705, 0.06199, 0.50092, 0.47192,
0.57152, 0.01818, 0.31404, 0.50173, 0.87725, 0.50530, 0.10717, 0.04035, 0.32901, 0.33538,
0.04780, 0.40984, 0.78216, 0.91288, 0.11314, 0.25248, 0.23823, 0.74001, 0.48089, 0.55531,
0.82486, 0.01058, 0.05409, 0.44357, 0.52641, 0.68188, 0.94629, 0.61627, 0.33037, 0.11961,
0.57988, 0.19653, 0.91902, 0.59838, 0.52974, 0.28364, 0.45767, 0.65836, 0.63045, 0.76140,
0.27918, 0.27256, 0.46035, 0.77418, 0.92918, 0.14095, 0.89645, 0.25146, 0.21172, 0.47910,
0.95451, 0.34377, 0.29927, 0.79220, 0.97654, 0.67591, 0.44385, 0.38434, 0.44860, 0.28170,
0.90712, 0.20337, 0.00292, 0.55046, 0.62255, 0.45127, 0.80896, 0.43965, 0.59145, 0.23801,
0.33601, 0.30119, 0.89935, 0.40850, 0.98226, 0.75430, 0.68318, 0.65407, 0.68067, 0.32942,
0.11756, 0.27626, 0.83879, 0.72174, 0.75430, 0.13702, 0.03402, 0.58781, 0.07393, 0.23067,
0.92537, 0.29445, 0.43437, 0.47685, 0.54548, 0.66082, 0.23805, 0.60208, 0.94337, 0.21363,
0.72637, 0.57181, 0.77679, 0.63931, 0.72860, 0.38901, 0.94920, 0.04535, 0.12863, 0.40550,
0.90095, 0.21418, 0.13953, 0.99639, 0.02526, 0.70018, 0.21828, 0.20294, 0.20191, 0.30954,
0.39490, 0.68955, 0.11506, 0.15748, 0.40252, 0.91680, 0.61547, 0.78443, 0.19693, 0.67630,
0.56552, 0.58556, 0.53554, 0.53507, 0.09831, 0.21229, 0.83135, 0.26375, 0.89287, 0.97069,
0.70615, 0.42041, 0.43117, 0.21291, 0.26086, 0.26978, 0.77340, 0.43833, 0.46179, 0.54418,
0.67878, 0.42776, 0.61454, 0.55915, 0.36363, 0.31999, 0.42442, 0.86649, 0.62513, 0.02047
};
class TestRunnable
{
public:
const std::string name;
int dim; // dimension of the solved problem
int nvar; // number of variable of the solved problem
TestRunnable(std::string n, int d, int nv)
: name{std::move(n)}, dim(d), nvar(nv)
{
}
virtual ~TestRunnable() = default;
bool test() const;
virtual bool run() const = 0;
protected:
static double korder_unfold_fold(int maxdim, int unfold_dim,
int nstat, int npred, int nboth, int forw,
const TwoDMatrix &gy, const TwoDMatrix &gu,
const TwoDMatrix &v);
};
bool
TestRunnable::test() const
{
std::cout << "Running test <" << name << ">" << std::endl;
clock_t start = clock();
auto start_real = std::chrono::steady_clock::now();
bool passed = run();
clock_t end = clock();
auto end_real = std::chrono::steady_clock::now();
std::chrono::duration<double> duration = end_real - start_real;
std::cout << "CPU time " << std::setprecision(4) << std::setw(8)
<< static_cast<double>(end-start)/CLOCKS_PER_SEC << " (CPU seconds)\n"
<< "Real time " << std::setw(8) << duration.count() << " (seconds).....................";
if (passed)
std::cout << "passed\n\n";
else
std::cout << "FAILED\n\n";
return passed;
}
double
TestRunnable::korder_unfold_fold(int maxdim, int unfold_dim,
int nstat, int npred, int nboth, int nforw,
const TwoDMatrix &gy, const TwoDMatrix &gu,
const TwoDMatrix &v)
{
TensorContainer<FSSparseTensor> c(1);
int ny = nstat+npred+nboth+nforw;
int nu = v.nrows();
int nz = nboth+nforw+ny+nboth+npred+nu;
SparseGenerator::fillContainer(c, maxdim, nz, ny, 5.0);
for (int d = 1; d <= maxdim; d++)
std::cout << "\ttensor fill for dim=" << d << " is: "
<< std::setprecision(2) << std::setw(6) << std::fixed
<< c.get(Symmetry{d}).getFillFactor()*100.0 << " %\n"
<< std::defaultfloat;
Journal jr("out.txt");
KOrder kord(nstat, npred, nboth, nforw, c, gy, gu, v, jr);
// Perform unfolded steps until unfold_dim
double maxerror = 0.0;
for (int d = 2; d <= unfold_dim; d++)
{
clock_t pertime = clock();
kord.performStep<Storage::unfold>(d);
pertime = clock()-pertime;
std::cout << "\ttime for unfolded step dim=" << d << ": " << std::setprecision(4)
<< static_cast<double>(pertime)/CLOCKS_PER_SEC << std::endl;
clock_t checktime = clock();
double err = kord.check<Storage::unfold>(d);
checktime = clock()-checktime;
std::cout << "\ttime for step check dim=" << d << ": " << std::setprecision(4)
<< static_cast<double>(checktime)/CLOCKS_PER_SEC << '\n'
<< "\tmax error in step dim=" << d << ": " << std::setprecision(6) << err
<< std::endl;
maxerror = std::max(err, maxerror);
}
// Perform folded steps until maxdim
if (unfold_dim < maxdim)
{
clock_t swtime = clock();
kord.switchToFolded();
swtime = clock()-swtime;
std::cout << "\ttime for switching dim=" << unfold_dim << ": " << std::setprecision(4)
<< static_cast<double>(swtime)/CLOCKS_PER_SEC << std::endl;
for (int d = unfold_dim+1; d <= maxdim; d++)
{
clock_t pertime = clock();
kord.performStep<Storage::fold>(d);
pertime = clock()-pertime;
std::cout << "\ttime for folded step dim=" << d << ": " << std::setprecision(4)
<< static_cast<double>(pertime)/CLOCKS_PER_SEC << std::endl;
clock_t checktime = clock();
double err = kord.check<Storage::fold>(d);
checktime = clock()-checktime;
std::cout << "\ttime for step check dim=" << d << ": " << std::setprecision(4)
<< static_cast<double>(checktime)/CLOCKS_PER_SEC << '\n'
<< "\tmax error in step dim=" << d << ": " << std::setprecision(6) << err
<< std::endl;
maxerror = std::max(err, maxerror);
}
}
return maxerror;
}
class UnfoldKOrderSmall : public TestRunnable
{
public:
UnfoldKOrderSmall()
: TestRunnable("unfold-3 fold-4 korder (stat=2,pred=3,both=1,forw=2,u=3,dim=4)",
4, 18)
{
}
bool
run() const override
{
TwoDMatrix gy{make_matrix(8, 4, gy_data)};
TwoDMatrix gu{make_matrix(8, 3, gu_data)};
TwoDMatrix v{make_matrix(3, 3, vdata)};
double err = korder_unfold_fold(4, 3, 2, 3, 1, 2,
gy, gu, v);
return err < 5e-7;
}
};
// Same dimension as Smets & Wouters
class UnfoldKOrderSW : public TestRunnable
{
public:
UnfoldKOrderSW()
: TestRunnable("unfold S&W korder (stat=5,pred=12,both=8,forw=5,u=10,dim=4)",
4, 73)
{
}
bool
run() const override
{
TwoDMatrix gy{make_matrix(30, 20, gy_data2)};
TwoDMatrix gu{make_matrix(30, 10, gu_data2)};
TwoDMatrix v{make_matrix(10, 10, vdata2)};
v.mult(0.001);
gu.mult(.01);
double err = korder_unfold_fold(4, 4, 5, 12, 8, 5,
gy, gu, v);
return err < 0.5;
}
};
class UnfoldFoldKOrderSW : public TestRunnable
{
public:
UnfoldFoldKOrderSW()
: TestRunnable("unfold-2 fold-3 S&W korder (stat=5,pred=12,both=8,forw=5,u=10,dim=3)",
4, 73)
{
}
bool
run() const override
{
TwoDMatrix gy{make_matrix(30, 20, gy_data2)};
TwoDMatrix gu{make_matrix(30, 10, gu_data2)};
TwoDMatrix v{make_matrix(10, 10, vdata2)};
v.mult(0.001);
gu.mult(.01);
double err = korder_unfold_fold(4, 3, 5, 12, 8, 5,
gy, gu, v);
return err < 0.5;
}
};
int
main()
{
std::vector<std::unique_ptr<TestRunnable>> all_tests;
// Fill in vector of all tests
all_tests.push_back(std::make_unique<UnfoldKOrderSmall>());
all_tests.push_back(std::make_unique<UnfoldKOrderSW>());
all_tests.push_back(std::make_unique<UnfoldFoldKOrderSW>());
// Find maximum dimension and maximum nvar
int dmax = 0;
int nvmax = 0;
for (const auto &test : all_tests)
{
if (dmax < test->dim)
dmax = test->dim;
if (nvmax < test->nvar)
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;
}

View File

@ -0,0 +1,43 @@
noinst_LIBRARIES = libparser.a
GENERATED_FILES = assign_tab.cc formula_tab.cc matrix_tab.cc assign_tab.hh formula_tab.hh matrix_tab.hh assign_ll.cc formula_ll.cc matrix_ll.cc
libparser_a_SOURCES = \
location.hh \
atom_assignings.cc \
atom_assignings.hh \
atom_substitutions.cc \
atom_substitutions.hh \
dynamic_atoms.cc \
dynamic_atoms.hh \
fine_atoms.cc \
fine_atoms.hh \
formula_parser.cc \
formula_parser.hh \
matrix_parser.cc \
matrix_parser.hh \
parser_exception.cc \
parser_exception.hh \
static_atoms.cc \
static_atoms.hh \
static_fine_atoms.cc \
static_fine_atoms.hh \
tree.cc \
tree.hh \
$(GENERATED_FILES)
libparser_a_CPPFLAGS = -I../.. $(BOOST_CPPFLAGS)
BUILT_SOURCES = $(GENERATED_FILES)
EXTRA_DIST = assign.yy formula.yy matrix.yy assign.ll formula.ll matrix.ll
%_tab.cc %_tab.hh: %.yy
$(YACC) -W -o$*_tab.cc $<
%_tab.$(OBJEXT): CXXFLAGS += -Wno-old-style-cast
%_ll.cc: %.ll
$(LEX) -i -o$@ $<
%_ll.$(OBJEXT): CXXFLAGS += -Wno-old-style-cast

View File

@ -0,0 +1,74 @@
/* -*- C++ -*- */
/*
* Copyright © 2004-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 <https://www.gnu.org/licenses/>.
*/
%{
#include "location.hh"
#include "assign_tab.hh"
#define YY_USER_ACTION SET_LLOC(asgn_);
%}
%option nounput
%option noyy_top_state
%option stack
%option yylineno
%option prefix="asgn_"
%option never-interactive
%x CMT
%%
/* comments */
<*>"/*" {yy_push_state(CMT);}
<CMT>[^*\n]*
<CMT>"*"+[^*/\n]*
<CMT>"*"+"/" {yy_pop_state();}
<CMT>[\n]
"//".*\n
/* spaces */
[ \t\r\n] {return BLANK;}
/* names */
[A-Za-z_][A-Za-z0-9_]* {
asgn_lval.string = asgn_text;
return NAME;
}
; {return SEMICOLON;}
= {return EQUAL_SIGN;}
. {
asgn_lval.character = asgn_text[0];
return CHARACTER;
}
%%
int
asgn_wrap()
{
return 1;
}
void
asgn__destroy_buffer(void* p)
{
asgn__delete_buffer(static_cast<YY_BUFFER_STATE>(p));
}

View File

@ -0,0 +1,76 @@
// -*- C++ -*-
/*
* Copyright © 2006-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 <https://www.gnu.org/licenses/>.
*/
%code requires
{
#include "location.hh"
#define ASGN_LTYPE ogp::location_type
}
%code
{
#include "atom_assignings.hh"
#include <string>
void asgn_error(std::string);
int asgn_lex();
extern ogp::AtomAssignings* aparser;
}
%union
{
int integer;
char *string;
char character;
}
%token EQUAL_SIGN SEMICOLON CHARACTER BLANK
%token <string> NAME;
%define api.prefix {asgn_}
%locations
%defines
%define parse.error verbose
%%
root : assignments | %empty;
assignments : assignments BLANK | assignments assignment | assignment | BLANK;
assignment : NAME EQUAL_SIGN material SEMICOLON {
aparser->add_assignment(@1.off, $1, @1.ll, @3.off-@1.off, @3.ll + @4.ll);}
| NAME space EQUAL_SIGN material SEMICOLON {
aparser->add_assignment(@1.off, $1, @1.ll, @4.off-@1.off, @4.ll + @5.ll);}
;
material : material CHARACTER | material NAME | material BLANK | NAME | CHARACTER | BLANK;
space : space BLANK | BLANK;
%%
void
asgn_error(std::string mes)
{
aparser->error(std::move(mes));
}

View File

@ -0,0 +1,254 @@
/*
* Copyright © 2006 Ondra Kamenik
* Copyright © 2019-2022 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 <https://www.gnu.org/licenses/>.
*/
#include "atom_assignings.hh"
#include "location.hh"
#include "parser_exception.hh"
#include "utils/cc/exception.hh"
#include <limits>
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace ogp;
AtomAssignings::AtomAssignings(const AtomAssignings &aa, ogp::StaticAtoms &a)
: atoms(a), expr(aa.expr, atoms), left_names(aa.left_names),
lname2expr(aa.lname2expr), order(aa.order)
{
}
/** A global symbol for passing info to the AtomAssignings from
* asgn_parse(). */
AtomAssignings *aparser;
/** The declaration of functions defined in asgn_ll.cc and asgn_tab.cc
* generated from assign.lex assign.y */
void *asgn__scan_string(const char *);
void asgn__destroy_buffer(void *);
void asgn_parse();
extern location_type asgn_lloc;
void
AtomAssignings::parse(const string &stream)
{
asgn_lloc.off = 0;
asgn_lloc.ll = 0;
void *p = asgn__scan_string(stream.c_str());
aparser = this;
asgn_parse();
asgn__destroy_buffer(p);
}
void
AtomAssignings::error(string mes)
{
throw ParserException(std::move(mes), asgn_lloc.off);
}
void
AtomAssignings::add_assignment_to_double(string name, double val)
{
// if left hand side is a registered atom, insert it to tree
int t;
try
{
if (atoms.check(name))
t = expr.add_nulary(name);
else
t = -1;
}
catch (const ParserException &e)
{
t = -1;
}
// register left hand side in order
order.push_back(t);
// add the double to the tree
std::ostringstream buf;
buf << std::setprecision(std::numeric_limits<double>::max_digits10)
<< val;
try
{
expr.parse(buf.str());
}
catch (const ParserException &e)
{
// should never happen
throw ParserException("Error parsing double "+buf.str()+": "+e.message(), 0);
}
// register name of the left hand side and put to lname2expr
left_names.insert(name);
lname2expr.emplace(std::move(name), order.size()-1);
}
void
AtomAssignings::add_assignment(int asgn_off, const string &str, int name_len,
int right_off, int right_len)
{
// the order of doing things here is important: since the
// FormulaParser requires that all references from the i-th tree
// refere to trees with index lass than i, so to capture also a
// nulary term for the left hand side, it must be inserted to the
// expression tree before the expression is parsed.
// find the name in the atoms
string name = str.substr(0, name_len);
// if left hand side is a registered atom, insert it to tree
int t;
try
{
t = atoms.check(name);
if (t == -1)
t = expr.add_nulary(name);
}
catch (const ParserException &e)
{
atoms.register_name(name);
t = expr.add_nulary(name);
}
// register left hand side in order
order.push_back(t);
// parse expression on the right
try
{
expr.parse(str.substr(right_off, right_len));
}
catch (const ParserException &e)
{
throw ParserException(e, asgn_off+right_off);
}
// register name of the left hand side and put to lname2expr
left_names.insert(name);
if (lname2expr.find(name) != lname2expr.end())
{
// Prevent the occurrence of #415
std::cerr << "Changing the value of " << name << " through a second assignment (e.g. in initval) is not supported. Aborting." << std::endl;
exit(EXIT_FAILURE);
}
lname2expr[name] = order.size()-1;
}
void
AtomAssignings::apply_subst(const AtomSubstitutions::Toldnamemap &mm)
{
// go through all old variables and see what are their derived new
// variables
for (const auto &it : mm)
{
const string &oldname = it.first;
const AtomSubstitutions::Tshiftnameset &sset = it.second;
if (!sset.empty())
{
int told = atoms.index(oldname);
if (told < 0 && !atoms.get_name_storage().query(oldname))
atoms.register_name(oldname);
if (told == -1)
told = expr.add_nulary(oldname);
// at least one substitution here, so make an expression
expr.add_formula(told);
// say that this expression is not assigned to any atom
order.push_back(-1);
// now go through all new names derived from the old name and
// reference to the newly added formula
for (const auto &itt : sset)
{
const string &newname = itt.first;
left_names.insert(newname);
lname2expr.emplace(newname, expr.nformulas()-1);
}
}
}
}
void
AtomAssignings::print() const
{
std::cout << "Atom Assignings\nExpressions:\n";
expr.print();
std::cout << "Left names:\n";
for (auto it : lname2expr)
std::cout << it.first << "" << expr.formula(it.second) << " (t=" << order[it.second] << ")\n";
}
void
AtomAsgnEvaluator::setValues(EvalTree &et) const
{
// set values of constants
aa.atoms.setValues(et);
// set values of variables to NaN or to user set values
double nan = std::numeric_limits<double>::quiet_NaN();
for (int i = 0; i < aa.atoms.nvar(); i++)
{
const string &ss = aa.atoms.name(i);
int t = aa.atoms.index(ss);
if (t >= 0)
{
auto it = user_values.find(t);
if (it == user_values.end())
et.set_nulary(t, nan);
else
et.set_nulary(t, it->second);
}
}
}
void
AtomAsgnEvaluator::set_user_value(const string &name, double val)
{
int t = aa.atoms.index(name);
if (t >= 0)
{
auto it = user_values.find(t);
if (it == user_values.end())
user_values.emplace(t, val);
else
it->second = val;
}
}
void
AtomAsgnEvaluator::load(int i, double res)
{
// set the value
operator[](i) = res;
// if i-th expression is atom, set its value to this EvalTree
int t = aa.order[i];
if (t >= 0)
etree.set_nulary(t, res);
}
double
AtomAsgnEvaluator::get_value(const string &name) const
{
auto it = aa.lname2expr.find(name);
if (it == aa.lname2expr.end())
return std::numeric_limits<double>::quiet_NaN();
else
return operator[](it->second);
}

View File

@ -0,0 +1,148 @@
/*
* Copyright © 2006 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 <https://www.gnu.org/licenses/>.
*/
#ifndef OGP_ATOM_ASSIGNINGS_H
#define OGP_ATOM_ASSIGNINGS_H
#include "static_atoms.hh"
#include "formula_parser.hh"
#include "atom_substitutions.hh"
#include <vector>
#include <map>
namespace ogp
{
class AtomAsgnEvaluator;
/** This class represents atom assignments used in parameters
* settings and initval initialization. It maintains atoms of the
* all expressions on the right hand side, the parsed formulas of
* the right hand sides, and the information about the left hand
* sides. See documentation to the order member below. */
class AtomAssignings
{
friend class AtomAsgnEvaluator;
protected:
using Tvarintmap = std::map<string, int>;
/** All atoms which should be sufficient for formulas at the
* right hand sides. The atoms should be filled with names
* (preregistered). This is a responsibility of the caller. */
StaticAtoms &atoms;
/** The formulas of right hand sides. */
FormulaParser expr;
/** Name storage of the names from left hand sides. */
NameStorage left_names;
/** Information on left hand sides. This maps a name to the
* index of its assigned expression in expr. More than one
* name may reference to the same expression. */
Tvarintmap lname2expr;
/** Information on left hand sides. If order[i] >= 0, then it
* says that i-th expression in expr is assigned to atom with
* order[i] tree index. */
std::vector<int> order;
public:
/** Construct the object using the provided static atoms. */
AtomAssignings(StaticAtoms &a) : atoms(a), expr(atoms)
{
}
/** Make a copy with provided reference to (posibly different)
* static atoms. */
AtomAssignings(const AtomAssignings &aa, StaticAtoms &a);
virtual ~AtomAssignings() = default;
/** Parse the assignments from the given string. */
void parse(const string &stream);
/** Process a syntax error from bison. */
void error(string mes);
/** Add an assignment of the given name to the given
* double. Can be called by a user, anytime. */
void add_assignment_to_double(string name, double val);
/** Add an assignment. Called from assign.y. */
void add_assignment(int asgn_off, const string &str, int name_len,
int right_off, int right_len);
/** This applies old2new map (possibly from atom
* substitutions) to this object. It registers new variables
* in the atoms, and adds the expressions to expr, and left
* names to lname2expr. The information about dynamical part
* of substitutions is ignored, since we are now in the static
* world. */
void apply_subst(const AtomSubstitutions::Toldnamemap &mm);
/** Debug print. */
void print() const;
};
/** This class basically evaluates the atom assignments
* AtomAssignings, so it inherits from ogp::FormulaEvaluator. It
* is also a storage for the results of the evaluation stored as a
* vector, so the class inherits from std::vector<double> and
* ogp::FormulaEvalLoader. As the expressions for atoms are
* evaluated, the results are values for atoms which will be
* used in subsequent evaluations. For this reason, the class
* inherits also from AtomValues. */
class AtomAsgnEvaluator : public FormulaEvalLoader,
public AtomValues,
protected FormulaEvaluator,
public std::vector<double>
{
protected:
using Tusrvalmap = std::map<int, double>;
Tusrvalmap user_values;
const AtomAssignings &aa;
public:
AtomAsgnEvaluator(const AtomAssignings &a)
: FormulaEvaluator(a.expr),
std::vector<double>(a.expr.nformulas()), aa(a)
{
}
~AtomAsgnEvaluator() override = default;
/** This sets all initial values to NaNs, all constants and
* all values set by user by call set_value. This is called by
* FormulaEvaluator::eval() method, which is called by eval()
* method passing this argument as AtomValues. So the
* ogp::EvalTree will be always this->etree. */
void setValues(EvalTree &et) const override;
/** User setting of the values. For example in initval,
* parameters are known and should be set to their values. In
* constrast endogenous variables are set initially to NaNs by
* AtomValues::setValues. */
void set_user_value(const string &name, double val);
/** This sets the result of i-th expression in aa to res, and
* also checks whether the i-th expression is an atom. If so,
* it sets the value of the atom in ogp::EvalTree
* this->etree. */
void load(int i, double res) override;
/** After the user values have been set, the assignments can
* be evaluated. For this purpose we have eval() method. The
* result is that this object as std::vector<double> will
* contain the values. It is ordered given by formulas in
* expr. */
void
eval()
{
FormulaEvaluator::eval(*this, *this);
}
/** This returns a value for a given name. If the name is not
* found among atoms, or there is no assignment for the atom,
* NaN is returned. */
double get_value(const string &name) const;
};
};
#endif

View File

@ -0,0 +1,275 @@
/*
* Copyright © 2006 Ondra Kamenik
* Copyright © 2019-2022 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 <https://www.gnu.org/licenses/>.
*/
#include "atom_substitutions.hh"
#include "utils/cc/exception.hh"
using namespace ogp;
AtomSubstitutions::AtomSubstitutions(const AtomSubstitutions &as, const FineAtoms &oa,
FineAtoms &na)
: new2old(as.new2old), old2new(as.old2new), old_atoms(oa), new_atoms(na)
{
}
void
AtomSubstitutions::add_substitution(string newname, string oldname, int tshift)
{
// insert to new2old map
new2old.emplace(newname, Tshiftname(oldname, tshift));
// insert to old2new map
auto it = old2new.find(oldname);
if (it != old2new.end())
it->second.emplace(std::move(newname), -tshift);
else
{
Tshiftnameset snset;
snset.emplace(std::move(newname), -tshift);
old2new.emplace(std::move(oldname), snset);
}
// put to info
info.num_substs++;
}
void
AtomSubstitutions::substitutions_finished(VarOrdering::ord_type ot)
{
// create an external ordering of new_atoms from old_atoms
const vector<string> &oa_ext = old_atoms.get_allvar();
vector<string> na_ext;
for (const auto &oname : oa_ext)
{
// add the old name itself
na_ext.push_back(oname);
// add all new names derived from the old name
auto it = old2new.find(oname);
if (it != old2new.end())
for (const auto &itt : it->second)
na_ext.push_back(itt.first);
}
// call parsing finished for the new_atoms
new_atoms.parsing_finished(ot, na_ext);
}
string
AtomSubstitutions::get_new4old(const string &oldname, int tshift) const
{
auto it = old2new.find(oldname);
if (it != old2new.end())
{
const Tshiftnameset &sset = it->second;
for (const auto &itt : sset)
if (itt.second == -tshift)
return itt.first;
}
return "";
}
void
AtomSubstitutions::print() const
{
std::cout << "Atom Substitutions:\nOld ⇒ New:\n";
for (const auto &it : old2new)
for (const auto &itt : it.second)
std::cout << " " << it.first << " ⇒ [" << itt.first << ", " << itt.second << "]\n";
std::cout << "Old ⇐ New:\n";
for (const auto &it : new2old)
std::cout << " [" << it.second.first << ", " << it.second.second << "] ⇐ " << it.first << '\n';
}
void
SAtoms::substituteAllLagsAndLeads(FormulaParser &fp, AtomSubstitutions &as)
{
string name;
int mlead, mlag;
endovarspan(mlead, mlag);
// substitute all endo lagged more than 1
while (!(name = findEndoWithLeadInInterval(mlag, -2)).empty())
makeAuxVariables(name, -1, -2, mlag, fp, as);
// substitute all endo leaded more than 1
while (!(name = findEndoWithLeadInInterval(2, mlead)).empty())
makeAuxVariables(name, 1, 2, mlead, fp, as);
exovarspan(mlead, mlag);
// substitute all lagged exo
while (!(name = findExoWithLeadInInterval(mlag, -1)).empty())
makeAuxVariables(name, -1, -1, mlag, fp, as);
// substitute all leaded exo
while (!(name = findExoWithLeadInInterval(1, mlead)).empty())
makeAuxVariables(name, 1, 1, mlead, fp, as);
// notify that substitution have been finished
as.substitutions_finished(order_type);
}
void
SAtoms::substituteAllLagsAndExo1Leads(FormulaParser &fp, AtomSubstitutions &as)
{
string name;
int mlead, mlag;
endovarspan(mlead, mlag);
// substitute all endo lagged more than 1
while (!(name = findEndoWithLeadInInterval(mlag, -2)).empty())
makeAuxVariables(name, -1, -2, mlag, fp, as);
exovarspan(mlead, mlag);
// substitute all lagged exo
while (!(name = findExoWithLeadInInterval(mlag, -1)).empty())
makeAuxVariables(name, -1, -1, mlag, fp, as);
// substitute all leaded exo by 1
while (!(name = findExoWithLeadInInterval(1, 1)).empty())
makeAuxVariables(name, 1, 1, 1, fp, as);
// notify that substitution have been finished
as.substitutions_finished(order_type);
}
string
SAtoms::findNameWithLeadInInterval(const vector<string> &names,
int ll1, int ll2) const
{
for (auto name : names)
{
auto it = vars.find(name);
if (it != vars.end())
{
const DynamicAtoms::Tlagmap &lmap = it->second;
for (auto itt : lmap)
if (itt.first >= ll1 && itt.first <= ll2)
return name;
}
}
// nothing found
return "";
}
void
SAtoms::attemptAuxName(const string &str, int ll, string &out) const
{
char c = (ll >= 0) ? ((ll == 0) ? 'e' : 'p') : 'm';
string absll = std::to_string(std::abs(ll));
int iter = 1;
do
{
out = str + '_';
for (int i = 0; i < iter; i++)
out += c;
if (ll != 0)
out += absll;
iter++;
}
while (varnames.query(out));
}
void
SAtoms::makeAuxVariables(const string &name, int step, int start, int limit_lead,
FormulaParser &fp, AtomSubstitutions &as)
{
if (!(step == 1 || step == -1))
throw ogu::Exception(__FILE__, __LINE__,
"Wrong value of step in SAtoms::makeAuxVariables");
if (step*start > step*limit_lead)
throw ogu::Exception(__FILE__, __LINE__,
"Wrong value of start in SAtoms::makeAuxVariables");
// make sure that we do not go further than necessary, this is
// that the limit lead is not behind maxlead or minlag
int mlead, mlag;
varspan(name, mlead, mlag);
if (step == -1)
limit_lead = std::max(limit_lead, mlag);
else
limit_lead = std::min(limit_lead, mlead);
// Comment to comments: name="a"; start=-3; step=-1;
// recover tree index of a previous atom, i.e. set tprev to a tree
// index of atom "a(-2)"
int tprev = index(name, start-step);
if (tprev == -1)
tprev = fp.add_nulary(name + '(' + std::to_string(start-step) + ')');
int ll = start;
do
{
// either create atom "a_m2(0)" with tree index taux and add
// equation "a_m2(0)=a(-2)"
// or
// check if "a_m2(0)" has not been already created (with
// different step), in this case do not add equation "a_m2(0)
// = a(-2)"
string newname, newname_str;
int taux;
if ((newname = as.get_new4old(name, ll-step)).empty())
{
attemptAuxName(name, ll-step, newname_str);
newname = newname_str;
register_uniq_endo(newname);
taux = fp.add_nulary(newname + "(0)");
// add to substitutions
as.add_substitution(newname, name, ll-step);
// add equation "a_m2(0) = a(-2)", this is taux = tprev
fp.add_formula(fp.add_binary(code_t::MINUS, taux, tprev));
}
else
{
// example: exogenous EPS and occurrence at both EPS(-1)
// EPS(+1)
// first call makeAuxVariables("EPS",1,1,...) will make endo EPS_p0 = EPS
// second call makeAuxVariables("EPS",-1,-1,...) will use this EPS_p0
// to substitute for EPS(-1)
taux = index(newname, 0);
if (taux < 0)
throw ogu::Exception(__FILE__, __LINE__,
"Couldn't find tree index of previously substituted variable");
}
// create atom "a_m2(-1)" or turn "a(-3)" if any to "a_m2(-1)"; tree index t
int t = index(name, ll);
if (t == -1)
{
// no "a(-3)", make t <-> a_m2(-1)
t = fp.add_nulary(newname + '(' + std::to_string(step) + ')');
}
else
{
// turn a(-3) to a_m2(-1)
unassign_variable(name, ll, t);
assign_variable(newname, step, t);
}
// next iteration starts with tprev <-> "a_m2(-1)" (this will be made equal to "a_m3(0)")
tprev = t;
ll += step;
}
while (step*ll <= step*limit_lead);
}

Some files were not shown because too many files have changed in this diff Show More