Merge remote-tracking branch 'origin/master' into ecb-master
commit
0617f58a14
|
@ -75,8 +75,6 @@ checksum
|
|||
/doc/mdate-sh
|
||||
/doc/stamp-vti
|
||||
!/doc/guide.bbl
|
||||
!/doc/macroprocessor/new-design.pdf
|
||||
!/doc/macroprocessor/old-design.pdf
|
||||
!/doc/userguide/P_ModStruct3.pdf
|
||||
!/doc/userguide/P_MH2.pdf
|
||||
!/doc/userguide/P_flowest.pdf
|
||||
|
@ -101,24 +99,6 @@ doc/internals/*.html
|
|||
doc/internals/ltxpng
|
||||
mex/build/matlab/run_m2html.m
|
||||
|
||||
# Preprocessor
|
||||
/preprocessor/dynare_m
|
||||
/preprocessor/dynare_m.exe
|
||||
/preprocessor/DynareBison.cc
|
||||
/preprocessor/DynareBison.hh
|
||||
/preprocessor/FlexLexer.h
|
||||
/preprocessor/DynareFlex.cc
|
||||
/preprocessor/location.hh
|
||||
/preprocessor/position.hh
|
||||
/preprocessor/stack.hh
|
||||
/preprocessor/macro/MacroBison.cc
|
||||
/preprocessor/macro/MacroBison.hh
|
||||
/preprocessor/macro/MacroFlex.cc
|
||||
/preprocessor/macro/location.hh
|
||||
/preprocessor/macro/position.hh
|
||||
/preprocessor/macro/stack.hh
|
||||
/preprocessor/doc/
|
||||
|
||||
# MATLAB dir
|
||||
/matlab/preprocessor*
|
||||
/matlab/dynare_version.m
|
||||
|
|
|
@ -30,3 +30,6 @@
|
|||
[submodule "contrib/jsonlab"]
|
||||
path = contrib/jsonlab
|
||||
url = https://github.com/fangq/jsonlab.git
|
||||
[submodule "preprocessor"]
|
||||
path = preprocessor
|
||||
url = https://github.com/DynareTeam/dynare-preprocessor.git
|
||||
|
|
17
Makefile.am
17
Makefile.am
|
@ -35,6 +35,19 @@ EXTRA_DIST = \
|
|||
scripts \
|
||||
.dir-locals.el
|
||||
|
||||
all-local: preprocessor/src/dynare_m
|
||||
{ \
|
||||
if [ -z "`file preprocessor/src/dynare_m | grep x86.64`" ]; then \
|
||||
ARCH="32"; \
|
||||
else \
|
||||
ARCH="64"; \
|
||||
fi; \
|
||||
mkdir -p $(abs_srcdir)/matlab/preprocessor$$ARCH; \
|
||||
$(LN_S) -f $(abs_srcdir)/preprocessor/src/dynare_m $(abs_srcdir)/matlab/preprocessor$$ARCH; \
|
||||
mkdir -p $(abs_srcdir)/julia/preprocessor$$ARCH ; \
|
||||
$(LN_S) -f $(abs_srcdir)/preprocessor/src/dynare_m $(abs_srcdir)/julia/preprocessor$$ARCH; \
|
||||
}
|
||||
|
||||
dist-hook:
|
||||
rm -rf `find $(distdir)/matlab $(distdir)/examples -name *~`
|
||||
rm -rf $(distdir)/matlab/preprocessor* $(distdir)/matlab/dynare_version.m
|
||||
|
@ -51,13 +64,13 @@ install-exec-local:
|
|||
find $(DESTDIR)$(pkglibdir) -name LICENSE.md -delete
|
||||
rm -rf $(DESTDIR)$(pkglibdir)/matlab/preprocessor*
|
||||
{ \
|
||||
if [ -z "`file preprocessor/dynare_m | grep x86.64`" ]; then \
|
||||
if [ -z "`file preprocessor/src/dynare_m | grep x86.64`" ]; then \
|
||||
ARCH="32"; \
|
||||
else \
|
||||
ARCH="64"; \
|
||||
fi; \
|
||||
mkdir -p $(DESTDIR)$(pkglibdir)/matlab/preprocessor$$ARCH; \
|
||||
cp preprocessor/dynare_m $(DESTDIR)$(pkglibdir)/matlab/preprocessor$$ARCH; \
|
||||
cp preprocessor/src/dynare_m $(DESTDIR)$(pkglibdir)/matlab/preprocessor$$ARCH; \
|
||||
}
|
||||
|
||||
uninstall-local:
|
||||
|
|
65
README.md
65
README.md
|
@ -53,7 +53,7 @@ at the MATLAB prompt: if it returns `PCWIN`, then you have a 32-bit MATLAB; if i
|
|||
1. [**Fedora**](#fedora)
|
||||
1. [**Windows**](#windows)
|
||||
1. [**Windows Subsystem for Linux**](#windows-subsystem-for-linux)
|
||||
1. [**Mac OS X**](#mac-os-x)
|
||||
1. [**macOS**](#macos)
|
||||
|
||||
## General Instructions
|
||||
|
||||
|
@ -285,27 +285,48 @@ NB: it might be necessary to preface your calls by ```sudo``` in case you do not
|
|||
|
||||
After this, prepare the source and configure the build tree as described for Linux above.
|
||||
|
||||
## Mac OS X
|
||||
## macOS
|
||||
|
||||
To simply use a snapshot of Dynare, you have two choices. On Matlab, you can
|
||||
use the [snapshot build](http://www.dynare.org/snapshot/macosx/) provided by
|
||||
Dynare. On Octave, you can simply install [Homebrew](https://brew.sh/) and run
|
||||
```brew install dynare --HEAD``` (See the Install Dynare (unstable) section of
|
||||
[this webpage](http://www.dynare.org/DynareWiki/InstallOnMacOSX) for more
|
||||
details).
|
||||
|
||||
If you do not wish to use the snapshots provided by Dynare or Homebrew, follow
|
||||
the directions below to build Dynare on your local machine.
|
||||
|
||||
Preparatory work:
|
||||
|
||||
- Install the Xcode Command Line Tools:
|
||||
- Download "Command Line Tools (OS X 10.X) for Xcode," where 10.X corresponds to your OS X version, from https://developer.apple.com/downloads/index.action
|
||||
- Install the latest version of [MacTeX](http://www.tug.org/mactex/), deselecting the option to install Ghostscript
|
||||
- Install [Homebrew](http://mxcl.github.io/homebrew/) by following the instructions on the website
|
||||
- Tap [Homebrew Science](https://github.com/Homebrew/homebrew-science) by opening Terminal and typing:
|
||||
- ```brew tap homebrew/science```
|
||||
- Open Terminal.app and type `xcode-select --install`
|
||||
- Install [Homebrew](https://brew.sh/) by following the instructions on their website
|
||||
|
||||
The following commands will install the programs that Dynare needs to
|
||||
compile. They should be entered at the command prompt in Terminal.app.
|
||||
|
||||
- `brew install automake bison flex boost fftw gcc gsl hdf5 libmatio metis veclibfort`
|
||||
- **(Optional)** To compile Dynare mex files for use on Octave:
|
||||
- ```brew install octave```
|
||||
- ```brew install suite-sparse```
|
||||
- To see the available options for compiling Dynare, type:
|
||||
- ```brew info dynare```
|
||||
- Install Dynare via a command of the form:
|
||||
- (basic) ```brew install dynare --HEAD --without-check```
|
||||
- (with Matlab mex) ```brew install dynare --HEAD --without-check --with-matlab=/Applications/MATLAB_R2015a.app --with-matlab-version=8.5```
|
||||
- **NB**: If compiling Dynare documentation, add ```--with-doc``` to the installation command
|
||||
- **NB**: If not compiling Dynare mex files for Octave, add ```--without-octave``` to the installation command
|
||||
- **NB**: To compile the latest stable version of dynare, follow the same instructions as above, omitting the ```--HEAD``` argument
|
||||
- **NB**: To update a ```--HEAD``` install of dynare you need to uninstall it then install it again: ```brew uninstall dynare; brew install dynare --HEAD```.
|
||||
- **NB**: If you want to maintain a separate git directory of dynare, you can do a ```--HEAD``` install of dynare, then uninstall it. This will have the effect of bringing in all the dependencies you will need to then compile dynare from your git directory. (For `flex` and `bison` it may be necessary to symlink them via `brew link bison --force` and `brew link flex --force` as they are keg-only). Then, change to the git directory and type:
|
||||
- ```autoreconf -si; ./configure --with-matlab=/Applications/MATLAB_R2015a.app MATLAB_VERSION=R2015a```, adjusting the Matlab path and version to accord with your version
|
||||
- Once compilation is done, open Matlab and type the last line shown when you type ```brew info dynare``` in the Terminal window. With the typical Homebrew setup, this is:
|
||||
- ```addpath /usr/local/opt/dynare/lib/dynare/matlab```
|
||||
- `brew install octave`
|
||||
- `brew install suite-sparse`
|
||||
- **(Optional)** To compile Dynare++
|
||||
- `brew install cweb`
|
||||
- **(Optional)** To compile Dynare documentation
|
||||
- Install the latest version of [MacTeX](http://www.tug.org/mactex/), deselecting the option to install Ghostscript
|
||||
- `brew install doxygen latex2html`
|
||||
|
||||
The following commands will download the Dynare source code and compile
|
||||
it. They should be entered at the command prompt in Terminal.app from the
|
||||
folder where you want Dynare installed.
|
||||
|
||||
- `git clone https://github.com/DynareTeam/dynare.git`
|
||||
- `cd dynare`
|
||||
- `PATH="/usr/local/opt/bison/bin:/usr/local/opt/flex/bin:$PATH"`
|
||||
- `autoreconf -si`
|
||||
- `./configure --disable-octave --with-matlab=/Applications/MATLAB_R2017b.app MATLAB_VERSION=R2017b`, adjusting the Matlab path and version to accord with your local installation. If you don't have Matlab, simply type `./configure --disable-octave`
|
||||
- `make -j`
|
||||
- **(Optional)** To then build mex files for Octave, run
|
||||
- `cd mex/build/octave`
|
||||
- `./configure CXXFLAGS="-std=c++0x"`
|
||||
- `make -j`
|
||||
|
|
34
configure.ac
34
configure.ac
|
@ -1,6 +1,6 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
dnl Copyright (C) 2009-2017 Dynare Team
|
||||
dnl Copyright (C) 2009-2018 Dynare Team
|
||||
dnl
|
||||
dnl This file is part of Dynare.
|
||||
dnl
|
||||
|
@ -19,9 +19,11 @@ dnl along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
AC_PREREQ([2.62])
|
||||
AC_INIT([dynare], [4.6-unstable])
|
||||
AC_CONFIG_SRCDIR([preprocessor/DynareMain.cc])
|
||||
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
|
||||
|
||||
|
@ -61,17 +63,6 @@ AX_PROG_LN_S
|
|||
|
||||
AC_PROG_MKDIR_P
|
||||
|
||||
AM_PROG_LEX
|
||||
# Hack to get lex include dir, ticket #575
|
||||
AC_PATH_PROG([LEXPATH], [$LEX])
|
||||
AC_SUBST([LEXINC], [`eval "echo $LEXPATH | sed 's|\(.*\)$LEX$|\1../include|'"`])
|
||||
|
||||
AC_CHECK_PROG([YACC], [bison], [bison])
|
||||
if test "x$YACC" = "x"; then
|
||||
unset YACC # AM_MISSING_PROG needs an unset variable: an empty variable won't do
|
||||
AM_MISSING_PROG([YACC], [bison])
|
||||
fi
|
||||
|
||||
# We need 1.36 because of unordered_{set,hash} used by Dynare++
|
||||
AX_BOOST_BASE([1.36], [], [AC_MSG_ERROR([Can't find Boost >= 1.36])])
|
||||
|
||||
|
@ -121,9 +112,6 @@ if test "x$PDFLATEX" != "x" -a "x$BIBTEX" != "x"; then
|
|||
fi
|
||||
AM_CONDITIONAL([HAVE_BEAMER], [test "x$ax_latex_have_beamer" = "xyes"])
|
||||
|
||||
AC_CHECK_PROG([DOXYGEN], [doxygen], [doxygen])
|
||||
AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$DOXYGEN" != "x"])
|
||||
|
||||
AC_CHECK_PROG([CTANGLE], [ctangle], [ctangle])
|
||||
AM_CONDITIONAL([HAVE_CTANGLE], [test "x$CTANGLE" != "x"])
|
||||
if test "x$CTANGLE" = "x"; then
|
||||
|
@ -166,11 +154,7 @@ AX_PTHREAD
|
|||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
VERSION
|
||||
preprocessor/macro/Makefile
|
||||
preprocessor/Makefile
|
||||
doc/Makefile
|
||||
doc/preprocessor/Makefile
|
||||
doc/macroprocessor/Makefile
|
||||
doc/parallel/Makefile
|
||||
doc/internals/Makefile
|
||||
doc/gsa/Makefile
|
||||
|
@ -220,8 +204,6 @@ AM_CONDITIONAL([ENABLE_ORG_EXPORT], [test "x$enable_org_export" != "x"])
|
|||
|
||||
# Construct final output message
|
||||
|
||||
BUILD_PREPROCESSOR="yes"
|
||||
|
||||
if test "x$ax_blas_ok" = "xyes" -a "x$ax_lapack_ok" = "xyes" -a "x$has_matio" = "xyes"; then
|
||||
if test x"$ax_pthread_ok" = "xyes"; then
|
||||
BUILD_DYNAREPLUSPLUS="yes"
|
||||
|
@ -250,12 +232,6 @@ else
|
|||
BUILD_OTHER_PDF_DOC="no (missing pdflatex)"
|
||||
fi
|
||||
|
||||
if test "x$DOXYGEN" != "x"; then
|
||||
BUILD_DYNARE_PREPROC_DOC="yes"
|
||||
else
|
||||
BUILD_DYNARE_PREPROC_DOC="no (missing doxygen)"
|
||||
fi
|
||||
|
||||
if test "x$enable_org_export" != "x"; then
|
||||
BUILD_DYNARE_INTERNAL_DOC="yes"
|
||||
else
|
||||
|
@ -293,7 +269,6 @@ AC_MSG_NOTICE([
|
|||
Dynare is now configured for building the following components...
|
||||
|
||||
Binaries (with "make"):
|
||||
Dynare preprocessor: $BUILD_PREPROCESSOR
|
||||
Dynare++: $BUILD_DYNAREPLUSPLUS
|
||||
|
||||
PDF documentation (with "make pdf"):
|
||||
|
@ -304,7 +279,6 @@ PDF documentation (with "make pdf"):
|
|||
|
||||
HTML documentation (with "make html"):
|
||||
Dynare reference manual: $BUILD_DYNARE_HTML_MANUAL
|
||||
Dynare preprocessor developer doc: $BUILD_DYNARE_PREPROC_DOC
|
||||
Dynare internal doc: $BUILD_DYNARE_INTERNAL_DOC
|
||||
|
||||
Info documentation (with "make info"): $BUILD_DYNARE_INFO
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
SUBDIRS = preprocessor macroprocessor parallel internals gsa dseries-and-reporting
|
||||
SUBDIRS = parallel internals gsa dseries-and-reporting
|
||||
|
||||
info_TEXINFOS = dynare.texi
|
||||
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
if HAVE_PDFLATEX
|
||||
if HAVE_BEAMER
|
||||
pdf-local: macroprocessor.pdf
|
||||
endif
|
||||
endif
|
||||
|
||||
SRC = macroprocessor.tex new-design.pdf
|
||||
|
||||
EXTRA_DIST = $(SRC)
|
||||
|
||||
macroprocessor.pdf: $(SRC)
|
||||
$(PDFLATEX) macroprocessor
|
||||
$(PDFLATEX) macroprocessor
|
||||
|
||||
clean-local:
|
||||
rm -f macroprocessor.pdf *.toc *.aux *.log *.nav *.snm *.vrb *.out *~
|
|
@ -1,624 +0,0 @@
|
|||
\documentclass{beamer}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage{lmodern}
|
||||
\usepackage{amsmath}
|
||||
\usepackage[copyright]{ccicons}
|
||||
|
||||
\usetheme{Boadilla}
|
||||
|
||||
\title{The Dynare Macro-processor}
|
||||
\subtitle{Dynare Summer School 2017}
|
||||
\author{Sébastien Villemot}
|
||||
%\pgfdeclareimage[height=0.6cm]{logo}{logo-ofce}
|
||||
\institute{OFCE}
|
||||
\date{June 13, 2017}
|
||||
|
||||
\AtBeginSection[]
|
||||
{
|
||||
\begin{frame}
|
||||
\frametitle{Outline}
|
||||
\tableofcontents[currentsection]
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\begin{frame}
|
||||
\titlepage
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Outline}
|
||||
\tableofcontents
|
||||
\end{frame}
|
||||
|
||||
\section{Overview}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Motivation}
|
||||
\begin{itemize}
|
||||
\item The \textbf{Dynare language} (used in MOD files) is well suited for many economic models
|
||||
\item However, as such, it lacks some useful features, such as:
|
||||
\begin{itemize}
|
||||
\item a loop mechanism for automatically repeating similar blocks of equations (such as in multi-country models)
|
||||
\item an operator for indexed sums or products inside equations
|
||||
\item a mechanism for splitting large MOD files in smaller modular files
|
||||
\item the possibility of conditionally including some equations or some runtime commands
|
||||
\end{itemize}
|
||||
\item The \textbf{Dynare Macro-language} was specifically designed to address these issues
|
||||
\item Being flexible and fairly general, it can also be helpful in other situations
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Design of the macro-language}
|
||||
\begin{itemize}
|
||||
\item The Dynare Macro-language provides a new set of \textbf{macro-commands} which can be inserted inside MOD files
|
||||
\item Language features include:
|
||||
\begin{itemize}
|
||||
\item file inclusion
|
||||
\item loops (\textit{for} structure)
|
||||
\item conditional inclusion (\textit{if/else} structures)
|
||||
\item expression substitution
|
||||
\end{itemize}
|
||||
\item The macro-processor transforms a MOD file with macro-commands into a MOD file without macro-commands (doing text expansions/inclusions) and then feeds it to the Dynare parser
|
||||
\item The key point to understand is that the macro-processor only does \textbf{text substitution} (like the C preprocessor or the PHP language)
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Design of Dynare}
|
||||
\includegraphics[width=0.95\linewidth]{new-design.pdf}
|
||||
\end{frame}
|
||||
|
||||
\section{Syntax}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Macro Directives}
|
||||
\begin{itemize}
|
||||
\item Directives begin with an at-sign followed by a pound sign (\verb+@#+)
|
||||
\item A directive produces no output, but gives instructions to the macro-processor
|
||||
\item Main directives are:
|
||||
\begin{itemize}
|
||||
\item file inclusion: \verb+@#include+
|
||||
\item definition a variable of the macro-processor: \verb+@#define+
|
||||
\item conditional statements (\verb+@#if/@#ifdef/@#ifndef/@#else/@#endif+)
|
||||
\item loop statements (\verb+@#for/@#endfor+)
|
||||
\end{itemize}
|
||||
\item In most cases, directives occupy exactly one line of text. In case of need, two anti-slashes (\verb+\\+) at the end of the line indicates that the directive is continued on the next line.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Variables}
|
||||
\begin{itemize}
|
||||
\item The macro processor maintains its own list of variables (distinct of model variables and of MATLAB/Octave variables)
|
||||
\item Macro-variables can be of four types:
|
||||
\begin{itemize}
|
||||
\item integer
|
||||
\item character string (declared between \textit{double} quotes)
|
||||
\item array of integers
|
||||
\item array of strings
|
||||
\end{itemize}
|
||||
\item No boolean type:
|
||||
\begin{itemize}
|
||||
\item false is represented by integer zero
|
||||
\item true is any non-null integer
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Macro-expressions (1/2)}
|
||||
It is possible to construct macro-expressions, using standard operators.
|
||||
\begin{block}{Operators on integers}
|
||||
\begin{itemize}
|
||||
\item arithmetic operators: \texttt{+ - * /}
|
||||
\item comparison operators: \texttt{< > <= >= == !=}
|
||||
\item logical operators: \verb+&& || !+
|
||||
\item integer ranges: \texttt{1:4} is equivalent to integer array \texttt{[1,2,3,4]}
|
||||
\end{itemize}
|
||||
\end{block}
|
||||
|
||||
\begin{block}{Operators on character strings}
|
||||
\begin{itemize}
|
||||
\item comparison operators: \texttt{== !=}
|
||||
\item concatenation: \texttt{+}
|
||||
\item extraction of substrings: if \texttt{s} is a string, then one can write \texttt{s[3]} or \texttt{s[4:6]}
|
||||
\end{itemize}
|
||||
\end{block}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Macro-expressions (2/2)}
|
||||
\begin{block}{Operators on arrays}
|
||||
\begin{itemize}
|
||||
\item dereferencing: if \texttt{v} is an array, then \texttt{v[2]} is its $2^{\textrm{nd}}$ element
|
||||
\item concatenation: \texttt{+}
|
||||
\item difference \texttt{-}: returns the first operand from which the elements of the second operand have been removed
|
||||
\item extraction of sub-arrays: \textit{e.g.} \texttt{v[4:6]}
|
||||
\item testing membership of an array: \texttt{in} operator \\ (example:
|
||||
\texttt{"b" in ["a", "b", "c"]} returns \texttt{1})
|
||||
\end{itemize}
|
||||
\end{block}
|
||||
|
||||
Macro-expressions can be used at two places:
|
||||
\begin{itemize}
|
||||
\item inside macro directives, directly
|
||||
\item in the body of the MOD file, between an at-sign and curly braces (like \verb+@{expr}+): the macro processor will substitute the expression with its value
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Define directive}
|
||||
|
||||
The value of a macro-variable can be defined with the \verb+@#define+ directive.
|
||||
|
||||
\begin{block}{Syntax}
|
||||
\verb+@#define +\textit{variable\_name}\verb+ = +\textit{expression}
|
||||
\end{block}
|
||||
|
||||
\begin{block}{Examples}
|
||||
\begin{verbatim}
|
||||
@#define x = 5 // Integer
|
||||
@#define y = "US" // String
|
||||
@#define v = [ 1, 2, 4 ] // Integer array
|
||||
@#define w = [ "US", "EA" ] // String array
|
||||
@#define z = 3 + v[2] // Equals 5
|
||||
@#define t = ("US" in w) // Equals 1 (true)
|
||||
\end{verbatim}
|
||||
\end{block}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Expression substitution}
|
||||
\framesubtitle{Dummy example}
|
||||
\begin{block}{Before macro-processing}
|
||||
\begin{verbatim}
|
||||
@#define x = [ "B", "C" ]
|
||||
@#define i = 2
|
||||
|
||||
model;
|
||||
A = @{x[i]};
|
||||
end;
|
||||
\end{verbatim}
|
||||
\end{block}
|
||||
\begin{block}{After macro-processing}
|
||||
\begin{verbatim}
|
||||
model;
|
||||
A = C;
|
||||
end;
|
||||
\end{verbatim}
|
||||
\end{block}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Inclusion directive (1/2)}
|
||||
\begin{itemize}
|
||||
\item This directive simply includes the content of another file at the place where it is inserted.
|
||||
\begin{block}{Syntax}
|
||||
\verb+@#include "+\textit{filename}\verb+"+
|
||||
\end{block}
|
||||
\begin{block}{Example}
|
||||
\begin{verbatim}
|
||||
@#include "modelcomponent.mod"
|
||||
\end{verbatim}
|
||||
\end{block}
|
||||
\item Exactly equivalent to a copy/paste of the content of the included file
|
||||
\item Note that it is possible to nest includes (\textit{i.e.} to include a
|
||||
file from an included file)
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Inclusion directive (2/2)}
|
||||
\begin{itemize}
|
||||
\item The filename can be given by a macro-variable (useful in loops):
|
||||
\begin{block}{Example with variable}
|
||||
\begin{verbatim}
|
||||
@#define fname = "modelcomponent.mod"
|
||||
@#include fname
|
||||
\end{verbatim}
|
||||
\end{block}
|
||||
\item Files to include are searched for in current directory. Other directories can
|
||||
be added with
|
||||
\texttt{@includepath} directive, \texttt{-I} command line option or
|
||||
\texttt{[paths]} section in config file.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Loop directive}
|
||||
\begin{block}{Syntax}
|
||||
\verb+@#for +\textit{variable\_name}\verb+ in +\textit{array\_expr} \\
|
||||
\verb+ +\textit{loop\_body} \\
|
||||
\verb+@#endfor+
|
||||
\end{block}
|
||||
\begin{block}{Example: before macro-processing}
|
||||
\small
|
||||
\begin{verbatim}
|
||||
model;
|
||||
@#for country in [ "home", "foreign" ]
|
||||
GDP_@{country} = A * K_@{country}^a * L_@{country}^(1-a);
|
||||
@#endfor
|
||||
end;
|
||||
\end{verbatim}
|
||||
\normalsize
|
||||
\end{block}
|
||||
|
||||
\begin{block}{Example: after macro-processing}
|
||||
\small
|
||||
\begin{verbatim}
|
||||
model;
|
||||
GDP_home = A * K_home^a * L_home^(1-a);
|
||||
GDP_foreign = A * K_foreign^a * L_foreign^(1-a);
|
||||
end;
|
||||
\end{verbatim}
|
||||
\normalsize
|
||||
\end{block}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Conditional inclusion directives (1/2)}
|
||||
|
||||
\begin{columns}[T]
|
||||
\column{0.47\linewidth}
|
||||
\begin{block}{Syntax 1}
|
||||
\verb+@#if +\textit{integer\_expr} \\
|
||||
\verb+ +\textit{body included if expr != 0} \\
|
||||
\verb+@#endif+
|
||||
\end{block}
|
||||
|
||||
\column{0.47\linewidth}
|
||||
\begin{block}{Syntax 2}
|
||||
\verb+@#if +\textit{integer\_expr} \\
|
||||
\verb+ +\textit{body included if expr != 0} \\
|
||||
\verb+@#else+ \\
|
||||
\verb+ +\textit{body included if expr == 0} \\
|
||||
\verb+@#endif+
|
||||
\end{block}
|
||||
\end{columns}
|
||||
|
||||
\begin{block}{Example: alternative monetary policy rules}
|
||||
\scriptsize
|
||||
\begin{verbatim}
|
||||
@#define linear_mon_pol = 0 // or 1
|
||||
...
|
||||
model;
|
||||
@#if linear_mon_pol
|
||||
i = w*i(-1) + (1-w)*i_ss + w2*(pie-piestar);
|
||||
@#else
|
||||
i = i(-1)^w * i_ss^(1-w) * (pie/piestar)^w2;
|
||||
@#endif
|
||||
...
|
||||
end;
|
||||
\end{verbatim}
|
||||
\scriptsize
|
||||
\end{block}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Conditional inclusion directives (2/2)}
|
||||
|
||||
\begin{columns}[T]
|
||||
\column{0.47\linewidth}
|
||||
\begin{block}{Syntax 1}
|
||||
\verb+@#ifdef +\textit{variable\_name} \\
|
||||
\verb+ +\textit{body included if variable defined} \\
|
||||
\verb+@#endif+
|
||||
\end{block}
|
||||
|
||||
\column{0.47\linewidth}
|
||||
\begin{block}{Syntax 2}
|
||||
\verb+@#ifdef +\textit{variable\_name} \\
|
||||
\verb+ +\textit{body included if variable defined} \\
|
||||
\verb+@#else+ \\
|
||||
\verb+ +\textit{body included if variable not defined} \\
|
||||
\verb+@#endif+
|
||||
\end{block}
|
||||
\end{columns}
|
||||
|
||||
\bigskip
|
||||
|
||||
There is also \verb+@#ifndef+, which is the opposite of \verb+@#ifdef+
|
||||
(\textit{i.e.} it tests whether a variable is \emph{not} defined).
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Echo and error directives}
|
||||
|
||||
\begin{itemize}
|
||||
\item The echo directive will simply display a message on standard output
|
||||
\item The error directive will display the message and make Dynare stop (only makes sense inside a conditional inclusion directive)
|
||||
\end{itemize}
|
||||
|
||||
\begin{block}{Syntax}
|
||||
\verb+@#echo +\textit{string\_expr} \\
|
||||
\verb+@#error +\textit{string\_expr}
|
||||
\end{block}
|
||||
|
||||
\begin{block}{Examples}
|
||||
\begin{verbatim}
|
||||
@#echo "Information message."
|
||||
@#error "Error message!"
|
||||
\end{verbatim}
|
||||
\end{block}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Saving the macro-expanded MOD file}
|
||||
\begin{itemize}
|
||||
\item For \textbf{debugging or learning} purposes, it is possible to save the output of the macro-processor
|
||||
\item This output is a valid MOD file, obtained after processing the macro-commands of the original MOD file
|
||||
% \item Useful to understand how the macro-processor works
|
||||
\item Just add the \texttt{savemacro} option on the Dynare command line (after the name of your MOD file)
|
||||
\item If MOD file is \texttt{filename.mod}, then the macro-expanded version will be saved in \texttt{filename-macroexp.mod}
|
||||
\item You can specify the filename for the macro-expanded version with the syntax \texttt{savemacro=mymacroexp.mod}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
% \begin{frame}
|
||||
% \frametitle{Note on error messages}
|
||||
% \end{frame}
|
||||
|
||||
\section{Typical usages}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Modularization}
|
||||
\begin{itemize}
|
||||
\item The \verb+@#include+ directive can be used to split MOD files into several modular components
|
||||
\item Example setup:
|
||||
\begin{description}
|
||||
\item[\texttt{modeldesc.mod}:] contains variable declarations, model equations and shocks declarations
|
||||
\item[\texttt{simulate.mod}:] includes \texttt{modeldesc.mod}, calibrates parameters and runs stochastic simulations
|
||||
\item[\texttt{estim.mod}:] includes \texttt{modeldesc.mod}, declares priors on parameters and runs bayesian estimation
|
||||
\end{description}
|
||||
\item Dynare can be called on \texttt{simulate.mod} and \texttt{estim.mod}
|
||||
\item But it makes no sense to run it on \texttt{modeldesc.mod}
|
||||
\item Advantage: no need to manually copy/paste the whole model (at the beginning) or changes to the model (during development)
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Indexed sums or products}
|
||||
\framesubtitle{Example: moving average}
|
||||
\begin{columns}[T]
|
||||
\column{0.47\linewidth}
|
||||
\begin{block}{Before macro-processing}
|
||||
\begin{verbatim}
|
||||
@#define window = 2
|
||||
|
||||
var x MA_x;
|
||||
...
|
||||
model;
|
||||
...
|
||||
MA_x = 1/@{2*window+1}*(
|
||||
@#for i in -window:window
|
||||
+x(@{i})
|
||||
@#endfor
|
||||
);
|
||||
...
|
||||
end;
|
||||
\end{verbatim}
|
||||
\end{block}
|
||||
\column{0.47\linewidth}
|
||||
\begin{block}{After macro-processing}
|
||||
\begin{verbatim}
|
||||
var x MA_x;
|
||||
...
|
||||
model;
|
||||
...
|
||||
MA_x = 1/5*(
|
||||
+x(-2)
|
||||
+x(-1)
|
||||
+x(0)
|
||||
+x(1)
|
||||
+x(2)
|
||||
);
|
||||
...
|
||||
end;
|
||||
\end{verbatim}
|
||||
\end{block}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Multi-country models}
|
||||
\framesubtitle{MOD file skeleton example}
|
||||
\scriptsize
|
||||
\begin{verbatim}
|
||||
@#define countries = [ "US", "EA", "AS", "JP", "RC" ]
|
||||
@#define nth_co = "US"
|
||||
|
||||
@#for co in countries
|
||||
var Y_@{co} K_@{co} L_@{co} i_@{co} E_@{co} ...;
|
||||
parameters a_@{co} ...;
|
||||
varexo ...;
|
||||
@#endfor
|
||||
|
||||
model;
|
||||
@#for co in countries
|
||||
Y_@{co} = K_@{co}^a_@{co} * L_@{co}^(1-a_@{co});
|
||||
...
|
||||
@# if co != nth_co
|
||||
(1+i_@{co}) = (1+i_@{nth_co}) * E_@{co}(+1) / E_@{co}; // UIP relation
|
||||
@# else
|
||||
E_@{co} = 1;
|
||||
@# endif
|
||||
@#endfor
|
||||
end;
|
||||
\end{verbatim}
|
||||
\normalsize
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Endogeneizing parameters (1/4)}
|
||||
\begin{itemize}
|
||||
\item When doing the steady-state calibration of the model, it may be useful to consider a parameter as an endogenous (and vice-versa)
|
||||
\item Example:
|
||||
\begin{gather*}
|
||||
y = \left(\alpha^{\frac{1}{\xi}} \ell^{1-\frac{1}{\xi}} + (1-\alpha)^{\frac{1}{\xi}}k^{1-\frac{1}{\xi}}\right)^{\frac{\xi}{\xi - 1}} \\
|
||||
lab\_rat = \frac{w \ell}{p y}
|
||||
\end{gather*}
|
||||
\item In the model, $\alpha$ is a (share) parameter, and $lab\_rat$ is an endogenous variable
|
||||
\item We observe that:
|
||||
\begin{itemize}
|
||||
\item calibrating $\alpha$ is not straigthforward!
|
||||
\item on the contrary, we have real world data for $lab\_rat$
|
||||
\item it is clear that these two variables are economically linked
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Endogeneizing parameters (2/4)}
|
||||
\begin{itemize}
|
||||
\item Therefore, when computing the steady state:
|
||||
\begin{itemize}
|
||||
\item we make $\alpha$ an endogenous variable and $lab\_rat$ a parameter
|
||||
\item we impose an economically relevant value for $lab\_rat$
|
||||
\item the solution algorithm deduces the implied value for $\alpha$
|
||||
\end{itemize}
|
||||
\item We call this method ``variable flipping''
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Endogeneizing parameters (3/4)}
|
||||
\framesubtitle{Example implementation}
|
||||
\begin{itemize}
|
||||
\item File \texttt{modeqs.mod}:
|
||||
\begin{itemize}
|
||||
\item contains variable declarations and model equations
|
||||
\item For declaration of \texttt{alpha} and \texttt{lab\_rat}:
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
@#if steady
|
||||
var alpha;
|
||||
parameter lab_rat;
|
||||
@#else
|
||||
parameter alpha;
|
||||
var lab_rat;
|
||||
@#endif
|
||||
\end{verbatim}
|
||||
\normalsize
|
||||
\end{itemize}
|
||||
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{Endogeneizing parameters (4/4)}
|
||||
\framesubtitle{Example implementation}
|
||||
\begin{itemize}
|
||||
\item File \texttt{steadystate.mod}:
|
||||
\begin{itemize}
|
||||
\item begins with \verb+@#define steady = 1+
|
||||
\item then with \verb+@#include "modeqs.mod"+
|
||||
\item initializes parameters (including \texttt{lab\_rat}, excluding \texttt{alpha})
|
||||
\item computes steady state (using guess values for endogenous, including \texttt{alpha})
|
||||
\item saves values of parameters and endogenous at steady-state in a file, using the \texttt{save\_params\_and\_steady\_state} command
|
||||
\end{itemize}
|
||||
\item File \texttt{simulate.mod}:
|
||||
\begin{itemize}
|
||||
\item begins with \verb+@#define steady = 0+
|
||||
\item then with \verb+@#include "modeqs.mod"+
|
||||
\item loads values of parameters and endogenous at steady-state from file, using the \texttt{load\_params\_and\_steady\_state} command
|
||||
\item computes simulations
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{MATLAB/Octave loops vs macro-processor loops (1/3)}
|
||||
Suppose you have a model with a parameter $\rho$, and you want to make
|
||||
simulations for three values: $\rho = 0.8, 0.9, 1$. There are
|
||||
several ways of doing this:
|
||||
\begin{block}{With a MATLAB/Octave loop}
|
||||
\begin{verbatim}
|
||||
rhos = [ 0.8, 0.9, 1];
|
||||
for i = 1:length(rhos)
|
||||
rho = rhos(i);
|
||||
stoch_simul(order=1);
|
||||
end
|
||||
\end{verbatim}
|
||||
\end{block}
|
||||
\begin{itemize}
|
||||
\item The loop is not unrolled
|
||||
\item MATLAB/Octave manages the iterations
|
||||
\item Interesting when there are a lot of iterations
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{MATLAB/Octave loops vs macro-processor loops (2/3)}
|
||||
\begin{block}{With a macro-processor loop (case 1)}
|
||||
\begin{verbatim}
|
||||
rhos = [ 0.8, 0.9, 1];
|
||||
@#for i in 1:3
|
||||
rho = rhos(@{i});
|
||||
stoch_simul(order=1);
|
||||
@#endfor
|
||||
\end{verbatim}
|
||||
\end{block}
|
||||
\begin{itemize}
|
||||
\item Very similar to previous example
|
||||
\item Loop is unrolled
|
||||
\item Dynare macro-processor manages the loop index but not the data array (\texttt{rhos})
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile=singleslide]
|
||||
\frametitle{MATLAB/Octave loops vs macro-processor loops (3/3)}
|
||||
\begin{block}{With a macro-processor loop (case 2)}
|
||||
\begin{verbatim}
|
||||
@#for rho_val in [ "0.8", "0.9", "1"]
|
||||
rho = @{rho_val};
|
||||
stoch_simul(order=1);
|
||||
@#endfor
|
||||
\end{verbatim}
|
||||
\end{block}
|
||||
\begin{itemize}
|
||||
\item Advantage: shorter syntax, since list of values directly given in the loop construct
|
||||
\item Note that values are given as character strings (the macro-processor does not
|
||||
know floating point values)
|
||||
\item Inconvenient: can not reuse an array stored in a MATLAB/Octave variable
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
% \begin{frame}[fragile=singleslide]
|
||||
% \frametitle{Possible future developments}
|
||||
% \begin{itemize}
|
||||
% \item Find a nicer syntax for indexed sums/products
|
||||
% \item Implement other control structures: \texttt{elsif}, \texttt{switch/case}, \texttt{while/until} loops
|
||||
% \item Implement macro-functions (or templates), with a syntax like:
|
||||
% \small
|
||||
% \verb+@#define QUADRATIC_COST(x, x_ss, phi) = phi/2*(x/x_ss-1)^2+
|
||||
% \normalsize
|
||||
% \end{itemize}
|
||||
% \end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\begin{center}
|
||||
\vfill {\LARGE Thanks for your attention!} \vfill
|
||||
{\LARGE Questions?}
|
||||
\vfill
|
||||
\end{center}
|
||||
\vfill
|
||||
\begin{columns}[T]
|
||||
\column{0.2\textwidth}
|
||||
\column{0.09\textwidth}
|
||||
|
||||
\ccbysa
|
||||
\column{0.71\textwidth}
|
||||
\tiny
|
||||
Copyright © 2008--2017 Dynare Team \\
|
||||
Licence: \href{http://creativecommons.org/licenses/by-sa/4.0/}{Creative
|
||||
Commons Attribution-ShareAlike 4.0}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
|
||||
\end{document}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,346 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="862.10712"
|
||||
height="382.82141"
|
||||
id="svg5540"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.45.1"
|
||||
version="1.0"
|
||||
sodipodi:docbase="K:\Commun\Villemot\Macroprocessor"
|
||||
sodipodi:docname="new-design.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
inkscape:export-filename="K:\Commun\Villemot\Macroprocessor\new-design.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs5542">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3243"
|
||||
d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.7"
|
||||
inkscape:cx="488.94636"
|
||||
inkscape:cy="380.52134"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
width="1052.3622px"
|
||||
height="744.09448px"
|
||||
inkscape:window-width="1024"
|
||||
inkscape:window-height="712"
|
||||
inkscape:window-x="-4"
|
||||
inkscape:window-y="-4" />
|
||||
<metadata
|
||||
id="metadata5545">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Calque 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-78.642861,-39.058769)">
|
||||
<g
|
||||
id="g4418"
|
||||
transform="translate(467.50002,289.64286)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4420"
|
||||
y="56.6479"
|
||||
x="361.42862"
|
||||
style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4422"
|
||||
y="56.6479"
|
||||
x="361.42862"
|
||||
sodipodi:role="line">Matlab files</tspan><tspan
|
||||
id="tspan4424"
|
||||
y="81.6479"
|
||||
x="361.42862"
|
||||
sodipodi:role="line">representing</tspan><tspan
|
||||
id="tspan4426"
|
||||
y="106.6479"
|
||||
x="361.42862"
|
||||
sodipodi:role="line">the model</tspan></text>
|
||||
<path
|
||||
transform="matrix(1.0528522,0,0,1.0682674,-22.862484,-9.0197689)"
|
||||
d="M 431.42857 79.808769 A 66.428574 51.42857 0 1 1 298.57143,79.808769 A 66.428574 51.42857 0 1 1 431.42857 79.808769 z"
|
||||
sodipodi:ry="51.42857"
|
||||
sodipodi:rx="66.428574"
|
||||
sodipodi:cy="79.808769"
|
||||
sodipodi:cx="365"
|
||||
id="path4428"
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
<g
|
||||
id="g4430"
|
||||
transform="translate(-555.35711,282.49999)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4432"
|
||||
y="65.21933"
|
||||
x="691.42859"
|
||||
style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
|
||||
xml:space="preserve"><tspan
|
||||
y="65.21933"
|
||||
x="691.42859"
|
||||
id="tspan4434"
|
||||
sodipodi:role="line">Output:</tspan><tspan
|
||||
id="tspan4436"
|
||||
y="90.21933"
|
||||
x="691.42859"
|
||||
sodipodi:role="line">Results,</tspan><tspan
|
||||
id="tspan4438"
|
||||
y="115.21933"
|
||||
x="691.42859"
|
||||
sodipodi:role="line">Graphics</tspan></text>
|
||||
<path
|
||||
d="M 747.14283 85.523056 A 54.285713 51.42857 0 1 1 638.5714,85.523056 A 54.285713 51.42857 0 1 1 747.14283 85.523056 z"
|
||||
sodipodi:ry="51.42857"
|
||||
sodipodi:rx="54.285713"
|
||||
sodipodi:cy="85.523056"
|
||||
sodipodi:cx="692.85712"
|
||||
id="path4440"
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
<g
|
||||
id="g4452"
|
||||
transform="translate(-25.357118,291.07143)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4454"
|
||||
y="68.076462"
|
||||
x="525.71436"
|
||||
style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
|
||||
xml:space="preserve"><tspan
|
||||
y="68.076462"
|
||||
x="525.71436"
|
||||
id="tspan4456"
|
||||
sodipodi:role="line">Dynare</tspan><tspan
|
||||
id="tspan4458"
|
||||
y="93.076462"
|
||||
x="525.71436"
|
||||
sodipodi:role="line">Matlab routines</tspan></text>
|
||||
<rect
|
||||
y="36.951626"
|
||||
x="448.57144"
|
||||
height="75.714287"
|
||||
width="152.85715"
|
||||
id="rect4460"
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<path
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 757.92859,365.8802 L 577.07147,365.8802"
|
||||
id="path4466"
|
||||
inkscape:connector-type="polyline"
|
||||
inkscape:connection-end="#g4452"
|
||||
inkscape:connection-start="#g4418" />
|
||||
<path
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 422.21432,366.33835 L 192.78572,367.69591"
|
||||
id="path4468"
|
||||
inkscape:connector-type="polyline"
|
||||
inkscape:connection-start="#g4452"
|
||||
inkscape:connection-end="#g4430" />
|
||||
<g
|
||||
id="g6668">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4470"
|
||||
y="117.30877"
|
||||
x="143.92857"
|
||||
style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
|
||||
xml:space="preserve"><tspan
|
||||
y="117.30877"
|
||||
x="143.92857"
|
||||
id="tspan4472"
|
||||
sodipodi:role="line">MOD file</tspan><tspan
|
||||
id="tspan4474"
|
||||
y="142.30877"
|
||||
x="143.92857"
|
||||
sodipodi:role="line">with macro</tspan><tspan
|
||||
id="tspan4482"
|
||||
y="167.30877"
|
||||
x="143.92857"
|
||||
sodipodi:role="line">commands</tspan></text>
|
||||
<path
|
||||
transform="matrix(1.0725676,0,0,0.999374,99.5973,-252.25554)"
|
||||
d="M 98.57143 390.52304 A 58.57143 56.42857 0 1 1 -18.57143,390.52304 A 58.57143 56.42857 0 1 1 98.57143 390.52304 z"
|
||||
sodipodi:ry="56.42857"
|
||||
sodipodi:rx="58.57143"
|
||||
sodipodi:cy="390.52304"
|
||||
sodipodi:cx="40"
|
||||
id="path4504"
|
||||
style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
<g
|
||||
id="g5516"
|
||||
transform="translate(316.78572,-245.35715)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4476"
|
||||
y="368.38019"
|
||||
x="307.14285"
|
||||
style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
|
||||
xml:space="preserve"><tspan
|
||||
y="368.38019"
|
||||
x="307.14285"
|
||||
id="tspan4478"
|
||||
sodipodi:role="line">MOD file</tspan><tspan
|
||||
id="tspan4480"
|
||||
y="393.38019"
|
||||
x="307.14285"
|
||||
sodipodi:role="line">without macro</tspan><tspan
|
||||
id="tspan4484"
|
||||
y="418.38019"
|
||||
x="307.14285"
|
||||
sodipodi:role="line">commands</tspan></text>
|
||||
<path
|
||||
transform="translate(-8.5714286,-4.2857143)"
|
||||
d="M 389.99999 391.95163 A 72.85714 65 0 1 1 244.28571,391.95163 A 72.85714 65 0 1 1 389.99999 391.95163 z"
|
||||
sodipodi:ry="65"
|
||||
sodipodi:rx="72.85714"
|
||||
sodipodi:cy="391.95163"
|
||||
sodipodi:cx="317.14285"
|
||||
id="path5475"
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
<g
|
||||
id="g5510"
|
||||
transform="translate(243.92858,-236.78572)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4486"
|
||||
y="372.66592"
|
||||
x="165.71428"
|
||||
style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4490"
|
||||
y="372.66592"
|
||||
x="165.71428"
|
||||
sodipodi:role="line">Macro</tspan><tspan
|
||||
id="tspan4492"
|
||||
y="397.66592"
|
||||
x="165.71428"
|
||||
sodipodi:role="line">Processor</tspan></text>
|
||||
<rect
|
||||
y="339.80878"
|
||||
x="110"
|
||||
height="72.85714"
|
||||
width="115.71429"
|
||||
id="rect5477"
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<g
|
||||
id="g5523"
|
||||
transform="translate(372.5,-249.64286)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4494"
|
||||
y="368.38019"
|
||||
x="455.71426"
|
||||
style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
|
||||
xml:space="preserve"><tspan
|
||||
y="368.38019"
|
||||
x="455.71426"
|
||||
id="tspan4496"
|
||||
sodipodi:role="line">Parser,</tspan><tspan
|
||||
id="tspan4498"
|
||||
y="393.38019"
|
||||
x="455.71426"
|
||||
sodipodi:role="line">Analytical</tspan><tspan
|
||||
id="tspan4500"
|
||||
y="418.38019"
|
||||
x="455.71426"
|
||||
sodipodi:role="line">derivator...</tspan></text>
|
||||
<rect
|
||||
y="339.80878"
|
||||
x="395.71429"
|
||||
height="94.285713"
|
||||
width="120"
|
||||
id="rect5479"
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<path
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 206.35715,138.3618 L 352.92858,139.13938"
|
||||
id="path5532"
|
||||
inkscape:connector-type="polyline"
|
||||
inkscape:connection-end="#g5510"
|
||||
inkscape:connection-start="#g6668" />
|
||||
<path
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 470.64287,140.23901 L 551.5,141.32071"
|
||||
id="path5534"
|
||||
inkscape:connector-type="polyline"
|
||||
inkscape:connection-start="#g5510"
|
||||
inkscape:connection-end="#g5516" />
|
||||
<path
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 699.21428,140.48835 L 767.21429,138.81229"
|
||||
id="path5536"
|
||||
inkscape:connector-type="polyline"
|
||||
inkscape:connection-start="#g5516"
|
||||
inkscape:connection-end="#g5523" />
|
||||
<path
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 828.36474,185.45163 L 828.75359,309.8802"
|
||||
id="path5538"
|
||||
inkscape:connector-type="polyline"
|
||||
inkscape:connection-end="#g4418"
|
||||
inkscape:connection-start="#g5523" />
|
||||
<rect
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:1.5, 4.5;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect5596"
|
||||
width="634.28571"
|
||||
height="201.42857"
|
||||
x="305.71429"
|
||||
y="39.808769" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
|
||||
x="404.28574"
|
||||
y="232.66591"
|
||||
id="text6567"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6569"
|
||||
x="404.28574"
|
||||
y="232.66591">Dynare preprocessor</tspan></text>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 17 KiB |
|
@ -1,16 +0,0 @@
|
|||
if HAVE_PDFLATEX
|
||||
if HAVE_BEAMER
|
||||
pdf-local: preprocessor.pdf
|
||||
endif
|
||||
endif
|
||||
|
||||
SRC = preprocessor.tex expr.png expr-sharing.png matrices.png overview.png json-preprocessor.png
|
||||
|
||||
EXTRA_DIST = $(SRC)
|
||||
|
||||
preprocessor.pdf: $(SRC)
|
||||
$(PDFLATEX) preprocessor
|
||||
$(PDFLATEX) preprocessor
|
||||
|
||||
clean-local:
|
||||
rm -f *.pdf *.toc *.aux *.log *.nav *.snm *.vrb *.out *~
|
Binary file not shown.
Before Width: | Height: | Size: 11 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0" version="6.0.1.9" editor="www.draw.io" type="device"><diagram name="Page-1">7VlJc5swFP41HNsB4QUfE2fpoZ3JTA5NjirIoEZGVMg2zq+vhMSOWhI7uPWYgy19T+v3Fp6E5S7X2T2DSfSNBohYwA4yy72xAJiDqfiVwF4BM9tVQMhwoCCnAh7xK9KgrdENDlDaaMgpJRwnTdCncYx83sAgY3TXbLaipDlrAkPUAR59SLrodxzwSKHe1K7wLwiHUTGzY2vJD+i/hIxuYj2fBdxV/ijxGhZj6fZpBAO6q0HureUuGaVcldbZEhFJbUGb6ndnkJbrZijmQzp4qsMWkg0qVjwjout1gLeSdcw1J7NfG7mo6wdJHbDdRQWJUqj/q67vgRKG2tCKio0Invi+tQ4p+JTmlnMl12MnmXlFaQLjErsFludZi3khFOw05BWsJu/APcsUaM9+DkFBY9dAqE0Yv6hc7yLM0WMCfSnZCfcTWMTXRNQcUYRpojxihTMUyL1zRl/QkhLK8qFcO38khZiQGn6XPwIPGQywMKBCFtMYlWuq25Y2ty1iHGU1SNvaPaJrxNleNNFSd67tXseFia7uKicrfCyq+VeBQe3WYTlwZdqioK3b4BqzLqeBcHpd1XvMXVfSdiMJ8uka+7pcoxhlmD9pWJafCzwWa3qqV551q9LNZeUn4nyvYx7ccCogynhEQxpD8pXSRI9gVpxREyndMF/vbqHjJmQhKuOUwuTG/6guhgjkeNuMhgexPz86+46JfftfZR+civ2FMcofGl7N0fIs4xfwmvHLcUYMYN7xA9jnqdGJlOjUblTw2/Aj92RRzDY60gGpC5j0+Rah4RszkbP0uMnshB7njKdu56JsEV5BS9mLEZUNxlP260XZ4iwwOaGy3Y9Qdn+StL8ouyeMj6nsSY+y2yzHwZW8NxI1n8A0lVlTndxG7mMm9u0nw0FZkNdNghYDc6CB/A5OlfQMDxTnPmEI3K7T0pvaje5Vv49qD9S6IACz1kCKg85AuQ2U2x5mFtPRzWL4kfW9ZlHwfrGLd9tFyfTZXFW0jOHvh66ey4tFvxkd/YjV54T/9zXdMdivfRv44BOu+aro6FlwIqg+j9Sokwf1KNmYGpWp0Ph34kV0HkPb4KJr+Xoe7TZDVKvPiOo1WH2qdW9/Aw==</diagram></mxfile>
|
Binary file not shown.
Before Width: | Height: | Size: 9.2 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0" version="6.0.1.9" editor="www.draw.io" type="device"><diagram name="Page-1">7VhLc5swEP41HNsBKXbwMXGS9tDOZCaHJkcVZFAjIypkG+fXd4XEGzJOnJI2Yw629K0eu98+EHLwcp1/kSSNv4uQcge5Ye7gKwehczSDXw3sDTB3sQEiyUIDeTVwx56oBV2LblhIs9ZAJQRXLG2DgUgSGqgWRqQUu/awleDtXVMS0R5wFxDeR3+wUMUG9WdujX+lLIrLnT3XSn6S4DGSYpPY/RyEV8VjxGtSrmXHZzEJxa4B4WsHL6UQyrTW+ZJyTW1Jm5l3MyKt9JY0UYdM8M2ELeEbWmo85zD1MmRbzTpTlpP5741W6vJWU4dcvKghaEX2v576GiiVtAutBBgCPKl9Rw8t+JQVkXOh9XHTfFyjLCVJhV0jx/edxXkpBHZa8ho2m/fgATUBHbDnGBS1rEbgNgh+6FzuYqboXUoCLdlB+gEWqzWHngdNkqUmI1Ysp6G2XUnxSJeCC1kshd3i0RQyzhv4TfEAHkkSMgigUpaIhFY6balUNB8NN68KYqgNVKypknsYYiegMxv3ti5g293VSVbmWNzIrxIjNq2jauE6tKFho3skNeZ9TkNIetu1Nhapq2m70gQFYs0C225QTHOm7i2s2w8lnoBO983Ogx1Vpbnu/KJK7W3NIxslABJSxSISCeHfhEjtCuOOM5Zo9Z/3A1grNjKwoxa2kBIZ0apwDbtLUk4U27aXP4r98zdn3xtj3/1v2EcTsb8YrfLHltfxavkh65c3a9ev6r0/RQHz376AfZ6NJpER/XNpVJ4QW3mEp6pi7mgiHXF0QWdDucVF9MKTyIfMOIzfMeO86dztnZwN76mOr/0JfY2m8/XTydeoLqbv4Wz8N5w9fEban5w9UMWndPbZgLO7LCfhhb42gl7ASZbpQ1OT3NbRZ5zYl38Yvu4Q5PfPQIth/g/k9+CTkt3hVrAiJ4brNnY7bjO620nN26jOOl7neqDnf2Nxb6EiBCqrD4uK2eRRcfgH65tFhec6p7B4JiygW9+1muH1fTa+/gM=</diagram></mxfile>
|
Binary file not shown.
Before Width: | Height: | Size: 51 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:51.0) Gecko/20100101 Firefox/51.0" version="6.0.3.0" editor="www.draw.io" type="device"><diagram name="Page-1">7Vxtc5s4EP41/tgMCPPij7ET96bTXDKTm2n7UcaKTYORR8iJc7/+BEgYJNnGiQw4vUxnCosEaPfZZ1cr4YEzWW2/Erhe3uE5igfAmm8Hzs0AANsCFvsvk7wVEm/kFoIFiea80U7wGP2LRE8u3URzlNYaUoxjGq3rwhAnCQppTQYJwa/1Zk84rj91DRdIETyGMFalP6I5XRbSwLV28r9QtFiKJ9sWvzKD4fOC4E3CnzcAzlP+V1xeQXEv3j5dwjl+rYic24EzIRjT4mi1naA4061QW9Fvuudq+d4EJbRJBxAA/iL0TQwezZku+GmCE/bfOB8RyvrY7CzEqyhkxxY7XtJVzMVoG9GfleNfWZMrNztLKHn7yXvkJ7trpQaya78RpW8cDnBDMRNhQpd4gRMYf8d4zW+fUoKf0QTHmOTv7Fj5H7uiKoDrJMUbEvIR8jFTSBaItwK+Uwiz0Vc6crV9RXiF2HuzBgTFkEYvdaRADrhF2W6ndHbA9b7HBsUtXmC84Te9WuF5BtuI2QB4MXvF8YywowUtR1i1Vxwzv8jM9LqMKHpcw3ycr8w16wZStDad2hN7ckhrL4hQtD2oD351yHtwj3c4wF937mMPuWxZcR3hUh9RYKAocAVDgr+g7RrmsAXWJWrU863OVApcrwkvHGEC7v2cC+waE+yI4Re/gWEmqHNWM14QJFBjBtc1zQx512tC4FulwRpHCU0rd37IBBUHA3U4iJgz3dPetuxD7dlB8Qb63o5bf5rv1odTqI13knBVqqQR1OzhYajtzH67k1asayQKNYVbIxjZvooiO+gsvASjVkP82R1bq8h3GQUEXhee7AwlT/b9g54stxdp8r72ABxsX/f893isrwTcyRKFz0z0ANO0QYA9Nax642t7yl5/zAJ4XJHz3NpIuAUWqFvF9dV4CzTxdmgk3p6Yh1ufIQ8XpFgjylFnRDmyTrPBJyVKjVE6IkrXOo0o5fadE6U6M/mHwCR9wmR12WTpeJJl2iVL508ky5HGL63uyLLdwlFfyVJnlG7I0pNd8ghZyu07J8uRQpYTvFpvaJQsLpssXSDNxNsly6BNR7X7QZZCm1W/9Ixnlu/y08A5zU/l9sCzjfodcFutD/QYIMB4jaYTgDicSY0BxGt1XtRngPifAyB80c8YQCwlcv8gLAwz0f2Gsgh+oXHbC7qc5KhFtjtIYzhjHe9DChm4wPTbJo7goFjXapId9XRhS6fXs61sqXNy1mec/xMEcOkKBaNhewr11Lx9FiUwf78LV6PjtYnLofEoa9WiLGinqjGd8jA7h+myfNPs5AFSikiSS4DVeDktcDWRuBeBWCyEcLzwhWJTYVWMu+JYpSsJTxIhwcoey8ItDwz8VISH4uzq6kr0Z4LZzhmPuicDxjo7DDez9/homXhJsXqa/zH5gsB5xCAgrnGsC/FNRFBII5zkl0jmiuO0QObIjOdLhhwCNSAF9pkCvS2Wfip2XjPUZkXiL+kahdET8/HMiLKdCFoTlLJRw1w5wMJPg8vc6lJmACIjGLYYwJgZNY4m6ymZX2cbCzMviGGaZrRbU0+VO2vMt58g91U338GXtRU0Aaij7FjRrntAuaeRqGbjyh7vOrKXRF3eke4zku5TKEG5z+kbbaTnWLXp1cenS0BH7G3gTbstyzASa9VxgcRa6Ob1q77A064XZz2v2U6no7ARZZhj8HxXyc5XAfP5d+26mkTQNl6SaZ6wt1pY7+sKmNYqHS2B2XLB5khhTG7f9RJYqctKZHiAJM1XwC6yhCbtCm+3giYCTVWbmsR6ghM2oLRIoZnjnJpC91Hvjoi80qJRTfG6oGpG8Wrt8mMJzn7S0pc6DjFn893gnia5br4bvJ3sRd6n7ViSAZumL7YtcVsgvYuh7Freli6eY261Si3wGgaf43hec/D5Stw2VRgTldcqPoN+wdOTduSV+8ZOzq4leA5H0o0MwdMTk7NzrbZryuWfFJ5As5G0Z/CUtzG6cvjrOzyNr/WLJZA/AJ6aD0L+h6dheJreaeCr7KlL6b9HM5KvQB5f2niNVjHMZ+oVBFczcz6P12X5h+tux6sbJ+Tz8swTqEuTQLdCIVaCP1bpUEnh5i1h42Gyh2wVAocoTdm4gXW7ReGGwlmjmVMbyk8ZtCmviwDnPNZwVVtYGlsErgFbiE9Udba4yz57rlijD1PXHXiaFw2Of/d8tpqBmPX8WZVV3XfPHX6wegDiEt08Lpl43jvGV0gnhjMUj8sfB5GeZIKSpMqnrTqNH2icpmz4sY9BTvwgp8nelUO/HQDOVAsvc9PGSebJ5fLA07ia25preYprfXu8/3vQ/n4BBdoa1e1Fuy1Xvc64X4Cd7n6Pp8hZdz965Nz+Bw==</diagram></mxfile>
|
Binary file not shown.
Before Width: | Height: | Size: 28 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0" version="6.0.1.9" editor="www.draw.io" type="device"><diagram name="Page-1">5ZhNj5swEIZ/DXeMycdem/3oYbetlErdPbowMe4aJnLMQvrra2BIQr2pKnXFqoRDYr8e2+PHk1coAV/l9Z0R2+wBU9BBFKZ1wK+DKFouQvfZCPtOWES8E6RRaSexo7BWP4FEmidLlcJuEGgRtVXboZhgUUBiB5owBqth2Ab1cNetkOAJ60RoX/2mUpvRsWbhUf8ISmb9ziykke8ieZYGy4L2CyK+aZ9uOBf9WhS/y0SK1YnEbwK+Moi2a+X1CnSDtsfWzbs9M3rI20Bh/2bCFaVh9/3RIXUkqFtg4b4+tOeBZkboegnmKqF2ZnPtmsw1oVb2keSm/dTrhTX7x9POE0Udzt50foC1eyoEUVp0EhqbocRC6HvELa2wswafYYUaTZsvD9vHjXQnadI/y4KkHZYmoaiIqksYCRTFD/fgyhswB5ezCzGghVUvw9UFFZo8xB1huwbxPnNZ4ZvDZ+fgh/8L/Hgk+LT1i9AlLfogrFG1fyVaO9dpbqLKlIX1VrTZV873hndwHs5GaX2i37aP06URqXJ8+jG6ccoMjIX6zzR9TjQh6g2Y/Le3m+poZmxJWnZiZL3B/QtZ7pG9xwqMk74aJQpZatF0poT7akibsRFxM+YzvCwLj30XmY1l4dGlW/gr8OcjwY89o/mEJhd6YuYSz97TXfilF/jML/DlWO4SX7q1vwJ/MRL8mecu633erOLwTstgfn99GfVtce5h/nworIlxnrN35LzwOH/BnWp/MVF4DRtVOI4TA86iIXAejwh86b+dgBTTBh7PxwPuuse/ydqxk78i+c0v</diagram></mxfile>
|
Binary file not shown.
Before Width: | Height: | Size: 54 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:51.0) Gecko/20100101 Firefox/51.0" version="6.0.2.15" editor="www.draw.io" type="device"><diagram name="Page-1">7Vtbc9o4FP41PG7HkrGBx0JK9yGZZoadafuo2AJ7a1seWQTor98jW/JNpCWNsYFsJjORjo9uR5/OTcrIXsT7z5ykwQPzaTTClr8f2XcjjJGFLfgjKYeC4rqzgrDhoa+YKsIq/El1S0Xdhj7NGoyCsUiEaZPosSShnmjQCOds12Rbs6g5ako21CCsPBKZ1K+hL4KCOnWsiv43DTeBHhlZ6ssT8X5sONsmarwRttf5T/E5JrovxZ8FxGe7Gsn+NLIXnDFRlOL9gkZStlpsRbvlC1/LeXOaiFMauE7R4plEW7X2u0MCzYH2yGnKmUezjPERdiPocP4kSxtZUvMXBy2zbBfGEUmgNg9EHAERQXHNErFSTBbUvSCM/HtyYFs5v0yAvHRtHjAe/gR+ohvDZy4UOrArewujaMEimI99l7BirLLRSnamhuE0g2aPWg6oJN2TTOipsCgiaRY+5ZOTLDHhmzCZMyFYrJj0qpbmyD7JAuqXU+XsB9UcsO1W/lMKqr4lapeeKRd0XyOpLfpMWUwFPwCL/jpVcDk0j8muwuZYswQ1XNpInwl1HjZl1xUmoKBgcRwiU2xsNfXhtKiqEkaO+VIaHotDT0mwBga6D8W3Wvm7ZPngyFoCs/qmWuSV6lt5RuS3f6kQBwUJshUMSIyLgG1YQqJ7xtI/34+MbbmnVqjWDPjbUMU1sQuaXPwvN43TiIjwualK3rID2DijH2LmS70Wwhb8/mRCb6A45S7tglDQVUryZe5Adzf3xxDacokWaNENiO0Whh0TxGh8BMSa700YNiQYE4+zv+g+JTlssXUDInWc/iQ6cTvXCkoTKL2AGlqhUhLftWIeQCugI2oBOUOpBWTqBTB4WZhsTgDwa2Hrzj+i5bJlgivvphs4O008u0c0BD6C53EXeJ68Rzw7R/A8GQzPpi8aJoJyWHI+XAoeHKwGBmWJiXC27lGJW9Zy2ZVzZ49bhhH3aBgn0/cI+8kR2E8Hg/3EgP0ioBDJQARGsuxGdDma9anMnc5Rffkhi0ZwI2ZBXaM6b/qRc3KoMaQMFHVW6/lREiowjGdNMOBpKyvxG/6p09r9YgIVFsqVnHbizHDgH06SbM14fFunrlcXSmcg3pctmZmnDo8HsyUz05awON2KPCi4ZmQ7uGVP7D6R/R7tiRZmHdk6jT+wPXGnr7MnbX4069agTLtPhlwnPnDnXvQw+MAd46P75MKV4qPz5MIg+HCtTuGhJVWz2l85mGAgfdkKsN43YrP79UaRIaPb90a159k4c1bXZ+7ke6uxgetXJPTIGlhH8o5fOrA50ynO62Uk9RzU9jh6TOphM6P0QEREnqDhF0+QZ6lZZI70vPLs8qZrYjXlafd41XXk9hDazPNfa1WcPmwtr1qe5QOWPgTqmlHqPExIPr8rF+Okz9z97B1aOJ3RbOTuO49KT94CjZg3WTihk48v8F2JjTvm3Z3tQYd9Zuxbv8A+Ggr7ton9ywi4y71vZedeCqhQW2/a3UZU2tv6Hx7DqUbbUI3ly9IH+fjqNW9LLzG6xW0MH3t+da7odtZ9dHv5GSUN5obtx0MBfGp6sbC+4qIFCpTIu8T8Vcpgbw27tPaodSd7xseGUK1ewBfav/o3A/vTfw==</diagram></mxfile>
|
|
@ -1,820 +0,0 @@
|
|||
\documentclass{beamer}
|
||||
%\documentclass[draft]{beamer}
|
||||
%\documentclass[handout]{beamer}
|
||||
|
||||
|
||||
\mode<handout>
|
||||
{
|
||||
\usepackage{pgfpages}
|
||||
\pgfpagesuselayout{4 on 1}[a4paper,border shrink=3mm,landscape]
|
||||
\usetheme{Madrid}
|
||||
\usecolortheme{seagull}
|
||||
}
|
||||
|
||||
\mode<beamer>
|
||||
{
|
||||
\usetheme{Madrid}
|
||||
\setbeamercovered{transparent}
|
||||
}
|
||||
|
||||
|
||||
\usepackage[english]{babel}
|
||||
\usepackage[utf8]{inputenc}
|
||||
|
||||
\usepackage{times}
|
||||
\usepackage[copyright]{ccicons}
|
||||
|
||||
\title{The Dynare Preprocessor}
|
||||
|
||||
\author[S. Villemot, H.Bastani]{Sébastien Villemot \and Houtan Bastani}
|
||||
|
||||
\institute{CEPREMAP}
|
||||
|
||||
\date{1 February 2017}
|
||||
|
||||
\AtBeginSection[]
|
||||
{
|
||||
\begin{frame}{Outline}
|
||||
\tableofcontents[currentsection]
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\begin{frame}
|
||||
\titlepage
|
||||
|
||||
\begin{columns}[T]
|
||||
\column{0.2\textwidth}
|
||||
\column{0.09\textwidth}
|
||||
|
||||
\ccbysa
|
||||
\column{0.71\textwidth}
|
||||
\tiny
|
||||
Copyright © 2007--2017 Dynare Team \\
|
||||
Licence: \href{http://creativecommons.org/licenses/by-sa/4.0/}{Creative
|
||||
Commons Attribution-ShareAlike 4.0}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Overview}
|
||||
\begin{center}
|
||||
\includegraphics[width=11cm]{overview.png}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Outline}
|
||||
\tableofcontents
|
||||
\end{frame}
|
||||
|
||||
\section{Invoking the preprocessor}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Calling Dynare}
|
||||
\begin{itemize}
|
||||
\item Dynare is called from the host language platform with the syntax \texttt{dynare <<filename>>.mod}
|
||||
\item This call can be followed by certain options:
|
||||
\begin{itemize}
|
||||
\item Some of these options impact host language platform functionality, \textit{e.g.} \texttt{nograph} prevents graphs from being displayed in Matlab
|
||||
\item Some cause differences in the output created by default, \textit{e.g.} \texttt{notmpterms} prevents temporary terms from being written to the static/dynamic files
|
||||
\item While others impact the functionality of the macroprocessor or the preprocessor, \textit{e.g.} \texttt{nostrict} shuts off certain checks that the preprocessor does by defalut
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\section{Parsing}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Parsing overview}
|
||||
\begin{itemize}
|
||||
\item Parsing is the action of transforming an input text (a \texttt{mod} file in our case) into a data structure suitable for computation
|
||||
\item The parser consists of three components:
|
||||
\begin{itemize}
|
||||
\item the \alert{lexical analyzer}, which recognizes the ``words'' of the \texttt{mod} file (analog to the \textit{vocabulary} of a language)
|
||||
\item the \alert{syntax analyzer}, which recognizes the ``sentences'' of the \texttt{mod} file (analog to the \textit{grammar} of a language)
|
||||
\item the \alert{parsing driver}, which coordinates the whole process and constructs the data structure using the results of the lexical and syntax analyses
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Lexical analysis}
|
||||
\begin{itemize}
|
||||
\item The lexical analyzer recognizes the ``words'' (or \alert{lexemes}) of the language
|
||||
\item Defined in \texttt{DynareFlex.ll}, it is transformed into C++ source code by the program \texttt{flex}
|
||||
\item This file details the list of known lexemes (described by regular expressions) and the associated \alert{token} for each of them
|
||||
\item For punctuation (semicolon, parentheses, \ldots), operators (+, -, \ldots) or fixed keywords (\textit{e.g.} \texttt{model}, \texttt{varexo}, \ldots), the token is simply an integer uniquely identifying the lexeme
|
||||
\item For variable names or numbers, the token also contains the associated string for further processing
|
||||
%\item \textit{Note:} the list of tokens can be found at the beginning of \texttt{DynareBison.yy}
|
||||
\item When invoked, the lexical analyzer reads the next characters of the input, tries to recognize a lexeme, and either produces an error or returns the associated token
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Lexical analysis}
|
||||
\framesubtitle{An example}
|
||||
\begin{itemize}
|
||||
\item Suppose the \texttt{mod} file contains the following:
|
||||
\begin{verbatim}
|
||||
model;
|
||||
x = log(3.5);
|
||||
end;
|
||||
\end{verbatim}
|
||||
\item Before lexical analysis, it is only a sequence of characters
|
||||
\item The lexical analysis produces the following stream of tokens:
|
||||
|
||||
\begin{footnotesize}
|
||||
\begin{verbatim}
|
||||
MODEL
|
||||
SEMICOLON
|
||||
NAME "x"
|
||||
EQUAL
|
||||
LOG
|
||||
LEFT_PARENTHESIS
|
||||
FLOAT_NUMBER "3.5"
|
||||
RIGHT_PARENTHESIS
|
||||
SEMICOLON
|
||||
END
|
||||
SEMICOLON
|
||||
\end{verbatim}
|
||||
\end{footnotesize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Syntax analysis}
|
||||
\framesubtitle{In Dynare}
|
||||
\begin{itemize}
|
||||
\item The \texttt{mod} file grammar is described in \texttt{DynareBison.yy}, which is transformed into C++ source code by the program \texttt{bison}
|
||||
\item The grammar tells a story which looks like:
|
||||
\begin{itemize}
|
||||
\item A \texttt{mod} file is a list of statements
|
||||
\item A statement can be a \texttt{var} statement, a \texttt{varexo} statement, a \texttt{model} block, an \texttt{initval} block, \ldots
|
||||
\item A \texttt{var} statement begins with the token \texttt{VAR}, then a list of \texttt{NAME}s, then a semicolon
|
||||
\item A \texttt{model} block begins with the token \texttt{MODEL}, then a semicolon, then a list of equations separated by semicolons, then an \texttt{END} token
|
||||
\item An equation can be either an expression, or an expression followed by an \texttt{EQUAL} token and another expression
|
||||
\item An expression can be a \texttt{NAME}, or a \texttt{FLOAT\_NUMBER}, or an expression followed by a \texttt{PLUS} and another expression, \ldots
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Syntax analysis}
|
||||
Using the list of tokens produced by lexical analysis, the syntax analyzer determines which ``sentences'' are valid in the language, according to a \alert{grammar} composed of \alert{rules}.
|
||||
\begin{block}{A grammar for lists of additive and multiplicative expressions}
|
||||
\begin{footnotesize}
|
||||
\begin{verbatim}
|
||||
%start expression_list;
|
||||
|
||||
expression_list := expression SEMICOLON
|
||||
| expression_list expression SEMICOLON;
|
||||
|
||||
expression := expression PLUS expression
|
||||
| expression TIMES expression
|
||||
| LEFT_PAREN expression RIGHT_PAREN
|
||||
| INT_NUMBER;
|
||||
\end{verbatim}
|
||||
\end{footnotesize}
|
||||
\end{block}
|
||||
\begin{itemize}
|
||||
\item \texttt{(1+3)*2; 4+5;} will pass the syntax analysis without error
|
||||
\item \texttt{1++2;} will fail the syntax analysis, even though it has passed the lexical analysis
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Semantic actions}
|
||||
\begin{itemize}
|
||||
\item So far we have only described how to accept valid \texttt{mod} files and to reject others
|
||||
\item But validating is not enough: one needs to do something with the parsed \texttt{mod} file
|
||||
\item Every grammar rule can have a \alert{semantic action} associated with it: C/C++ code enclosed by curly braces
|
||||
\item Every rule can return a semantic value (referenced by \texttt{\$\$} in the action)
|
||||
\item In the action, it is possible to refer to semantic values returned by components of the rule (using \texttt{\$1}, \texttt{\$2}, \ldots)
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Semantic actions}
|
||||
\framesubtitle{An example}
|
||||
\begin{block}{A simple calculator which prints its results}
|
||||
\begin{footnotesize}
|
||||
\begin{verbatim}
|
||||
%start expression_list
|
||||
%type <int> expression
|
||||
|
||||
expression_list := expression SEMICOLON
|
||||
{ cout << $1 << endl; }
|
||||
| expression_list expression SEMICOLON
|
||||
{ cout << $2 << endl; };
|
||||
|
||||
expression := expression PLUS expression
|
||||
{ $$ = $1 + $3; }
|
||||
| expression TIMES expression
|
||||
{ $$ = $1 * $3; }
|
||||
| LEFT_PAREN expression RIGHT_PAREN
|
||||
{ $$ = $2; }
|
||||
| INT_NUMBER
|
||||
{ $$ = $1; };
|
||||
\end{verbatim}
|
||||
\end{footnotesize}
|
||||
\end{block}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Parsing driver}
|
||||
|
||||
The class \texttt{ParsingDriver} has the following roles:
|
||||
\begin{itemize}
|
||||
\item It opens the \texttt{mod} file and launches the lexical and syntaxic analyzers on it
|
||||
\item It implements most of the semantic actions of the grammar
|
||||
\item By doing so, it creates an object of type \texttt{ModFile}, which is the data structure representing the \texttt{mod} file
|
||||
\item Or, if there is a parsing error (unknown keyword, undeclared symbol, syntax error), it displays the line and column numbers where the error occurred and exits
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\section{Data structure representing a \texttt{mod} file}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{The \texttt{ModFile} class}
|
||||
\begin{itemize}
|
||||
\item This class is the internal data structure used to store all the information contained in a \texttt{mod} file
|
||||
\item One instance of the class represents one \texttt{mod} file
|
||||
\item The class contains the following elements (as class members):
|
||||
\begin{itemize}
|
||||
\item a symbol table, numerical constants table, external functions table
|
||||
\item trees of expressions: dynamic model, static model, original model, ramsey dynamic model, steady state model, trend dynamic model, \ldots
|
||||
\item the list of the statements (parameter initializations, \texttt{shocks} block, \texttt{check}, \texttt{steady}, \texttt{simul}, \ldots)
|
||||
\item model-specification and user-preference variables: \texttt{block}, \texttt{bytecode}, \texttt{use\_dll}, \texttt{no\_static}, \ldots
|
||||
\item an evaluation context (containing \texttt{initval} and parameter values)
|
||||
\end{itemize}
|
||||
\item An instance of \texttt{ModFile} is the output of the parsing process (return value of \texttt{ParsingDriver::parse()})
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{The symbol table (1/3)}
|
||||
\begin{itemize}
|
||||
\item A \alert{symbol} is simply the name of a variable (endogenous, exogenous, local, auxiliary, etc), parameter, external function, \ldots basically everything that is not recognized as a Dynare keyword
|
||||
\item \alert{SymbolTable} is a simple class used to maintain the list of the symbols used in the \texttt{mod} file
|
||||
\item For each symbol, it stores:
|
||||
\begin{itemize}
|
||||
\item its name, tex\_name, and long\_name (strings, some of which can be empty)
|
||||
\item its type (an enumerator defined in \texttt{CodeInterpreter.hh})
|
||||
\item a unique integer identifier (also has a unique identifier by type)
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{The symbol table (2/3)}
|
||||
Existing types of symbols:
|
||||
\begin{itemize}
|
||||
\item Endogenous variables
|
||||
\item Exogenous variables
|
||||
\item Exogenous deterministic variables
|
||||
\item Parameters
|
||||
\item Local variables inside model: declared with a pound sign (\#) construction
|
||||
\item Local variables outside model: no declaration needed (\textit{e.g.} lhs symbols in equations from \texttt{steady\_state\_model} block, expression outside of model block, \ldots)
|
||||
\item External functions
|
||||
\item Trend variables
|
||||
\item Log Trend variables
|
||||
\item Unused Endogenous variables (created when \texttt{nostrict} option is passed)
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{The symbol table (3/3)}
|
||||
\begin{itemize}
|
||||
\item Symbol table filled in:
|
||||
\begin{itemize}
|
||||
\item using the \texttt{var}, \texttt{varexo}, \texttt{varexo\_det}, \texttt{parameter}, \texttt{external\_function}, \texttt{trend\_var}, and \texttt{log\_trend\_var} declarations
|
||||
\item using pound sign (\#) constructions in the model block
|
||||
\item on the fly during parsing: local variables outside models or unknown functions when an undeclared symbol is encountered
|
||||
\item during the creation of auxiliary variables in the transform pass
|
||||
\end{itemize}
|
||||
\item Roles of the symbol table:
|
||||
\begin{itemize}
|
||||
\item permits parcimonious and more efficient representation of expressions (no need to duplicate or compare strings, only handle a pair of integers)
|
||||
\item ensures that a given symbol is used with only one type
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Expression trees (1/3)}
|
||||
\begin{itemize}
|
||||
\item The data structure used to store expressions is essentially a \alert{tree}
|
||||
\item Graphically, the tree representation of $(1+z)*\log(y)$ is:
|
||||
\begin{center}
|
||||
\includegraphics[width=6cm]{expr.png}
|
||||
\end{center}
|
||||
\item No need to store parentheses
|
||||
\item Each circle represents a \alert{node}
|
||||
\item A non external function node has at most one parent and at most three children (an external function node has as many children as arguments)
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Expression trees (2/3)}
|
||||
\begin{itemize}
|
||||
\item A tree node is represented by an instance of the abstract class \texttt{ExprNode}
|
||||
\item This class has 5 sub-classes, corresponding to the 5 types of non-external-function nodes:
|
||||
\begin{itemize}
|
||||
\item \texttt{NumConstNode} for constant nodes: contains the identifier of the numerical constants it represents
|
||||
\item \texttt{VariableNode} for variable/parameters nodes: contains the identifier of the variable or parameter it represents
|
||||
\item \texttt{UnaryOpNode} for unary operators (\textit{e.g.} unary minus, $\log$, $\sin$): contains an enumerator representing the operator, and a pointer to its child
|
||||
\item \texttt{BinaryOpNode} for binary operators (\textit{e.g.} $+$, $*$, pow): contains an enumerator representing the operator, and pointers to its two children
|
||||
\item \texttt{TrinaryOpNode} for trinary operators (\textit{e.g.} $normcdf$, $normpdf$): contains an enumerator representing the operator and pointers to its three children
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Expression trees (3/3)}
|
||||
\begin{itemize}
|
||||
\item The abstract class \texttt{ExprNode} has an abstract sub-class called \texttt{AbstractExternalFunctionNode}
|
||||
\item This abstract sub-class has 3 sub-classes, corresponding to the 3 types of external function nodes:
|
||||
\begin{itemize}
|
||||
\item \texttt{ExternalFunctionNode} for external functions. Contains the identifier of the external function and a vector of its arguments
|
||||
\item \texttt{FirstDerivExternalFunctionNode} for the first derivative of an external function. In addition to the information contained in \texttt{ExternalFunctionNode}, contains the index w.r.t. which this node is the derivative.
|
||||
\item \texttt{SecondDerivExternalFunctionNode} for the second derivative of an external function. In addition to the information contained in \texttt{FirstDerivExternalFunctionNode}, contains the index w.r.t. which this node is the second derivative.
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Classes \texttt{DataTree} and \texttt{ModelTree}}
|
||||
\begin{itemize}
|
||||
\item Class \texttt{DataTree} is a container for storing a set of expression trees
|
||||
\item Class \texttt{ModelTree} is a sub-class container of \texttt{DataTree}, specialized for storing a set of model equations.
|
||||
\item In the code, we use \texttt{ModelTree}-derived classes: \texttt{DynamicModel} (the model with lags) and \texttt{StaticModel} (the model without lags)
|
||||
\item Class \texttt{ModFile} contains:
|
||||
\begin{itemize}
|
||||
\item one instance of \texttt{DataTree} for storing all expressions outside model block
|
||||
\item several instances of \texttt{DynamicModel}, one each for storing the equations of the model block for the original model, modified model, original Ramsey model, the Ramsey FOCs, etc.
|
||||
\item one instance of \texttt{StaticModel} for storing the equations of model block without lags
|
||||
\end{itemize}
|
||||
\item Expression storage is optimized through three mechanisms:
|
||||
\begin{itemize}
|
||||
\item symbolic simplification rules
|
||||
\item sub-expression sharing
|
||||
\item pre-computing of numerical constants
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Constructing expression trees}
|
||||
\begin{itemize}
|
||||
\item Class \texttt{DataTree} contains a set of methods for constructing expression trees
|
||||
\item Construction is done bottom-up, node by node:
|
||||
\begin{itemize}
|
||||
\item one method for adding a constant node (\texttt{AddPossiblyNegativeConstant(double)})
|
||||
\item one method for a log node (\texttt{AddLog(arg)})
|
||||
\item one method for a plus node (\texttt{AddPlus(arg1, arg2)})
|
||||
\end{itemize}
|
||||
\item These methods take pointers to \texttt{ExprNode}, allocate the memory for the node, construct it, and return its pointer
|
||||
\item These methods are called:
|
||||
\begin{itemize}
|
||||
\item from \texttt{ParsingDriver} in the semantic actions associated to the parsing of expressions
|
||||
\item during symbolic derivation, to create derivatives expressions
|
||||
\item when creating the static model from the dynamic model
|
||||
\item \ldots
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Reduction of constants and symbolic simplifications}
|
||||
\begin{itemize}
|
||||
\item The construction methods compute constants whenever possible
|
||||
\begin{itemize}
|
||||
\item Suppose you ask to construct the node $1+1$
|
||||
\item The \texttt{AddPlus()} method will return a pointer to a constant node containing 2
|
||||
\end{itemize}
|
||||
\item The construction methods also apply a set of simplification rules, such as:
|
||||
\begin{itemize}
|
||||
\item $0+0=0$
|
||||
\item $x+0 = x$
|
||||
\item $0-x = -x$
|
||||
\item $-(-x) = x$
|
||||
\item $x*0 = 0$
|
||||
\item $x/1 = x$
|
||||
\item $x^0 = 1$
|
||||
\end{itemize}
|
||||
\item When a simplification rule applies, no new node is created
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Sub-expression sharing (1/2)}
|
||||
\begin{itemize}
|
||||
\item Consider the two following expressions: $(1+z)*\log(y)$ and $2^{(1+z)}$
|
||||
\item Expressions share a common sub-expression: $1+z$
|
||||
\item The internal representation of these expressions is:
|
||||
\begin{center}
|
||||
\includegraphics[width=7cm]{expr-sharing.png}
|
||||
\end{center}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Sub-expression sharing (2/2)}
|
||||
\begin{itemize}
|
||||
\item Construction methods implement a simple algorithm which achieves maximal expression sharing
|
||||
\item Algorithm uses the fact that each node has a unique memory address (pointer to the corresponding instance of \texttt{ExprNode})
|
||||
\item It maintains 9 tables which keep track of the already-constructed nodes: one table by type of node (constants, variables, unary ops, binary ops, trinary ops, external functions, first deriv of external functions, second deriv of external functions, local variables)
|
||||
\item Suppose you want to create the node $e_1+e_2$ (where $e_1$ and $e_2$ are sub-expressions):
|
||||
\begin{itemize}
|
||||
\item the algorithm searches the binary ops table for the tuple equal to (address of $e_1$, address of $e_2$, op code of +) (it is the \alert{search key})
|
||||
\item if the tuple is found in the table, the node already exists and its memory address is returned
|
||||
\item otherwise, the node is created and is added to the table with its search key
|
||||
\end{itemize}
|
||||
\item Maximum sharing is achieved because expression trees are constructed bottom-up
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Final remarks about expressions}
|
||||
\begin{itemize}
|
||||
\item Storage of negative constants
|
||||
\begin{itemize}
|
||||
\item class \texttt{NumConstNode} only accepts positive constants
|
||||
\item a negative constant is stored as a unary minus applied to a positive constant
|
||||
\item this is a kind of identification constraint to avoid having two ways of representing negative constants: $(-2)$ and $-(2)$
|
||||
\end{itemize}
|
||||
\item Widely used constants
|
||||
\begin{itemize}
|
||||
\item class \texttt{DataTree} has attributes containing pointers to constants: $0$, $1$, $2$, $-1$, \texttt{NaN}, $\infty$, $-\infty$, and $\pi$
|
||||
\item these constants are used in many places (in simplification rules, in derivation algorithm\ldots)
|
||||
\item sub-expression sharing algorithm ensures that these constants will never be duplicated
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{List of statements}
|
||||
\begin{itemize}
|
||||
\item A statement is represented by an instance of a subclass of the abstract class \texttt{Statement}
|
||||
\item Three groups of statements:
|
||||
\begin{itemize}
|
||||
\item initialization statements (parameter initialization with $p = \ldots$, \texttt{initval}, \texttt{histval}, or \texttt{endval} block)
|
||||
\item shocks blocks (\texttt{shocks}, \texttt{mshocks}, \ldots)
|
||||
\item computing tasks (\texttt{steady}, \texttt{check}, \texttt{simul}, \ldots)
|
||||
\end{itemize}
|
||||
\item Each type of statement has its own class (\textit{e.g.} \texttt{InitValStatement}, \texttt{SimulStatement}, \ldots)
|
||||
\item The class \texttt{ModFile} stores a list of pointers of type \texttt{Statement*}, corresponding to the statements of the \texttt{mod} file, in their order of declaration
|
||||
\item Heavy use of polymorphism in the check pass, computing pass, and when writing outputs: abstract class \texttt{Statement} provides a virtual method for these 3 actions
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Evaluation context}
|
||||
\begin{itemize}
|
||||
\item The \texttt{ModFile} class contains an \alert{evaluation context}
|
||||
\item It is a map associating a numerical value to some symbols
|
||||
\item Filled in with \texttt{initval} block values and parameter initializations
|
||||
\item Used during equation normalization (in the block decomposition), for finding non-zero entries in the jacobian
|
||||
\item Used in testing that trends are compatible with a balanced growth path, for finding non-zero cross partials of equations with respect to trend variables and endogenous varibales
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\section{Check pass}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Error checking during parsing}
|
||||
\begin{itemize}
|
||||
\item Some errors in the \texttt{mod} file can be detected during parsing:
|
||||
\begin{itemize}
|
||||
\item syntax errors
|
||||
\item use of undeclared symbols in model block, initval block\ldots
|
||||
\item use of a symbol incompatible with its type (\textit{e.g.} parameter in initval, local variable used both in model and outside model)
|
||||
\item multiple shock declarations for the same variable
|
||||
\end{itemize}
|
||||
\item But some other checks can only be done when parsing is completed\ldots
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Check pass}
|
||||
\begin{itemize}
|
||||
\item The check pass is implemented through the method \texttt{ModFile::checkPass()}
|
||||
\item Performs many checks. Examples include:
|
||||
\begin{itemize}
|
||||
\item check there is at least one equation in the model (except if doing a standalone BVAR estimation)
|
||||
\item checks for coherence in statements (\textit{e.g.} options passed to statements do not conflict with each other, required options have been passed)
|
||||
\item checks for coherence among statements (\textit{e.g.} if \texttt{osr} statement is present, ensure \texttt{osr\_params} and \texttt{optim\_weights} statements are present)
|
||||
\item checks for coherence between statements and attributes of \texttt{mod} file (\textit{e.g.} \texttt{use\_dll} is not used with \texttt{block} or \texttt{bytecode})
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\section{Transform pass}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Transform pass (1/2)}
|
||||
\begin{itemize}
|
||||
\item The transform pass is implemented through the method \texttt{ModFile::transformPass(bool nostrict)}
|
||||
\item It makes necessary transformations (notably to the dynamic model, symbol table, and statements list) preparing the \texttt{ModFile} object for the computing pass. Examples of transformations include:
|
||||
\begin{itemize}
|
||||
\item creation of auxiliary variables and equations for leads, lags, expectation operator, differentiated forward variables, etc.
|
||||
\item detrending of model equations if nonstationary variables are present
|
||||
\item decreasing leads/lags of predetermined variables by one period
|
||||
\item addition of FOCs of Langrangian for Ramsey problem
|
||||
\item addition of \texttt{dsge\_prior\_weight} initialization before all other statements if estimating a DSGE-VAR where the weight of the DSGE prior of the VAR is calibrated
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Transform pass (2/2)}
|
||||
\begin{itemize}
|
||||
\item It then freezes the symbol table, meaning that no more symbols can be created on the \texttt{ModFile} object
|
||||
\item Finally checks are performed on the transformed model. Examples include:
|
||||
\begin{itemize}
|
||||
\item same number of endogenous varibables as equations (not done in certain situations, \textit{e.g.} Ramsey, discretionary policy, etc.)
|
||||
\item correspondence among variables and statements, \textit{e.g.} Ramsey policy, identification, perfect foresight solver, and simul are incompatible with deterministic exogenous variables
|
||||
\item correspondence among statements, \textit{e.g.} for DSGE-VAR without \texttt{bayesian\_irf} option, the number of shocks must be greater than or equal to the number of observed variables
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
|
||||
\section{Computing pass}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Overview of the computing pass}
|
||||
\begin{itemize}
|
||||
\item Computing pass implemented in \texttt{ModFile::computingPass()}
|
||||
\item Creates Static model from Dynamic (by removing leads/lags)
|
||||
\item Determines which derivatives to compute
|
||||
\item Then calls \texttt{DynamicModel::computingPass()} which computes:
|
||||
\begin{itemize}
|
||||
\item leag/lag variable incidence matrix
|
||||
\item symbolic derivatives w.r.t. endogenous, exogenous, and parameters, if needed
|
||||
\item equation normalization + block decomposition
|
||||
\item temporary terms
|
||||
\item computes equation cross references, if desired
|
||||
\end{itemize}
|
||||
\item NB: analagous operations for Static model are performed by \texttt{StaticModel::computingPass()}
|
||||
\item Asserts that equations declared linear are indeed linear (by checking that Hessian == 0)
|
||||
\item Finally, calls \texttt{Statement::computingPass()} on all statements
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Model Variables}
|
||||
\begin{itemize}
|
||||
\item In the context of class \texttt{ModelTree}, a \alert{variable} is a pair (symbol, lag)
|
||||
\item The symbol must correspond to a variable of type endogenous, exogenous, deterministic exogenous variable, or parameter
|
||||
\item The \texttt{SymbolTable} class keeps track of valid symbols while the \texttt{variable\_node\_map} keeps track of model variables (symbol, lag pairs stored in \texttt{VariableNode} objects)
|
||||
\item After the computing pass, the \texttt{DynamicModel} class writes the leag/lag incidence matrix:
|
||||
\begin{itemize}
|
||||
\item three rows: the first row indicates $t-1$, the second row $t$, and the third row $t+1$
|
||||
\item one column for every endogenous symbol in order of declaration; NB: includes endogenous auxiliary variables created during the transform pass
|
||||
\item elements of the matrix are either 0 (if the variable does not appear in the model) or correspond to the variable's column in the Jacobian of the dynamic model
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Static versus dynamic model}
|
||||
\begin{itemize}
|
||||
\item The static model is simply the dynamic model without leads and lags
|
||||
\item Static model used to characterize the steady state
|
||||
\item The jacobian of the static model is used in the (Matlab) solver for determining the steady state
|
||||
\end{itemize}
|
||||
\begin{block}{Example}
|
||||
\begin{itemize}
|
||||
\item suppose dynamic model is $2x_t \cdot x_{t-1} = 0$
|
||||
\item static model is $2x^2 = 0$, whose derivative w.r.t. $x$ is $4x$
|
||||
\item dynamic derivative w.r.t. $x_t$ is $2x_{t-1}$, and w.r.t. $x_{t-1}$ is $2x_t$
|
||||
\item removing leads/lags from dynamic derivatives and summing over the two partial derivatives w.r.t. $x_t$ and $x_{t-1}$ gives $4x$
|
||||
\end{itemize}
|
||||
\end{block}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Which derivatives to compute?}
|
||||
\begin{itemize}
|
||||
\item In deterministic mode:
|
||||
\begin{itemize}
|
||||
\item static jacobian w.r.t. endogenous variables only
|
||||
\item dynamic jacobian w.r.t. endogenous variables only
|
||||
\end{itemize}
|
||||
\item In stochastic mode:
|
||||
\begin{itemize}
|
||||
\item static jacobian w.r.t. endogenous variables only
|
||||
\item dynamic jacobian w.r.t. endogenous, exogenous, and deterministic exogenous variables
|
||||
\item dynamic hessian w.r.t. endogenous, exogenous, and deterministic exogenous variables
|
||||
\item possibly dynamic 3rd derivatives (if \texttt{order} option $\geq 3$)
|
||||
\item possibly dynamic jacobian and/or hessian w.r.t. parameters (if \texttt{identification} or analytic derivs needed for \texttt{estimation} and \texttt{params\_derivs\_order} $>0$)
|
||||
\end{itemize}
|
||||
\item For Ramsey policy: the same as above, but with one further order of derivation than declared by the user with \texttt{order} option (the derivation order is determined in the check pass, see \texttt{RamseyPolicyStatement::checkPass()})
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Derivation algorithm (1/2)}
|
||||
\begin{itemize}
|
||||
\item Derivation of the model implemented in \texttt{ModelTree::computeJacobian()}, \texttt{ModelTree::computeHessian()}, \texttt{ModelTree::computeThirdDerivatives()}, and \texttt{ModelTree::computeParamsDerivatives()}
|
||||
\item Simply call \texttt{ExprNode::getDerivative(deriv\_id)} on each equation node
|
||||
\item Use of polymorphism:
|
||||
\begin{itemize}
|
||||
\item for a constant or variable node, derivative is straightforward ($0$ or $1$)
|
||||
\item for a unary, binary, trinary op nodes and external function nodes, recursively calls method \texttt{computeDerivative()} on children to construct derivative
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Derivation algorithm (2/2)}
|
||||
\framesubtitle{Optimizations}
|
||||
\begin{itemize}
|
||||
\item Caching of derivation results
|
||||
\begin{itemize}
|
||||
\item method \texttt{ExprNode::getDerivative(deriv\_id)} memorizes its result in a member attribute (\texttt{derivatives}) the first time it is called
|
||||
\item the second time it is called (with the same argument), it simply returns the cached value without recomputation
|
||||
\item caching is useful because of sub-expression sharing
|
||||
\end{itemize}
|
||||
\item Efficiently finds symbolic derivatives equal to $0$
|
||||
\begin{itemize}
|
||||
\item consider the expression $x+y^2$
|
||||
\item without any computation, you know its derivative w.r.t. $z$ is zero
|
||||
\item each node stores in an attribute (\texttt{non\_null\_derivatives}) the set of variables which appear in the expression it represents ($\{x,y\}$ in the example)
|
||||
\item this set is computed in \texttt{prepareForDerivation()}
|
||||
\item when \texttt{getDerivative(deriv\_id)} is called, immediately returns zero if \texttt{deriv\_id} is not in that set
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Temporary terms (1/2)}
|
||||
\begin{itemize}
|
||||
\item When the preprocessor writes equations and derivatives in its outputs, it takes advantage of sub-expression sharing
|
||||
\item In Matlab static and dynamic output files, equations are preceded by a list of \alert{temporary terms}
|
||||
\item These terms are variables containing expressions shared by several equations or derivatives
|
||||
\item Using these terms greatly enhances the computing speed of the model residual, jacobian, hessian, or third derivative
|
||||
\end{itemize}
|
||||
\begin{block}{Example}
|
||||
\begin{columns}[t]
|
||||
\begin{column}{6cm}
|
||||
The equations:
|
||||
\begin{verbatim}
|
||||
residual(0)=x+y^2-z^3;
|
||||
residual(1)=3*(x+y^2)+1;
|
||||
\end{verbatim}
|
||||
\end{column}
|
||||
\begin{column}{4.8cm}
|
||||
Can be optimized in:
|
||||
\begin{verbatim}
|
||||
T1=x+y^2;
|
||||
residual(0)=T1-z^3;
|
||||
residual(1)=3*T1+1;
|
||||
\end{verbatim}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{block}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Temporary terms (2/2)}
|
||||
\begin{itemize}
|
||||
\item Expression storage in the preprocessor implements maximal sharing but this is not optimal for the Matlab output files, because creating a temporary variable also has a cost (in terms of CPU and of memory)
|
||||
\item Computation of temporary terms implements a trade-off between:
|
||||
\begin{itemize}
|
||||
\item cost of duplicating sub-expressions
|
||||
\item cost of creating new variables
|
||||
\end{itemize}
|
||||
\item Algorithm uses a recursive cost calculation, which marks some nodes as being ``temporary''
|
||||
\item \textit{Problem}: redundant with optimizations done by the C/C++ compiler (when Dynare is in DLL mode) $\Rightarrow$ compilation very slow on big models
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{The special case of Ramsey policy}
|
||||
\begin{itemize}
|
||||
\item For most statements, the method \texttt{computingPass()} is a no-op\ldots
|
||||
\item \ldots except for \texttt{planner\_objective} statement, which serves to declare planner objective when doing optimal policy under commitment
|
||||
\item Class \texttt{PlannerObjectiveStatement} contains an instance of \texttt{ModelTree}, which stores the objective function (\texttt{i.e.} only one equation in the tree)
|
||||
\item During the computing pass, triggers the computation of the first and second order (static) derivatives of the objective
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\section{Writing outputs}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Output overview}
|
||||
\begin{itemize}
|
||||
\item Implemented in \texttt{ModFile::writeOutputFiles()}
|
||||
\item If \texttt{mod} file is \texttt{model.mod}, all created filenames will begin with \texttt{model}
|
||||
\item Main output file is \texttt{model.m}, containing:
|
||||
\begin{itemize}
|
||||
\item general initialization commands
|
||||
\item symbol table output (from \texttt{SymbolTable::writeOutput()})
|
||||
\item lead/lag incidence matrix (from \texttt{DynamicModel::writeDynamicMFile()})
|
||||
\item call to Matlab functions corresponding to the statements of the \texttt{mod} file (written by calling \texttt{Statement::writeOutput()} on all statements through polymorphism)
|
||||
\end{itemize}
|
||||
\item Subsidiary output files:
|
||||
\begin{itemize}
|
||||
\item one for the static model
|
||||
\item one for the dynamic model
|
||||
\item one for the auxiliary variables
|
||||
\item one for the steady state file (if relevant)
|
||||
\item one for the planner objective (if relevant)
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Model output files}
|
||||
Three possible output types:
|
||||
\begin{itemize}
|
||||
\item Matlab/Octave mode: static and dynamic files in Matlab
|
||||
\item Julia mode: static and dynamic files in Julia
|
||||
\item DLL mode:
|
||||
\begin{itemize}
|
||||
\item static and dynamic files in C++ source code (with corresponding headers)
|
||||
\item compiled through \texttt{mex} to allow execution from within Matlab
|
||||
\end{itemize}
|
||||
\item Sparse DLL mode:
|
||||
\begin{itemize}
|
||||
\item static file in Matlab
|
||||
\item two possibilities for dynamic file:
|
||||
\begin{itemize}
|
||||
\item by default, a C++ source file (with header) and a binary file, to be read from the C++ code
|
||||
\item or, with \texttt{no\_compiler} option, a binary file in custom format, executed from Matlab through \texttt{simulate} DLL
|
||||
\item the second option serves to bypass compilation of C++ file which can be very slow
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\section{Proposed Changes}
|
||||
|
||||
\newcounter{sauvegardeenumi}
|
||||
\newcommand{\asuivre}{\setcounter{sauvegardeenumi}{\theenumi}}
|
||||
\newcommand{\suite}{\setcounter{enumi}{\thesauvegardeenumi}}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Proposed changes with addition of Julia support (1/2)}
|
||||
\begin{enumerate}
|
||||
\item Julia output is provided upon parsing of \texttt{mod} file, everything else done in Julia
|
||||
\begin{itemize}
|
||||
\item Pros: very few changes to the preprocessor
|
||||
\item Cons: repeated code (same checks, transformations, computations done in preprocessor and Julia); potential code divergence/two parallel projects
|
||||
\end{itemize}
|
||||
\item Dump preprocessor altogether: do everything with Julia
|
||||
\begin{itemize}
|
||||
\item Pros: simple to distribute, move away from C++ (no contributions, requires more expertise)
|
||||
\item Cons: Matlab/Octave users must also download Julia, a big project, speed (?)
|
||||
\end{itemize}
|
||||
\asuivre
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Proposed changes with addition of Julia support (2/2)}
|
||||
\begin{enumerate}
|
||||
\suite
|
||||
\item Create libraries out of the preprocessor
|
||||
\begin{itemize}
|
||||
\item Pros: Dynare interaction similar across HLPs, preprocessor used as is
|
||||
\item Cons: difficult for outsiders to contribute, big project, not much benefit in speed when compared to\ldots
|
||||
\end{itemize}
|
||||
\item Write \texttt{mod} file from HLP then call preprocessor; option to output JSON file representing \texttt{ModFile} object at every step of the preprocessor
|
||||
\begin{itemize}
|
||||
\item Pros: Dynare interaction similar across HLPs, preprocessor used as is, minimal amount of work, easy incremental step, allows users to support any given HPL given the JSON output
|
||||
\item Cons: unnecessary processing when certain changes made in host language, keeps defaults of current preprocessor, speed (?)
|
||||
\end{itemize}
|
||||
\item Other ideas?
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Using HLP \texttt{mod} file objects (1/2)}
|
||||
\begin{center}
|
||||
\includegraphics[width=11cm]{json-preprocessor.png}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Using HLP \texttt{mod} file objects (2/2)}
|
||||
\begin{itemize}
|
||||
\item Allows interactivity for all HLPs; requires only
|
||||
\begin{itemize}
|
||||
\item A definition of a mod file class in the HLP
|
||||
\item A library function that converts an HLP mod file object to a \texttt{mod} file
|
||||
\end{itemize}
|
||||
\item Allows users to use Dynare with any HPL. Standard JSON output can be read in any HPL; user can use it construct desired HPL objects and work with model in their language of preference
|
||||
\item Easy first step
|
||||
\item No divergence of codebase: don't need to repeat code (checks, transformations, etc.) across platforms
|
||||
\item Creates \texttt{mod} files that can be used on other host language platforms
|
||||
\item Adds one more HLP library to distribute
|
||||
\item Need to design/implement classes that will store processed dynare \texttt{mod} file in various HLPs
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\end{document}
|
|
@ -1,2 +0,0 @@
|
|||
NB: .png files made on https://www.draw.io. They can be edited by loading the .xml file with the same name
|
||||
|
|
@ -16,7 +16,7 @@ function dynare(fname, varargin)
|
|||
% SPECIAL REQUIREMENTS
|
||||
% none
|
||||
|
||||
% Copyright (C) 2001-2017 Dynare Team
|
||||
% Copyright (C) 2001-2018 Dynare Team
|
||||
%
|
||||
% This file is part of Dynare.
|
||||
%
|
||||
|
@ -217,8 +217,12 @@ for i=1:length(varargin)
|
|||
end
|
||||
|
||||
if preprocessoroutput
|
||||
fprintf(['Starting Dynare (version ' dynare_version() ').\n']);
|
||||
fprintf('Calling Dynare with arguments: ');
|
||||
disp(varargin);
|
||||
if isempty(varargin)
|
||||
disp('none')
|
||||
end
|
||||
end
|
||||
|
||||
[status, result] = system(command);
|
||||
|
|
|
@ -34,7 +34,7 @@ fake_1 = 1;
|
|||
fake_2 = 1;
|
||||
|
||||
exit_flag = 1;
|
||||
info = 0;
|
||||
info = zeros(4,1);
|
||||
|
||||
%------------------------------------------------------------------------------
|
||||
% 1. Get the structural parameters & define penalties
|
||||
|
@ -46,7 +46,7 @@ if ~isequal(DynareOptions.mode_compute,1) && any(xparams<p3)
|
|||
fval = Inf;
|
||||
exit_flag = 0;
|
||||
info(1) = 41;
|
||||
info(2) = sum((p3(k)-xparams(k)).^2);
|
||||
info(4) = sum((p3(k)-xparams(k)).^2);
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -56,7 +56,7 @@ if ~isequal(DynareOptions.mode_compute,1) && any(xparams>p4)
|
|||
fval = Inf;
|
||||
exit_flag = 0;
|
||||
info(1) = 42;
|
||||
info(2) = sum((xparams(k)-p4(k)).^2);
|
||||
info(4) = sum((xparams(k)-p4(k)).^2);
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -75,7 +75,7 @@ if ~issquare(Q) || EstimatedParams.ncx || isfield(EstimatedParams,'calibrated_co
|
|||
fval = Inf;
|
||||
exit_flag = 0;
|
||||
info(1) = 43;
|
||||
info(2) = penalty;
|
||||
info(4) = penalty;
|
||||
return
|
||||
end
|
||||
if isfield(EstimatedParams,'calibrated_covariances')
|
||||
|
@ -85,7 +85,7 @@ if ~issquare(Q) || EstimatedParams.ncx || isfield(EstimatedParams,'calibrated_co
|
|||
fval = Inf;
|
||||
exit_flag = 0;
|
||||
info(1) = 71;
|
||||
info(2) = penalty;
|
||||
info(4) = penalty;
|
||||
return
|
||||
end
|
||||
end
|
||||
|
@ -100,7 +100,7 @@ if ~issquare(H) || EstimatedParams.ncn || isfield(EstimatedParams,'calibrated_co
|
|||
fval = Inf;
|
||||
exit_flag = 0;
|
||||
info(1) = 44;
|
||||
info(2) = penalty;
|
||||
info(4) = penalty;
|
||||
return
|
||||
end
|
||||
if isfield(EstimatedParams,'calibrated_covariances_ME')
|
||||
|
@ -110,7 +110,7 @@ if ~issquare(H) || EstimatedParams.ncn || isfield(EstimatedParams,'calibrated_co
|
|||
fval = Inf;
|
||||
exit_flag = 0;
|
||||
info(1) = 72;
|
||||
info(2) = penalty;
|
||||
info(4) = penalty;
|
||||
return
|
||||
end
|
||||
end
|
||||
|
@ -124,7 +124,6 @@ end
|
|||
M_ = set_all_parameters(xparams,EstimatedParams,DynareModel);
|
||||
[dr,info,DynareModel,DynareOptions,DynareResults] = resol(0,DynareModel,DynareOptions,DynareResults);
|
||||
|
||||
% Return, with endogenous penalty when possible, if dynare_resolve issues an error code (defined in resol).
|
||||
% Return, with endogenous penalty when possible, if dynare_resolve issues an error code (defined in resol).
|
||||
if info(1)
|
||||
if info(1) == 3 || info(1) == 4 || info(1) == 5 || info(1)==6 ||info(1) == 19 ...
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
mex_PROGRAMS = bytecode
|
||||
|
||||
bytecode_CPPFLAGS = -Wno-maybe-uninitialized $(AM_CPPFLAGS) -I$(top_srcdir)/../../sources -I$(top_srcdir)/../../sources/bytecode -I$(top_srcdir)/../../../preprocessor
|
||||
bytecode_CPPFLAGS = -Wno-maybe-uninitialized $(AM_CPPFLAGS) -I$(top_srcdir)/../../sources -I$(top_srcdir)/../../sources/bytecode -I$(top_srcdir)/../../../preprocessor/src
|
||||
|
||||
TOPDIR = $(top_srcdir)/../../sources/bytecode
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit a1437ac982d684289e292bc8ce8f9af29354587c
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,783 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include "ConfigFile.hh"
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
Hook::Hook(string &global_init_file_arg)
|
||||
{
|
||||
if (global_init_file_arg.empty())
|
||||
{
|
||||
cerr << "ERROR: The Hook must have a Global Initialization File argument." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
hooks["global_init_file"] = global_init_file_arg;
|
||||
}
|
||||
|
||||
Path::Path(vector<string> &includepath_arg)
|
||||
{
|
||||
if (includepath_arg.empty())
|
||||
{
|
||||
cerr << "ERROR: The Path must have an Include argument." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
paths["include"] = includepath_arg;
|
||||
}
|
||||
|
||||
SlaveNode::SlaveNode(string &computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string &userName_arg,
|
||||
string &password_arg, string &remoteDrive_arg, string &remoteDirectory_arg,
|
||||
string &dynarePath_arg, string &matlabOctavePath_arg, bool singleCompThread_arg, int numberOfThreadsPerJob_arg,
|
||||
string &operatingSystem_arg) :
|
||||
computerName(computerName_arg), port(port_arg), minCpuNbr(minCpuNbr_arg), maxCpuNbr(maxCpuNbr_arg), userName(userName_arg),
|
||||
password(password_arg), remoteDrive(remoteDrive_arg), remoteDirectory(remoteDirectory_arg), dynarePath(dynarePath_arg),
|
||||
matlabOctavePath(matlabOctavePath_arg), singleCompThread(singleCompThread_arg), numberOfThreadsPerJob(numberOfThreadsPerJob_arg),
|
||||
operatingSystem(operatingSystem_arg)
|
||||
{
|
||||
if (computerName.empty())
|
||||
{
|
||||
cerr << "ERROR: The node must have a ComputerName." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!operatingSystem.empty())
|
||||
if (operatingSystem.compare("windows") != 0 && operatingSystem.compare("unix") != 0)
|
||||
{
|
||||
cerr << "ERROR: The OperatingSystem must be either 'unix' or 'windows' (Case Sensitive)." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
Cluster::Cluster(member_nodes_t member_nodes_arg) :
|
||||
member_nodes(member_nodes_arg)
|
||||
{
|
||||
if (member_nodes.empty())
|
||||
{
|
||||
cerr << "ERROR: The cluster must have at least one member node." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigFile::ConfigFile(bool parallel_arg, bool parallel_test_arg,
|
||||
bool parallel_slave_open_mode_arg, const string &cluster_name_arg) :
|
||||
parallel(parallel_arg), parallel_test(parallel_test_arg),
|
||||
parallel_slave_open_mode(parallel_slave_open_mode_arg), cluster_name(cluster_name_arg)
|
||||
{
|
||||
}
|
||||
|
||||
ConfigFile::~ConfigFile()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::getConfigFileInfo(const string &config_file)
|
||||
{
|
||||
using namespace boost;
|
||||
ifstream *configFile;
|
||||
|
||||
if (config_file.empty())
|
||||
{
|
||||
string defaultConfigFile("");
|
||||
// Test OS and try to open default file
|
||||
#if defined(_WIN32) || defined(__CYGWIN32__)
|
||||
if (getenv("APPDATA") == NULL)
|
||||
{
|
||||
if (parallel || parallel_test)
|
||||
cerr << "ERROR: ";
|
||||
else
|
||||
cerr << "WARNING: ";
|
||||
cerr << "APPDATA environment variable not found." << endl;
|
||||
|
||||
if (parallel || parallel_test)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultConfigFile += getenv("APPDATA");
|
||||
defaultConfigFile += "\\dynare.ini";
|
||||
}
|
||||
#else
|
||||
if (getenv("HOME") == NULL)
|
||||
{
|
||||
if (parallel || parallel_test)
|
||||
cerr << "ERROR: ";
|
||||
else
|
||||
cerr << "WARNING: ";
|
||||
cerr << "HOME environment variable not found." << endl;
|
||||
if (parallel || parallel_test)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultConfigFile += getenv("HOME");
|
||||
defaultConfigFile += "/.dynare";
|
||||
}
|
||||
#endif
|
||||
configFile = new ifstream(defaultConfigFile.c_str(), fstream::in);
|
||||
if (!configFile->is_open())
|
||||
if (parallel || parallel_test)
|
||||
{
|
||||
cerr << "ERROR: Could not open the default config file (" << defaultConfigFile << ")" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
configFile = new ifstream(config_file.c_str(), fstream::in);
|
||||
if (!configFile->is_open())
|
||||
{
|
||||
cerr << "ERROR: Couldn't open file " << config_file << endl;;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
string name, computerName, port, userName, password, remoteDrive,
|
||||
remoteDirectory, dynarePath, matlabOctavePath, operatingSystem,
|
||||
global_init_file;
|
||||
vector<string> includepath;
|
||||
int minCpuNbr = 0, maxCpuNbr = 0;
|
||||
int numberOfThreadsPerJob = 1;
|
||||
bool singleCompThread = false;
|
||||
member_nodes_t member_nodes;
|
||||
|
||||
bool inHooks = false;
|
||||
bool inNode = false;
|
||||
bool inCluster = false;
|
||||
bool inPaths = false;
|
||||
while (configFile->good())
|
||||
{
|
||||
string line;
|
||||
getline(*configFile, line);
|
||||
trim(line);
|
||||
if (line.empty() || !line.compare(0, 1, "#"))
|
||||
continue;
|
||||
|
||||
if (!line.compare("[node]")
|
||||
|| !line.compare("[cluster]")
|
||||
|| !line.compare("[hooks]")
|
||||
|| !line.compare("[paths]"))
|
||||
{
|
||||
if (!global_init_file.empty())
|
||||
// we were just in [hooks]
|
||||
addHooksConfFileElement(global_init_file);
|
||||
else if (!includepath.empty())
|
||||
// we were just in [paths]
|
||||
addPathsConfFileElement(includepath);
|
||||
else
|
||||
// we were just in [node] or [cluster]
|
||||
addParallelConfFileElement(inNode, inCluster, member_nodes, name,
|
||||
computerName, port, minCpuNbr, maxCpuNbr, userName,
|
||||
password, remoteDrive, remoteDirectory,
|
||||
dynarePath, matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
|
||||
operatingSystem);
|
||||
|
||||
//! Reset communication vars / option defaults
|
||||
if (!line.compare("[hooks]"))
|
||||
{
|
||||
inHooks = true;
|
||||
inNode = false;
|
||||
inCluster = false;
|
||||
inPaths = false;
|
||||
}
|
||||
else if (!line.compare("[node]"))
|
||||
{
|
||||
inHooks = false;
|
||||
inNode = true;
|
||||
inCluster = false;
|
||||
inPaths = false;
|
||||
}
|
||||
else if (!line.compare("[paths]"))
|
||||
{
|
||||
inHooks = false;
|
||||
inNode = false;
|
||||
inCluster = false;
|
||||
inPaths = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
inHooks = false;
|
||||
inNode = false;
|
||||
inCluster = true;
|
||||
inPaths = false;
|
||||
}
|
||||
|
||||
name = userName = computerName = port = password = remoteDrive
|
||||
= remoteDirectory = dynarePath = matlabOctavePath
|
||||
= operatingSystem = global_init_file = "";
|
||||
includepath.clear();
|
||||
minCpuNbr = maxCpuNbr = 0;
|
||||
numberOfThreadsPerJob = 1;
|
||||
singleCompThread = false;
|
||||
member_nodes.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<string> tokenizedLine;
|
||||
split(tokenizedLine, line, is_any_of("="));
|
||||
if (tokenizedLine.size() != 2)
|
||||
{
|
||||
cerr << "ERROR (in config file): Options should be formatted as 'option = value'." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
trim(tokenizedLine.front());
|
||||
trim(tokenizedLine.back());
|
||||
|
||||
if (inHooks)
|
||||
if (!tokenizedLine.front().compare("GlobalInitFile"))
|
||||
if (global_init_file.empty())
|
||||
global_init_file = tokenizedLine.back();
|
||||
else
|
||||
{
|
||||
cerr << "ERROR: May not have more than one GlobalInitFile option in [hooks] block." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "ERROR: Unrecognized option " << tokenizedLine.front() << " in [hooks] block." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else if (inPaths)
|
||||
if (!tokenizedLine.front().compare("Include"))
|
||||
if (includepath.empty())
|
||||
{
|
||||
vector<string> tokenizedPath;
|
||||
split(tokenizedPath, tokenizedLine.back(), is_any_of(":"), token_compress_on);
|
||||
for (vector<string>::iterator it = tokenizedPath.begin();
|
||||
it != tokenizedPath.end(); it++)
|
||||
if (!it->empty())
|
||||
{
|
||||
trim(*it);
|
||||
includepath.push_back(*it);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "ERROR: May not have more than one Include option in [paths] block." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "ERROR: Unrecognized option " << tokenizedLine.front() << " in [paths] block." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
if (!tokenizedLine.front().compare("Name"))
|
||||
name = tokenizedLine.back();
|
||||
else if (!tokenizedLine.front().compare("CPUnbr"))
|
||||
{
|
||||
vector<string> tokenizedCpuNbr;
|
||||
split(tokenizedCpuNbr, tokenizedLine.back(), is_any_of(":"));
|
||||
try
|
||||
{
|
||||
if (tokenizedCpuNbr.size() == 1)
|
||||
{
|
||||
minCpuNbr = 1;
|
||||
maxCpuNbr = lexical_cast< int >(tokenizedCpuNbr.front());
|
||||
}
|
||||
else if (tokenizedCpuNbr.size() == 2
|
||||
&& tokenizedCpuNbr[0].at(0) == '['
|
||||
&& tokenizedCpuNbr[1].at(tokenizedCpuNbr[1].size()-1) == ']')
|
||||
{
|
||||
tokenizedCpuNbr[0].erase(0, 1);
|
||||
tokenizedCpuNbr[1].erase(tokenizedCpuNbr[1].size()-1, 1);
|
||||
minCpuNbr = lexical_cast< int >(tokenizedCpuNbr[0]);
|
||||
maxCpuNbr = lexical_cast< int >(tokenizedCpuNbr[1]);
|
||||
}
|
||||
}
|
||||
catch (const bad_lexical_cast &)
|
||||
{
|
||||
cerr << "ERROR: Could not convert value to integer for CPUnbr." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (minCpuNbr <= 0 || maxCpuNbr <= 0)
|
||||
{
|
||||
cerr << "ERROR: Syntax for the CPUnbr option is as follows:" << endl
|
||||
<< " 1) CPUnbr = <int>" << endl
|
||||
<< " or 2) CPUnbr = [<int>:<int>]" << endl
|
||||
<< " where <int> is an Integer > 0." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
minCpuNbr--;
|
||||
maxCpuNbr--;
|
||||
if (minCpuNbr > maxCpuNbr)
|
||||
{
|
||||
int tmp = maxCpuNbr;
|
||||
maxCpuNbr = minCpuNbr;
|
||||
minCpuNbr = tmp;
|
||||
}
|
||||
}
|
||||
else if (!tokenizedLine.front().compare("Port"))
|
||||
port = tokenizedLine.back();
|
||||
else if (!tokenizedLine.front().compare("ComputerName"))
|
||||
computerName = tokenizedLine.back();
|
||||
else if (!tokenizedLine.front().compare("UserName"))
|
||||
userName = tokenizedLine.back();
|
||||
else if (!tokenizedLine.front().compare("Password"))
|
||||
password = tokenizedLine.back();
|
||||
else if (!tokenizedLine.front().compare("RemoteDrive"))
|
||||
remoteDrive = tokenizedLine.back();
|
||||
else if (!tokenizedLine.front().compare("RemoteDirectory"))
|
||||
remoteDirectory = tokenizedLine.back();
|
||||
else if (!tokenizedLine.front().compare("DynarePath"))
|
||||
dynarePath = tokenizedLine.back();
|
||||
else if (!tokenizedLine.front().compare("MatlabOctavePath"))
|
||||
matlabOctavePath = tokenizedLine.back();
|
||||
else if (!tokenizedLine.front().compare("NumberOfThreadsPerJob"))
|
||||
numberOfThreadsPerJob = atoi(tokenizedLine.back().c_str());
|
||||
else if (!tokenizedLine.front().compare("SingleCompThread"))
|
||||
if (tokenizedLine.back().compare("true") == 0)
|
||||
singleCompThread = true;
|
||||
else if (tokenizedLine.back().compare("false") == 0)
|
||||
singleCompThread = false;
|
||||
else
|
||||
{
|
||||
cerr << "ERROR (in config file): The value passed to SingleCompThread may only be 'true' or 'false'." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else if (!tokenizedLine.front().compare("OperatingSystem"))
|
||||
operatingSystem = tokenizedLine.back();
|
||||
else if (!tokenizedLine.front().compare("Members"))
|
||||
{
|
||||
char_separator<char> sep(" ,;", "()", drop_empty_tokens);
|
||||
tokenizer<char_separator<char> > tokens(tokenizedLine.back(), sep);
|
||||
bool begin_weight = false;
|
||||
string node_name;
|
||||
for (tokenizer<char_separator<char> >::iterator it = tokens.begin();
|
||||
it != tokens.end(); it++)
|
||||
{
|
||||
string token(*it);
|
||||
if (token.compare("(") == 0)
|
||||
{
|
||||
begin_weight = true;
|
||||
continue;
|
||||
}
|
||||
else if (token.compare(")") == 0)
|
||||
{
|
||||
node_name.clear();
|
||||
begin_weight = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!begin_weight)
|
||||
{
|
||||
if (!node_name.empty())
|
||||
if (member_nodes.find(node_name) != member_nodes.end())
|
||||
{
|
||||
cerr << "ERROR (in config file): Node entered twice in specification of cluster." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
member_nodes[node_name] = 1.0;
|
||||
node_name = token;
|
||||
}
|
||||
else
|
||||
try
|
||||
{
|
||||
double weight = lexical_cast<double>(token.c_str());
|
||||
if (weight <= 0)
|
||||
{
|
||||
cerr << "ERROR (in config file): Misspecification of weights passed to Members option." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
member_nodes[node_name] = weight;
|
||||
}
|
||||
catch (bad_lexical_cast &)
|
||||
{
|
||||
cerr << "ERROR (in config file): Misspecification of weights passed to Members option." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (!node_name.empty())
|
||||
if (member_nodes.find(node_name) == member_nodes.end())
|
||||
member_nodes[node_name] = 1.0;
|
||||
else
|
||||
{
|
||||
cerr << "ERROR (in config file): Node entered twice in specification of cluster." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "ERROR (in config file): Option " << tokenizedLine.front() << " is invalid." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!global_init_file.empty())
|
||||
addHooksConfFileElement(global_init_file);
|
||||
else if (!includepath.empty())
|
||||
addPathsConfFileElement(includepath);
|
||||
else
|
||||
addParallelConfFileElement(inNode, inCluster, member_nodes, name,
|
||||
computerName, port, minCpuNbr, maxCpuNbr, userName,
|
||||
password, remoteDrive, remoteDirectory,
|
||||
dynarePath, matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
|
||||
operatingSystem);
|
||||
|
||||
configFile->close();
|
||||
delete configFile;
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::addHooksConfFileElement(string &global_init_file)
|
||||
{
|
||||
if (global_init_file.empty())
|
||||
{
|
||||
cerr << "ERROR: The global initialization file must be passed to the GlobalInitFile option." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
hooks.push_back(new Hook(global_init_file));
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::addPathsConfFileElement(vector<string> &includepath)
|
||||
{
|
||||
if (includepath.empty())
|
||||
{
|
||||
cerr << "ERROR: The path to be included must be passed to the Include option." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
paths.push_back(new Path(includepath));
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, member_nodes_t member_nodes,
|
||||
string &name, string &computerName, string port, int minCpuNbr, int maxCpuNbr, string &userName,
|
||||
string &password, string &remoteDrive, string &remoteDirectory,
|
||||
string &dynarePath, string &matlabOctavePath, bool singleCompThread, int numberOfThreadsPerJob,
|
||||
string &operatingSystem)
|
||||
{
|
||||
//! ADD NODE
|
||||
if (inNode)
|
||||
if (!member_nodes.empty())
|
||||
{
|
||||
cerr << "Invalid option passed to [node]." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
if (name.empty() || slave_nodes.find(name) != slave_nodes.end())
|
||||
{
|
||||
cerr << "ERROR: Every node must be assigned a unique name." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
slave_nodes[name] = new SlaveNode(computerName, port, minCpuNbr, maxCpuNbr, userName,
|
||||
password, remoteDrive, remoteDirectory, dynarePath,
|
||||
matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
|
||||
operatingSystem);
|
||||
//! ADD CLUSTER
|
||||
else if (inCluster)
|
||||
if (minCpuNbr > 0 || maxCpuNbr > 0 || !userName.empty()
|
||||
|| !password.empty() || !remoteDrive.empty() || !remoteDirectory.empty()
|
||||
|| !dynarePath.empty() || !matlabOctavePath.empty() || !operatingSystem.empty())
|
||||
{
|
||||
cerr << "Invalid option passed to [cluster]." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
if (name.empty() || clusters.find(name) != clusters.end())
|
||||
{
|
||||
cerr << "ERROR: The cluster must be assigned a unique name." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clusters.empty())
|
||||
firstClusterName = name;
|
||||
clusters[name] = new Cluster(member_nodes);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::checkPass(WarningConsolidation &warnings) const
|
||||
{
|
||||
bool global_init_file_declared = false;
|
||||
for (vector<Hook *>::const_iterator it = hooks.begin(); it != hooks.end(); it++)
|
||||
{
|
||||
const map <string, string> hookmap = (*it)->get_hooks();
|
||||
for (map <string, string>::const_iterator mapit = hookmap.begin(); mapit != hookmap.end(); mapit++)
|
||||
if (mapit->first.compare("global_init_file") == 0)
|
||||
if (global_init_file_declared == true)
|
||||
{
|
||||
cerr << "ERROR: Only one global initialization file may be provided." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
global_init_file_declared = true;
|
||||
}
|
||||
|
||||
if (!parallel && !parallel_test)
|
||||
return;
|
||||
|
||||
//! Check Slave Nodes
|
||||
if (slave_nodes.empty())
|
||||
{
|
||||
cerr << "ERROR: At least one node must be defined in the config file." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (map<string, SlaveNode *>::const_iterator it = slave_nodes.begin();
|
||||
it != slave_nodes.end(); it++)
|
||||
{
|
||||
#if !defined(_WIN32) && !defined(__CYGWIN32__)
|
||||
//For Linux/Mac, check that cpuNbr starts at 0
|
||||
if (it->second->minCpuNbr != 0)
|
||||
warnings << "WARNING: On Unix-based operating systems, you cannot specify the CPU that is "
|
||||
<< "used in parallel processing. This will be adjusted for you such that the "
|
||||
<< "same number of CPUs are used." << endl;
|
||||
#endif
|
||||
if (!it->second->port.empty())
|
||||
try
|
||||
{
|
||||
boost::lexical_cast< int >(it->second->port);
|
||||
}
|
||||
catch (const boost::bad_lexical_cast &)
|
||||
{
|
||||
cerr << "ERROR (node " << it->first << "): the port must be an integer." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!it->second->computerName.compare("localhost")) // We are working locally
|
||||
{
|
||||
if (!it->second->remoteDrive.empty())
|
||||
{
|
||||
cerr << "ERROR (node " << it->first << "): the RemoteDrive option may not be passed for a local node." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!it->second->remoteDirectory.empty())
|
||||
{
|
||||
cerr << "ERROR (node " << it->first << "): the RemoteDirectory option may not be passed for a local node." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (it->second->userName.empty())
|
||||
{
|
||||
cerr << "ERROR (node " << it->first << "): the UserName option must be passed for every remote node." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (it->second->operatingSystem.compare("windows") == 0)
|
||||
{
|
||||
if (it->second->password.empty())
|
||||
{
|
||||
cerr << "ERROR (node " << it->first << "): the Password option must be passed under Windows for every remote node." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (it->second->remoteDrive.empty())
|
||||
{
|
||||
cerr << "ERROR (node " << it->first << "): the RemoteDrive option must be passed under Windows for every remote node." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#if defined(_WIN32) || defined(__CYGWIN32__)
|
||||
if (it->second->operatingSystem.empty())
|
||||
{
|
||||
if (it->second->password.empty())
|
||||
{
|
||||
cerr << "ERROR (node " << it->first << "): the Password option must be passed under Windows for every remote node." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (it->second->remoteDrive.empty())
|
||||
{
|
||||
cerr << "ERROR (node " << it->first << "): the RemoteDrive option must be passed under Windows for every remote node." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (it->second->remoteDirectory.empty())
|
||||
{
|
||||
cerr << "ERROR (node " << it->first << "): the RemoteDirectory must be specified for every remote node." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Check Clusters
|
||||
if (clusters.empty())
|
||||
{
|
||||
cerr << "ERROR: At least one cluster must be defined in the config file." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!cluster_name.empty() && clusters.find(cluster_name) == clusters.end())
|
||||
{
|
||||
cerr << "ERROR: Cluster Name " << cluster_name << " was not found in the config file." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (map<string, Cluster *>::const_iterator it = clusters.begin();
|
||||
it != clusters.end(); it++)
|
||||
for (member_nodes_t::const_iterator itmn = it->second->member_nodes.begin();
|
||||
itmn != it->second->member_nodes.end(); itmn++)
|
||||
if (slave_nodes.find(itmn->first) == slave_nodes.end())
|
||||
{
|
||||
cerr << "Error: node " << itmn->first << " specified in cluster " << it->first << " was not found" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::transformPass()
|
||||
{
|
||||
if (!parallel && !parallel_test)
|
||||
return;
|
||||
|
||||
#if !defined(_WIN32) && !defined(__CYGWIN32__)
|
||||
//For Linux/Mac, check that cpuNbr starts at 0
|
||||
for (map<string, SlaveNode *>::const_iterator it = slave_nodes.begin();
|
||||
it != slave_nodes.end(); it++)
|
||||
if (it->second->minCpuNbr != 0)
|
||||
{
|
||||
it->second->maxCpuNbr = it->second->maxCpuNbr - it->second->minCpuNbr;
|
||||
it->second->minCpuNbr = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
map<string, Cluster *>::const_iterator cluster_it;
|
||||
if (cluster_name.empty())
|
||||
cluster_it = clusters.find(firstClusterName);
|
||||
else
|
||||
cluster_it = clusters.find(cluster_name);
|
||||
|
||||
double weight_denominator = 0.0;
|
||||
for (member_nodes_t::const_iterator it = cluster_it->second->member_nodes.begin();
|
||||
it != cluster_it->second->member_nodes.end(); it++)
|
||||
weight_denominator += it->second;
|
||||
|
||||
for (member_nodes_t::iterator it = cluster_it->second->member_nodes.begin();
|
||||
it != cluster_it->second->member_nodes.end(); it++)
|
||||
it->second /= weight_denominator;
|
||||
}
|
||||
|
||||
vector<string>
|
||||
ConfigFile::getIncludePaths() const
|
||||
{
|
||||
vector<string> include_paths;
|
||||
for (vector<Path *>::const_iterator it = paths.begin(); it != paths.end(); it++)
|
||||
{
|
||||
map <string, vector<string> > pathmap = (*it)->get_paths();
|
||||
for (map <string, vector<string> >::const_iterator mapit = pathmap.begin(); mapit != pathmap.end(); mapit++)
|
||||
for (vector<string>::const_iterator vecit = mapit->second.begin(); vecit != mapit->second.end(); vecit++)
|
||||
include_paths.push_back(*vecit);
|
||||
}
|
||||
return include_paths;
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::writeHooks(ostream &output) const
|
||||
{
|
||||
for (vector<Hook *>::const_iterator it = hooks.begin(); it != hooks.end(); it++)
|
||||
{
|
||||
map <string, string> hookmap = (*it)->get_hooks();
|
||||
for (map <string, string>::const_iterator mapit = hookmap.begin(); mapit != hookmap.end(); mapit++)
|
||||
output << "options_." << mapit->first << " = '" << mapit->second << "';" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::writeCluster(ostream &output) const
|
||||
{
|
||||
if (!parallel && !parallel_test)
|
||||
return;
|
||||
|
||||
map<string, Cluster *>::const_iterator cluster_it;
|
||||
if (cluster_name.empty())
|
||||
cluster_it = clusters.find(firstClusterName);
|
||||
else
|
||||
cluster_it = clusters.find(cluster_name);
|
||||
|
||||
int i = 1;
|
||||
for (map<string, SlaveNode *>::const_iterator it = slave_nodes.begin();
|
||||
it != slave_nodes.end(); it++)
|
||||
{
|
||||
bool slave_node_in_member_nodes = false;
|
||||
for (member_nodes_t::const_iterator itmn = cluster_it->second->member_nodes.begin();
|
||||
itmn != cluster_it->second->member_nodes.end(); itmn++)
|
||||
if (!it->first.compare(itmn->first))
|
||||
slave_node_in_member_nodes = true;
|
||||
|
||||
if (!slave_node_in_member_nodes)
|
||||
continue;
|
||||
|
||||
output << "options_.parallel";
|
||||
if (i > 1)
|
||||
output << "(" << i << ")";
|
||||
i++;
|
||||
output << " = struct('Local', ";
|
||||
if (it->second->computerName.compare("localhost"))
|
||||
output << "0, ";
|
||||
else
|
||||
output << "1, ";
|
||||
|
||||
output << "'ComputerName', '" << it->second->computerName << "', "
|
||||
<< "'Port', '" << it->second->port << "', "
|
||||
<< "'CPUnbr', [" << it->second->minCpuNbr << ":" << it->second->maxCpuNbr << "], "
|
||||
<< "'UserName', '" << it->second->userName << "', "
|
||||
<< "'Password', '" << it->second->password << "', "
|
||||
<< "'RemoteDrive', '" << it->second->remoteDrive << "', "
|
||||
<< "'RemoteDirectory', '" << it->second->remoteDirectory << "', "
|
||||
<< "'DynarePath', '" << it->second->dynarePath << "', "
|
||||
<< "'MatlabOctavePath', '" << it->second->matlabOctavePath << "', "
|
||||
<< "'OperatingSystem', '" << it->second->operatingSystem << "', "
|
||||
<< "'NodeWeight', '" << (cluster_it->second->member_nodes.find(it->first))->second << "', "
|
||||
<< "'NumberOfThreadsPerJob', " << it->second->numberOfThreadsPerJob << ", ";
|
||||
|
||||
if (it->second->singleCompThread)
|
||||
output << "'SingleCompThread', 'true');" << endl;
|
||||
else
|
||||
output << "'SingleCompThread', 'false');" << endl;
|
||||
}
|
||||
|
||||
if (parallel_slave_open_mode)
|
||||
output << "options_.parallel_info.leaveSlaveOpen = 1;" << endl;
|
||||
|
||||
output << "InitializeComputationalEnvironment();" << endl;
|
||||
if (parallel_test)
|
||||
output << "ErrorCode = AnalyseComputationalEnvironment(options_.parallel, options_.parallel_info);" << endl
|
||||
<< "disp(['AnalyseComputationalEnvironment returned with Error Code: ' num2str(ErrorCode)]);" << endl
|
||||
<< "diary off;" << endl
|
||||
<< "return;" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::writeEndParallel(ostream &output) const
|
||||
{
|
||||
if ((!parallel && !parallel_test) || !parallel_slave_open_mode)
|
||||
return;
|
||||
|
||||
output << "if options_.parallel_info.leaveSlaveOpen == 1" << endl
|
||||
<< " closeSlave(options_.parallel,options_.parallel_info.RemoteTmpFolder);" << endl
|
||||
<< "end" << endl;
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_FILE_HH
|
||||
#define _CONFIG_FILE_HH
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "WarningConsolidation.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef map<string, double> member_nodes_t;
|
||||
|
||||
class Hook
|
||||
{
|
||||
public:
|
||||
Hook(string &global_init_file_arg);
|
||||
~Hook();
|
||||
private:
|
||||
map<string, string> hooks;
|
||||
public:
|
||||
inline map<string, string>
|
||||
get_hooks()
|
||||
{
|
||||
return hooks;
|
||||
};
|
||||
};
|
||||
|
||||
class Path
|
||||
{
|
||||
public:
|
||||
Path(vector<string> &includepath_arg);
|
||||
~Path();
|
||||
private:
|
||||
map<string, vector<string> > paths;
|
||||
public:
|
||||
inline map<string, vector<string> >
|
||||
get_paths()
|
||||
{
|
||||
return paths;
|
||||
};
|
||||
};
|
||||
|
||||
class SlaveNode
|
||||
{
|
||||
friend class ConfigFile;
|
||||
public:
|
||||
SlaveNode(string &computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string &userName_arg,
|
||||
string &password_arg, string &remoteDrive_arg, string &remoteDirectory_arg,
|
||||
string &dynarePath_arg, string &matlabOctavePath_arg, bool singleCompThread_arg, int numberOfThreadsPerJob_arg,
|
||||
string &operatingSystem_arg);
|
||||
~SlaveNode();
|
||||
|
||||
protected:
|
||||
const string computerName;
|
||||
const string port;
|
||||
int minCpuNbr;
|
||||
int maxCpuNbr;
|
||||
const string userName;
|
||||
const string password;
|
||||
const string remoteDrive;
|
||||
const string remoteDirectory;
|
||||
const string dynarePath;
|
||||
const string matlabOctavePath;
|
||||
const bool singleCompThread;
|
||||
const int numberOfThreadsPerJob;
|
||||
const string operatingSystem;
|
||||
};
|
||||
|
||||
class Cluster
|
||||
{
|
||||
friend class ConfigFile;
|
||||
public:
|
||||
Cluster(member_nodes_t member_nodes_arg);
|
||||
~Cluster();
|
||||
|
||||
protected:
|
||||
member_nodes_t member_nodes;
|
||||
};
|
||||
|
||||
//! The abstract representation of a "config" file
|
||||
class ConfigFile
|
||||
{
|
||||
public:
|
||||
ConfigFile(bool parallel_arg, bool parallel_test_arg, bool parallel_slave_open_mode_arg, const string &cluster_name);
|
||||
~ConfigFile();
|
||||
|
||||
private:
|
||||
const bool parallel;
|
||||
const bool parallel_test;
|
||||
const bool parallel_slave_open_mode;
|
||||
const string cluster_name;
|
||||
string firstClusterName;
|
||||
//! Hooks
|
||||
vector<Hook *> hooks;
|
||||
//! Paths
|
||||
vector<Path *> paths;
|
||||
//! Cluster Table
|
||||
map<string, Cluster *> clusters;
|
||||
//! Node Map
|
||||
map<string, SlaveNode *> slave_nodes;
|
||||
//! Add Hooks
|
||||
void addHooksConfFileElement(string &global_init_file);
|
||||
//! Add Paths
|
||||
void addPathsConfFileElement(vector<string> &includepath);
|
||||
//! Add a SlaveNode or a Cluster object
|
||||
void addParallelConfFileElement(bool inNode, bool inCluster, member_nodes_t member_nodes, string &name,
|
||||
string &computerName, string port, int minCpuNbr, int maxCpuNbr, string &userName,
|
||||
string &password, string &remoteDrive, string &remoteDirectory,
|
||||
string &dynarePath, string &matlabOctavePath, bool singleCompThread, int numberOfThreadsPerJob,
|
||||
string &operatingSystem);
|
||||
public:
|
||||
//! Parse config file
|
||||
void getConfigFileInfo(const string ¶llel_config_file);
|
||||
//! Check Pass
|
||||
void checkPass(WarningConsolidation &warnings) const;
|
||||
//! Check Pass
|
||||
void transformPass();
|
||||
//! Get Path Info
|
||||
vector<string> getIncludePaths() const;
|
||||
//! Write any hooks
|
||||
void writeHooks(ostream &output) const;
|
||||
//! Create options_.parallel structure, write options
|
||||
void writeCluster(ostream &output) const;
|
||||
//! Close slave nodes if needed
|
||||
void writeEndParallel(ostream &output) const;
|
||||
};
|
||||
|
||||
#endif // ! CONFIG_FILE_HH
|
|
@ -1,796 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2018 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#include "DataTree.hh"
|
||||
|
||||
DataTree::DataTree(SymbolTable &symbol_table_arg,
|
||||
NumericalConstants &num_constants_arg,
|
||||
ExternalFunctionsTable &external_functions_table_arg) :
|
||||
symbol_table(symbol_table_arg),
|
||||
num_constants(num_constants_arg),
|
||||
external_functions_table(external_functions_table_arg),
|
||||
node_counter(0)
|
||||
{
|
||||
Zero = AddNonNegativeConstant("0");
|
||||
One = AddNonNegativeConstant("1");
|
||||
Two = AddNonNegativeConstant("2");
|
||||
|
||||
MinusOne = AddUMinus(One);
|
||||
|
||||
NaN = AddNonNegativeConstant("NaN");
|
||||
Infinity = AddNonNegativeConstant("Inf");
|
||||
MinusInfinity = AddUMinus(Infinity);
|
||||
|
||||
Pi = AddNonNegativeConstant("3.141592653589793");
|
||||
}
|
||||
|
||||
DataTree::~DataTree()
|
||||
{
|
||||
for (node_list_t::iterator it = node_list.begin(); it != node_list.end(); it++)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddNonNegativeConstant(const string &value)
|
||||
{
|
||||
int id = num_constants.AddNonNegativeConstant(value);
|
||||
|
||||
num_const_node_map_t::iterator it = num_const_node_map.find(id);
|
||||
if (it != num_const_node_map.end())
|
||||
return it->second;
|
||||
else
|
||||
return new NumConstNode(*this, id);
|
||||
}
|
||||
|
||||
VariableNode *
|
||||
DataTree::AddVariableInternal(int symb_id, int lag)
|
||||
{
|
||||
variable_node_map_t::iterator it = variable_node_map.find(make_pair(symb_id, lag));
|
||||
if (it != variable_node_map.end())
|
||||
return it->second;
|
||||
else
|
||||
return new VariableNode(*this, symb_id, lag);
|
||||
}
|
||||
|
||||
bool
|
||||
DataTree::ParamUsedWithLeadLagInternal() const
|
||||
{
|
||||
for (variable_node_map_t::const_iterator it = variable_node_map.begin();
|
||||
it != variable_node_map.end(); it++)
|
||||
if (symbol_table.getType(it->first.first) == eParameter && it->first.second != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
VariableNode *
|
||||
DataTree::AddVariable(int symb_id, int lag)
|
||||
{
|
||||
assert(lag == 0);
|
||||
return AddVariableInternal(symb_id, lag);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddPlus(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
if (iArg1 != Zero && iArg2 != Zero)
|
||||
{
|
||||
// Simplify x+(-y) in x-y
|
||||
UnaryOpNode *uarg2 = dynamic_cast<UnaryOpNode *>(iArg2);
|
||||
if (uarg2 != NULL && uarg2->get_op_code() == oUminus)
|
||||
return AddMinus(iArg1, uarg2->get_arg());
|
||||
|
||||
// To treat commutativity of "+"
|
||||
// Nodes iArg1 and iArg2 are sorted by index
|
||||
if (iArg1->idx > iArg2->idx)
|
||||
{
|
||||
expr_t tmp = iArg1;
|
||||
iArg1 = iArg2;
|
||||
iArg2 = tmp;
|
||||
}
|
||||
return AddBinaryOp(iArg1, oPlus, iArg2);
|
||||
}
|
||||
else if (iArg1 != Zero)
|
||||
return iArg1;
|
||||
else if (iArg2 != Zero)
|
||||
return iArg2;
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddMinus(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
if (iArg2 == Zero)
|
||||
return iArg1;
|
||||
|
||||
if (iArg1 == Zero)
|
||||
return AddUMinus(iArg2);
|
||||
|
||||
if (iArg1 == iArg2)
|
||||
return Zero;
|
||||
|
||||
return AddBinaryOp(iArg1, oMinus, iArg2);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddUMinus(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
{
|
||||
// Simplify -(-x) in x
|
||||
UnaryOpNode *uarg = dynamic_cast<UnaryOpNode *>(iArg1);
|
||||
if (uarg != NULL && uarg->get_op_code() == oUminus)
|
||||
return uarg->get_arg();
|
||||
|
||||
return AddUnaryOp(oUminus, iArg1);
|
||||
}
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddTimes(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
if (iArg1 == MinusOne)
|
||||
return AddUMinus(iArg2);
|
||||
else if (iArg2 == MinusOne)
|
||||
return AddUMinus(iArg1);
|
||||
else if (iArg1 != Zero && iArg1 != One && iArg2 != Zero && iArg2 != One)
|
||||
{
|
||||
// To treat commutativity of "*"
|
||||
// Nodes iArg1 and iArg2 are sorted by index
|
||||
if (iArg1->idx > iArg2->idx)
|
||||
{
|
||||
expr_t tmp = iArg1;
|
||||
iArg1 = iArg2;
|
||||
iArg2 = tmp;
|
||||
}
|
||||
return AddBinaryOp(iArg1, oTimes, iArg2);
|
||||
}
|
||||
else if (iArg1 != Zero && iArg1 != One && iArg2 == One)
|
||||
return iArg1;
|
||||
else if (iArg2 != Zero && iArg2 != One && iArg1 == One)
|
||||
return iArg2;
|
||||
else if (iArg2 == One && iArg1 == One)
|
||||
return One;
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddDivide(expr_t iArg1, expr_t iArg2) throw (DivisionByZeroException)
|
||||
{
|
||||
if (iArg2 == One)
|
||||
return iArg1;
|
||||
|
||||
// This test should be before the next two, otherwise 0/0 won't be rejected
|
||||
if (iArg2 == Zero)
|
||||
{
|
||||
cerr << "ERROR: Division by zero!" << endl;
|
||||
throw DivisionByZeroException();
|
||||
}
|
||||
|
||||
if (iArg1 == Zero)
|
||||
return Zero;
|
||||
|
||||
if (iArg1 == iArg2)
|
||||
return One;
|
||||
|
||||
return AddBinaryOp(iArg1, oDivide, iArg2);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddLess(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
return AddBinaryOp(iArg1, oLess, iArg2);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddGreater(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
return AddBinaryOp(iArg1, oGreater, iArg2);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddLessEqual(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
return AddBinaryOp(iArg1, oLessEqual, iArg2);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddGreaterEqual(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
return AddBinaryOp(iArg1, oGreaterEqual, iArg2);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddEqualEqual(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
return AddBinaryOp(iArg1, oEqualEqual, iArg2);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddDifferent(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
return AddBinaryOp(iArg1, oDifferent, iArg2);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddPower(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
if (iArg1 != Zero && iArg2 != Zero && iArg1 != One && iArg2 != One)
|
||||
return AddBinaryOp(iArg1, oPower, iArg2);
|
||||
else if (iArg1 == One)
|
||||
return One;
|
||||
else if (iArg2 == One)
|
||||
return iArg1;
|
||||
else if (iArg2 == Zero)
|
||||
return One;
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddPowerDeriv(expr_t iArg1, expr_t iArg2, int powerDerivOrder)
|
||||
{
|
||||
assert(powerDerivOrder > 0);
|
||||
return AddBinaryOp(iArg1, oPowerDeriv, iArg2, powerDerivOrder);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddDiff(expr_t iArg1)
|
||||
{
|
||||
return AddUnaryOp(oDiff, iArg1);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddAdl(expr_t iArg1, const string &name, int lag)
|
||||
{
|
||||
return AddUnaryOp(oAdl, iArg1, 0, 0, 0, string(name), lag);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddAdl(expr_t iArg1, const string &name, const vector<int> &lags)
|
||||
{
|
||||
return AddUnaryOp(oAdl, iArg1, 0, 0, 0, string(name), -1, lags);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddExp(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oExp, iArg1);
|
||||
else
|
||||
return One;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddLog(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero && iArg1 != One)
|
||||
return AddUnaryOp(oLog, iArg1);
|
||||
else if (iArg1 == One)
|
||||
return Zero;
|
||||
else
|
||||
{
|
||||
cerr << "ERROR: log(0) not defined!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddLog10(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero && iArg1 != One)
|
||||
return AddUnaryOp(oLog10, iArg1);
|
||||
else if (iArg1 == One)
|
||||
return Zero;
|
||||
else
|
||||
{
|
||||
cerr << "ERROR: log10(0) not defined!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddCos(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oCos, iArg1);
|
||||
else
|
||||
return One;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddSin(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oSin, iArg1);
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddTan(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oTan, iArg1);
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddAcos(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != One)
|
||||
return AddUnaryOp(oAcos, iArg1);
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddAsin(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oAsin, iArg1);
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddAtan(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oAtan, iArg1);
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddCosh(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oCosh, iArg1);
|
||||
else
|
||||
return One;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddSinh(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oSinh, iArg1);
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddTanh(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oTanh, iArg1);
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddAcosh(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != One)
|
||||
return AddUnaryOp(oAcosh, iArg1);
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddAsinh(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oAsinh, iArg1);
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddAtanh(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oAtanh, iArg1);
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddSqrt(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oSqrt, iArg1);
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddAbs(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 == Zero)
|
||||
return Zero;
|
||||
if (iArg1 == One)
|
||||
return One;
|
||||
else
|
||||
return AddUnaryOp(oAbs, iArg1);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddSign(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 == Zero)
|
||||
return Zero;
|
||||
if (iArg1 == One)
|
||||
return One;
|
||||
else
|
||||
return AddUnaryOp(oSign, iArg1);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddErf(expr_t iArg1)
|
||||
{
|
||||
if (iArg1 != Zero)
|
||||
return AddUnaryOp(oErf, iArg1);
|
||||
else
|
||||
return Zero;
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddMax(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
return AddBinaryOp(iArg1, oMax, iArg2);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddMin(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
return AddBinaryOp(iArg1, oMin, iArg2);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddNormcdf(expr_t iArg1, expr_t iArg2, expr_t iArg3)
|
||||
{
|
||||
return AddTrinaryOp(iArg1, oNormcdf, iArg2, iArg3);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddNormpdf(expr_t iArg1, expr_t iArg2, expr_t iArg3)
|
||||
{
|
||||
return AddTrinaryOp(iArg1, oNormpdf, iArg2, iArg3);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddSteadyState(expr_t iArg1)
|
||||
{
|
||||
return AddUnaryOp(oSteadyState, iArg1);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddSteadyStateParamDeriv(expr_t iArg1, int param_symb_id)
|
||||
{
|
||||
return AddUnaryOp(oSteadyStateParamDeriv, iArg1, 0, param_symb_id);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddSteadyStateParam2ndDeriv(expr_t iArg1, int param1_symb_id, int param2_symb_id)
|
||||
{
|
||||
return AddUnaryOp(oSteadyStateParam2ndDeriv, iArg1, 0, param1_symb_id, param2_symb_id);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddExpectation(int iArg1, expr_t iArg2)
|
||||
{
|
||||
return AddUnaryOp(oExpectation, iArg2, iArg1);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddVarExpectation(const int symb_id, const int forecast_horizon, const string &model_name)
|
||||
{
|
||||
assert(symbol_table.getType(symb_id) == eEndogenous);
|
||||
|
||||
var_expectation_node_map_t::iterator it = var_expectation_node_map.find(make_pair(model_name, make_pair(symb_id, forecast_horizon)));
|
||||
if (it != var_expectation_node_map.end())
|
||||
return it->second;
|
||||
|
||||
return new VarExpectationNode(*this, symb_id, forecast_horizon, model_name);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddPacExpectation(const string &model_name, const string &var_model_name, const int discount_id, const int growth_id)
|
||||
{
|
||||
pac_expectation_node_map_t::iterator it =
|
||||
pac_expectation_node_map.find(make_pair(model_name, make_pair(var_model_name, make_pair(discount_id, growth_id))));
|
||||
if (it != pac_expectation_node_map.end())
|
||||
return it->second;
|
||||
|
||||
return new PacExpectationNode(*this, model_name, var_model_name, discount_id, growth_id);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddEqual(expr_t iArg1, expr_t iArg2)
|
||||
{
|
||||
return AddBinaryOp(iArg1, oEqual, iArg2);
|
||||
}
|
||||
|
||||
void
|
||||
DataTree::AddLocalVariable(int symb_id, expr_t value) throw (LocalVariableException)
|
||||
{
|
||||
assert(symbol_table.getType(symb_id) == eModelLocalVariable);
|
||||
|
||||
// Throw an exception if symbol already declared
|
||||
map<int, expr_t>::iterator it = local_variables_table.find(symb_id);
|
||||
if (it != local_variables_table.end())
|
||||
throw LocalVariableException(symbol_table.getName(symb_id));
|
||||
|
||||
local_variables_table[symb_id] = value;
|
||||
local_variables_vector.push_back(symb_id);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddExternalFunction(int symb_id, const vector<expr_t> &arguments)
|
||||
{
|
||||
assert(symbol_table.getType(symb_id) == eExternalFunction);
|
||||
|
||||
external_function_node_map_t::iterator it = external_function_node_map.find(make_pair(arguments, symb_id));
|
||||
if (it != external_function_node_map.end())
|
||||
return it->second;
|
||||
|
||||
return new ExternalFunctionNode(*this, symb_id, arguments);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index)
|
||||
{
|
||||
assert(symbol_table.getType(top_level_symb_id) == eExternalFunction);
|
||||
|
||||
first_deriv_external_function_node_map_t::iterator it
|
||||
= first_deriv_external_function_node_map.find(make_pair(make_pair(arguments, input_index),
|
||||
top_level_symb_id));
|
||||
if (it != first_deriv_external_function_node_map.end())
|
||||
return it->second;
|
||||
|
||||
return new FirstDerivExternalFunctionNode(*this, top_level_symb_id, arguments, input_index);
|
||||
}
|
||||
|
||||
expr_t
|
||||
DataTree::AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index1, int input_index2)
|
||||
{
|
||||
assert(symbol_table.getType(top_level_symb_id) == eExternalFunction);
|
||||
|
||||
second_deriv_external_function_node_map_t::iterator it
|
||||
= second_deriv_external_function_node_map.find(make_pair(make_pair(arguments,
|
||||
make_pair(input_index1, input_index2)),
|
||||
top_level_symb_id));
|
||||
if (it != second_deriv_external_function_node_map.end())
|
||||
return it->second;
|
||||
|
||||
return new SecondDerivExternalFunctionNode(*this, top_level_symb_id, arguments, input_index1, input_index2);
|
||||
}
|
||||
|
||||
bool
|
||||
DataTree::isSymbolUsed(int symb_id) const
|
||||
{
|
||||
for (variable_node_map_t::const_iterator it = variable_node_map.begin();
|
||||
it != variable_node_map.end(); it++)
|
||||
if (it->first.first == symb_id)
|
||||
return true;
|
||||
|
||||
if (local_variables_table.find(symb_id) != local_variables_table.end())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
DataTree::getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException)
|
||||
{
|
||||
throw UnknownDerivIDException();
|
||||
}
|
||||
|
||||
SymbolType
|
||||
DataTree::getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException)
|
||||
{
|
||||
throw UnknownDerivIDException();
|
||||
}
|
||||
|
||||
int
|
||||
DataTree::getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException)
|
||||
{
|
||||
throw UnknownDerivIDException();
|
||||
}
|
||||
|
||||
int
|
||||
DataTree::getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException)
|
||||
{
|
||||
throw UnknownDerivIDException();
|
||||
}
|
||||
|
||||
void
|
||||
DataTree::addAllParamDerivId(set<int> &deriv_id_set)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
DataTree::getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException)
|
||||
{
|
||||
throw UnknownDerivIDException();
|
||||
}
|
||||
|
||||
bool
|
||||
DataTree::isUnaryOpUsed(UnaryOpcode opcode) const
|
||||
{
|
||||
for (unary_op_node_map_t::const_iterator it = unary_op_node_map.begin();
|
||||
it != unary_op_node_map.end(); it++)
|
||||
if (it->first.first.second == opcode)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DataTree::isBinaryOpUsed(BinaryOpcode opcode) const
|
||||
{
|
||||
for (binary_op_node_map_t::const_iterator it = binary_op_node_map.begin();
|
||||
it != binary_op_node_map.end(); it++)
|
||||
if (it->first.second == opcode)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DataTree::isTrinaryOpUsed(TrinaryOpcode opcode) const
|
||||
{
|
||||
for (trinary_op_node_map_t::const_iterator it = trinary_op_node_map.begin();
|
||||
it != trinary_op_node_map.end(); it++)
|
||||
if (it->first.second == opcode)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DataTree::isExternalFunctionUsed(int symb_id) const
|
||||
{
|
||||
for (external_function_node_map_t::const_iterator it = external_function_node_map.begin();
|
||||
it != external_function_node_map.end(); it++)
|
||||
if (it->first.second == symb_id)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DataTree::isFirstDerivExternalFunctionUsed(int symb_id) const
|
||||
{
|
||||
for (first_deriv_external_function_node_map_t::const_iterator it = first_deriv_external_function_node_map.begin();
|
||||
it != first_deriv_external_function_node_map.end(); it++)
|
||||
if (it->first.second == symb_id)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DataTree::isSecondDerivExternalFunctionUsed(int symb_id) const
|
||||
{
|
||||
for (second_deriv_external_function_node_map_t::const_iterator it = second_deriv_external_function_node_map.begin();
|
||||
it != second_deriv_external_function_node_map.end(); it++)
|
||||
if (it->first.second == symb_id)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
DataTree::minLagForSymbol(int symb_id) const
|
||||
{
|
||||
int r = 0;
|
||||
for (variable_node_map_t::const_iterator it = variable_node_map.begin();
|
||||
it != variable_node_map.end(); ++it)
|
||||
if (it->first.first == symb_id && it->first.second < r)
|
||||
r = it->first.second;
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
DataTree::writePowerDerivCHeader(ostream &output) const
|
||||
{
|
||||
if (isBinaryOpUsed(oPowerDeriv))
|
||||
output << "double getPowerDeriv(double, double, int);" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
DataTree::writePowerDeriv(ostream &output) const
|
||||
{
|
||||
if (isBinaryOpUsed(oPowerDeriv))
|
||||
output << "/*" << endl
|
||||
<< " * The k-th derivative of x^p" << endl
|
||||
<< " */" << endl
|
||||
<< "double getPowerDeriv(double x, double p, int k)" << endl
|
||||
<< "{" << endl
|
||||
<< "#ifdef _MSC_VER" << endl
|
||||
<< "# define nearbyint(x) (fabs((x)-floor(x)) < fabs((x)-ceil(x)) ? floor(x) : ceil(x))" << endl
|
||||
<< "#endif" << endl
|
||||
<< " if ( fabs(x) < " << NEAR_ZERO << " && p > 0 && k > p && fabs(p-nearbyint(p)) < " << NEAR_ZERO << " )" << endl
|
||||
<< " return 0.0;" << endl
|
||||
<< " else" << endl
|
||||
<< " {" << endl
|
||||
<< " int i = 0;" << endl
|
||||
<< " double dxp = pow(x, p-k);" << endl
|
||||
<< " for (; i<k; i++)" << endl
|
||||
<< " dxp *= p--;" << endl
|
||||
<< " return dxp;" << endl
|
||||
<< " }" << endl
|
||||
<< "}" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
DataTree::writeNormcdfCHeader(ostream &output) const
|
||||
{
|
||||
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
|
||||
if (isTrinaryOpUsed(oNormcdf))
|
||||
output << "#ifdef _MSC_VER" << endl
|
||||
<< "double normcdf(double);" << endl
|
||||
<< "#endif" << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DataTree::writeNormcdf(ostream &output) const
|
||||
{
|
||||
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
|
||||
if (isTrinaryOpUsed(oNormcdf))
|
||||
output << endl
|
||||
<< "#ifdef _MSC_VER" << endl
|
||||
<< "/*" << endl
|
||||
<< " * Define normcdf for MSVC compiler" << endl
|
||||
<< " */" << endl
|
||||
<< "double normcdf(double x)" << endl
|
||||
<< "{" << endl
|
||||
<< "#if _MSC_VER >= 1700" << endl
|
||||
<< " return 0.5 * erfc(-x * M_SQRT1_2);" << endl
|
||||
<< "#else" << endl
|
||||
<< " // From http://www.johndcook.com/blog/cpp_phi" << endl
|
||||
<< " double a1 = 0.254829592;" << endl
|
||||
<< " double a2 = -0.284496736;" << endl
|
||||
<< " double a3 = 1.421413741;" << endl
|
||||
<< " double a4 = -1.453152027;" << endl
|
||||
<< " double a5 = 1.061405429;" << endl
|
||||
<< " double p = 0.3275911;" << endl
|
||||
<< " int sign = (x < 0) ? -1 : 1;" << endl
|
||||
<< " x = fabs(x)/sqrt(2.0);" << endl
|
||||
<< " // From the Handbook of Mathematical Functions by Abramowitz and Stegun, formula 7.1.26" << endl
|
||||
<< " double t = 1.0/(1.0 + p*x);" << endl
|
||||
<< " double y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);" << endl
|
||||
<< " return 0.5*(1.0 + sign*y);" << endl
|
||||
<< "#endif" << endl
|
||||
<< "}" << endl
|
||||
<< "#endif" << endl;
|
||||
#endif
|
||||
}
|
|
@ -1,398 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2018 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _DATATREE_HH
|
||||
#define _DATATREE_HH
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
|
||||
#include "SymbolTable.hh"
|
||||
#include "NumericalConstants.hh"
|
||||
#include "ExternalFunctionsTable.hh"
|
||||
#include "ExprNode.hh"
|
||||
|
||||
#define CONSTANTS_PRECISION 16
|
||||
|
||||
class DataTree
|
||||
{
|
||||
friend class ExprNode;
|
||||
friend class NumConstNode;
|
||||
friend class VariableNode;
|
||||
friend class UnaryOpNode;
|
||||
friend class BinaryOpNode;
|
||||
friend class TrinaryOpNode;
|
||||
friend class AbstractExternalFunctionNode;
|
||||
friend class ExternalFunctionNode;
|
||||
friend class FirstDerivExternalFunctionNode;
|
||||
friend class SecondDerivExternalFunctionNode;
|
||||
friend class VarExpectationNode;
|
||||
friend class PacExpectationNode;
|
||||
protected:
|
||||
//! A reference to the symbol table
|
||||
SymbolTable &symbol_table;
|
||||
//! Reference to numerical constants table
|
||||
NumericalConstants &num_constants;
|
||||
//! A reference to the external functions table
|
||||
ExternalFunctionsTable &external_functions_table;
|
||||
|
||||
typedef map<int, NumConstNode *> num_const_node_map_t;
|
||||
num_const_node_map_t num_const_node_map;
|
||||
//! Pair (symbol_id, lag) used as key
|
||||
typedef map<pair<int, int>, VariableNode *> variable_node_map_t;
|
||||
variable_node_map_t variable_node_map;
|
||||
//! Pair( Pair(arg1, UnaryOpCode), Pair( Expectation Info Set, Pair(param1_symb_id, param2_symb_id)) ))
|
||||
|
||||
typedef map<pair<pair<expr_t, UnaryOpcode>, pair<pair<int, pair<int, int> >, pair<string, pair<int, vector<int> > > > >, UnaryOpNode *> unary_op_node_map_t;
|
||||
unary_op_node_map_t unary_op_node_map;
|
||||
//! Pair( Pair( Pair(arg1, arg2), order of Power Derivative), opCode)
|
||||
typedef map<pair<pair<pair<expr_t, expr_t>, int>, BinaryOpcode>, BinaryOpNode *> binary_op_node_map_t;
|
||||
binary_op_node_map_t binary_op_node_map;
|
||||
typedef map<pair<pair<pair<expr_t, expr_t>, expr_t>, TrinaryOpcode>, TrinaryOpNode *> trinary_op_node_map_t;
|
||||
trinary_op_node_map_t trinary_op_node_map;
|
||||
|
||||
// (arguments, symb_id) -> ExternalFunctionNode
|
||||
typedef map<pair<vector<expr_t>, int>, ExternalFunctionNode *> external_function_node_map_t;
|
||||
external_function_node_map_t external_function_node_map;
|
||||
|
||||
// (model_name, (symb_id, forecast_horizon)) -> VarExpectationNode
|
||||
typedef map<pair<string, pair<int, int> >, VarExpectationNode *> var_expectation_node_map_t;
|
||||
var_expectation_node_map_t var_expectation_node_map;
|
||||
|
||||
// (model_name, (discount, growth)) -> PacExpectationNode
|
||||
typedef map<pair<string, pair<string, pair<int, int> > >, PacExpectationNode *> pac_expectation_node_map_t;
|
||||
pac_expectation_node_map_t pac_expectation_node_map;
|
||||
|
||||
// ((arguments, deriv_idx), symb_id) -> FirstDerivExternalFunctionNode
|
||||
typedef map<pair<pair<vector<expr_t>, int>, int>, FirstDerivExternalFunctionNode *> first_deriv_external_function_node_map_t;
|
||||
first_deriv_external_function_node_map_t first_deriv_external_function_node_map;
|
||||
|
||||
// ((arguments, (deriv_idx1, deriv_idx2)), symb_id) -> SecondDerivExternalFunctionNode
|
||||
typedef map<pair<pair<vector<expr_t>, pair<int, int> >, int>, SecondDerivExternalFunctionNode *> second_deriv_external_function_node_map_t;
|
||||
second_deriv_external_function_node_map_t second_deriv_external_function_node_map;
|
||||
|
||||
//! Stores local variables value (maps symbol ID to corresponding node)
|
||||
map<int, expr_t> local_variables_table;
|
||||
//! Stores the order of appearance of local variables in the model block. Needed following change in #563
|
||||
vector<int> local_variables_vector;
|
||||
|
||||
//! Internal implementation of AddVariable(), without the check on the lag
|
||||
VariableNode *AddVariableInternal(int symb_id, int lag);
|
||||
|
||||
//! Internal implementation of ParamUsedWithLeadLag()
|
||||
bool ParamUsedWithLeadLagInternal() const;
|
||||
private:
|
||||
typedef list<expr_t> node_list_t;
|
||||
//! The list of nodes
|
||||
node_list_t node_list;
|
||||
//! A counter for filling ExprNode's idx field
|
||||
int node_counter;
|
||||
|
||||
inline expr_t AddPossiblyNegativeConstant(double val);
|
||||
inline expr_t AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set = 0, int param1_symb_id = 0, int param2_symb_id = 0, const string &adl_param_name = "", int adl_param_lag = -1, const vector<int> &adl_lags = vector<int>());
|
||||
inline expr_t AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder = 0);
|
||||
inline expr_t AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3);
|
||||
|
||||
public:
|
||||
DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg);
|
||||
virtual
|
||||
~DataTree();
|
||||
|
||||
//! Some predefined constants
|
||||
expr_t Zero, One, Two, MinusOne, NaN, Infinity, MinusInfinity, Pi;
|
||||
|
||||
//! Raised when a local parameter is declared twice
|
||||
class LocalVariableException
|
||||
{
|
||||
public:
|
||||
string name;
|
||||
LocalVariableException(const string &name_arg) : name(name_arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class DivisionByZeroException
|
||||
{
|
||||
};
|
||||
|
||||
//! Adds a non-negative numerical constant (possibly Inf or NaN)
|
||||
expr_t AddNonNegativeConstant(const string &value);
|
||||
//! Adds a variable
|
||||
/*! The default implementation of the method refuses any lag != 0 */
|
||||
virtual VariableNode *AddVariable(int symb_id, int lag = 0);
|
||||
//! Adds "arg1+arg2" to model tree
|
||||
expr_t AddPlus(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "arg1-arg2" to model tree
|
||||
expr_t AddMinus(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "-arg" to model tree
|
||||
expr_t AddUMinus(expr_t iArg1);
|
||||
//! Adds "arg1*arg2" to model tree
|
||||
expr_t AddTimes(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "arg1/arg2" to model tree
|
||||
expr_t AddDivide(expr_t iArg1, expr_t iArg2) throw (DivisionByZeroException);
|
||||
//! Adds "arg1<arg2" to model tree
|
||||
expr_t AddLess(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "arg1>arg2" to model tree
|
||||
expr_t AddGreater(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "arg1<=arg2" to model tree
|
||||
expr_t AddLessEqual(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "arg1>=arg2" to model tree
|
||||
expr_t AddGreaterEqual(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "arg1==arg2" to model tree
|
||||
expr_t AddEqualEqual(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "arg1!=arg2" to model tree
|
||||
expr_t AddDifferent(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "arg1^arg2" to model tree
|
||||
expr_t AddPower(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "getPowerDeriv(arg1, arg2, powerDerivOrder)" to model tree
|
||||
expr_t AddPowerDeriv(expr_t iArg1, expr_t iArg2, int powerDerivOrder);
|
||||
//! Adds "E(arg1)(arg2)" to model tree
|
||||
expr_t AddExpectation(int iArg1, expr_t iArg2);
|
||||
//! Adds "diff(arg)" to model tree
|
||||
expr_t AddDiff(expr_t iArg1);
|
||||
//! Adds "adl(arg1, arg2)" to model tree
|
||||
expr_t AddAdl(expr_t iArg1, const string &name, int lag);
|
||||
expr_t AddAdl(expr_t iArg1, const string &name, const vector<int> &lags);
|
||||
//! Adds "exp(arg)" to model tree
|
||||
expr_t AddExp(expr_t iArg1);
|
||||
//! Adds "log(arg)" to model tree
|
||||
expr_t AddLog(expr_t iArg1);
|
||||
//! Adds "log10(arg)" to model tree
|
||||
expr_t AddLog10(expr_t iArg1);
|
||||
//! Adds "cos(arg)" to model tree
|
||||
expr_t AddCos(expr_t iArg1);
|
||||
//! Adds "sin(arg)" to model tree
|
||||
expr_t AddSin(expr_t iArg1);
|
||||
//! Adds "tan(arg)" to model tree
|
||||
expr_t AddTan(expr_t iArg1);
|
||||
//! Adds "acos(arg)" to model tree
|
||||
expr_t AddAcos(expr_t iArg1);
|
||||
//! Adds "asin(arg)" to model tree
|
||||
expr_t AddAsin(expr_t iArg1);
|
||||
//! Adds "atan(arg)" to model tree
|
||||
expr_t AddAtan(expr_t iArg1);
|
||||
//! Adds "cosh(arg)" to model tree
|
||||
expr_t AddCosh(expr_t iArg1);
|
||||
//! Adds "sinh(arg)" to model tree
|
||||
expr_t AddSinh(expr_t iArg1);
|
||||
//! Adds "tanh(arg)" to model tree
|
||||
expr_t AddTanh(expr_t iArg1);
|
||||
//! Adds "acosh(arg)" to model tree
|
||||
expr_t AddAcosh(expr_t iArg1);
|
||||
//! Adds "asinh(arg)" to model tree
|
||||
expr_t AddAsinh(expr_t iArg1);
|
||||
//! Adds "atanh(args)" to model tree
|
||||
expr_t AddAtanh(expr_t iArg1);
|
||||
//! Adds "sqrt(arg)" to model tree
|
||||
expr_t AddSqrt(expr_t iArg1);
|
||||
//! Adds "abs(arg)" to model tree
|
||||
expr_t AddAbs(expr_t iArg1);
|
||||
//! Adds "sign(arg)" to model tree
|
||||
expr_t AddSign(expr_t iArg1);
|
||||
//! Adds "erf(arg)" to model tree
|
||||
expr_t AddErf(expr_t iArg1);
|
||||
//! Adds "max(arg1,arg2)" to model tree
|
||||
expr_t AddMax(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "min(arg1,arg2)" to model tree
|
||||
expr_t AddMin(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "normcdf(arg1,arg2,arg3)" to model tree
|
||||
expr_t AddNormcdf(expr_t iArg1, expr_t iArg2, expr_t iArg3);
|
||||
//! Adds "normpdf(arg1,arg2,arg3)" to model tree
|
||||
expr_t AddNormpdf(expr_t iArg1, expr_t iArg2, expr_t iArg3);
|
||||
//! Adds "steadyState(arg)" to model tree
|
||||
expr_t AddSteadyState(expr_t iArg1);
|
||||
//! Add derivative of steady state w.r.t. parameter to model tree
|
||||
expr_t AddSteadyStateParamDeriv(expr_t iArg1, int param_symb_id);
|
||||
//! Add 2nd derivative of steady state w.r.t. parameter to model tree
|
||||
expr_t AddSteadyStateParam2ndDeriv(expr_t iArg1, int param1_symb_id, int param2_symb_id);
|
||||
//! Adds "arg1=arg2" to model tree
|
||||
expr_t AddEqual(expr_t iArg1, expr_t iArg2);
|
||||
//! Adds "var_expectation(arg1, arg2, model_name=arg3)" to model tree
|
||||
expr_t AddVarExpectation(const int symb_id, const int forecast_horizon, const string &model_name);
|
||||
//! Adds pac_expectation command to model tree
|
||||
expr_t AddPacExpectation(const string &model_name, const string &var_model_name, const int discount_id, const int growth_id);
|
||||
//! Adds a model local variable with its value
|
||||
void AddLocalVariable(int symb_id, expr_t value) throw (LocalVariableException);
|
||||
//! Adds an external function node
|
||||
expr_t AddExternalFunction(int symb_id, const vector<expr_t> &arguments);
|
||||
//! Adds an external function node for the first derivative of an external function
|
||||
expr_t AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index);
|
||||
//! Adds an external function node for the second derivative of an external function
|
||||
expr_t AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index1, int input_index2);
|
||||
//! Checks if a given symbol is used somewhere in the data tree
|
||||
bool isSymbolUsed(int symb_id) const;
|
||||
//! Checks if a given unary op is used somewhere in the data tree
|
||||
bool isUnaryOpUsed(UnaryOpcode opcode) const;
|
||||
//! Checks if a given binary op is used somewhere in the data tree
|
||||
bool isBinaryOpUsed(BinaryOpcode opcode) const;
|
||||
//! Checks if a given trinary op is used somewhere in the data tree
|
||||
bool isTrinaryOpUsed(TrinaryOpcode opcode) const;
|
||||
//! Checks if a given external function is used somewhere in the data tree
|
||||
bool isExternalFunctionUsed(int symb_id) const;
|
||||
//! Checks if a given first derivative external function is used somewhere in the data tree
|
||||
bool isFirstDerivExternalFunctionUsed(int symb_id) const;
|
||||
//! Checks if a given second derivative external function is used somewhere in the data tree
|
||||
bool isSecondDerivExternalFunctionUsed(int symb_id) const;
|
||||
//! Returns the minimum lag (as a negative number) of the given symbol in the whole data tree (and not only in the equations !!)
|
||||
/*! Returns 0 if the symbol is not used */
|
||||
int minLagForSymbol(int symb_id) const;
|
||||
//! Write the C Header for getPowerDeriv when use_dll is used
|
||||
void writePowerDerivCHeader(ostream &output) const;
|
||||
//! Write getPowerDeriv in C
|
||||
void writePowerDeriv(ostream &output) const;
|
||||
//! Write the C Header for normcdf when use_dll is used
|
||||
void writeNormcdfCHeader(ostream &output) const;
|
||||
//! Write normcdf in C
|
||||
void writeNormcdf(ostream &output) const;
|
||||
//! Thrown when trying to access an unknown variable by deriv_id
|
||||
class UnknownDerivIDException
|
||||
{
|
||||
};
|
||||
|
||||
//! Raised when a trend is declared twice
|
||||
class TrendException
|
||||
{
|
||||
public:
|
||||
string name;
|
||||
TrendException(const string &name_arg) : name(name_arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//! Returns the derivation ID, or throws an exception if the derivation ID does not exist
|
||||
virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException);
|
||||
virtual SymbolType getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException);
|
||||
virtual int getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException);
|
||||
virtual int getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException);
|
||||
//! Returns the column of the dynamic Jacobian associated to a derivation ID
|
||||
virtual int getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException);
|
||||
//! Adds to the set all the deriv IDs corresponding to parameters
|
||||
virtual void addAllParamDerivId(set<int> &deriv_id_set);
|
||||
|
||||
//! Returns bool indicating whether DataTree represents a Dynamic Model (returns true in DynamicModel.hh)
|
||||
virtual bool
|
||||
isDynamic() const
|
||||
{
|
||||
return false;
|
||||
};
|
||||
};
|
||||
|
||||
inline expr_t
|
||||
DataTree::AddPossiblyNegativeConstant(double v)
|
||||
{
|
||||
/* Treat NaN and Inf separately. In particular, under Windows, converting
|
||||
them to a string does not work as expected */
|
||||
if (isnan(v))
|
||||
return NaN;
|
||||
if (isinf(v))
|
||||
return (v < 0 ? MinusInfinity : Infinity);
|
||||
|
||||
bool neg = false;
|
||||
if (v < 0)
|
||||
{
|
||||
v = -v;
|
||||
neg = true;
|
||||
}
|
||||
ostringstream ost;
|
||||
ost << setprecision(CONSTANTS_PRECISION) << v;
|
||||
|
||||
expr_t cnode = AddNonNegativeConstant(ost.str());
|
||||
|
||||
if (neg)
|
||||
return AddUMinus(cnode);
|
||||
else
|
||||
return cnode;
|
||||
}
|
||||
|
||||
inline expr_t
|
||||
DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int param1_symb_id, int param2_symb_id, const string &adl_param_name, int adl_param_lag, const vector<int> &adl_lags)
|
||||
{
|
||||
// If the node already exists in tree, share it
|
||||
unary_op_node_map_t::iterator it = unary_op_node_map.find(make_pair(make_pair(arg, op_code), make_pair(make_pair(arg_exp_info_set, make_pair(param1_symb_id, param2_symb_id)), make_pair(adl_param_name, make_pair(adl_param_lag, adl_lags)))));
|
||||
if (it != unary_op_node_map.end())
|
||||
return it->second;
|
||||
|
||||
// Try to reduce to a constant
|
||||
// Case where arg is a constant and op_code == oUminus (i.e. we're adding a negative constant) is skipped
|
||||
NumConstNode *carg = dynamic_cast<NumConstNode *>(arg);
|
||||
if (op_code != oUminus || carg == NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
double argval = arg->eval(eval_context_t());
|
||||
double val = UnaryOpNode::eval_opcode(op_code, argval);
|
||||
return AddPossiblyNegativeConstant(val);
|
||||
}
|
||||
catch (ExprNode::EvalException &e)
|
||||
{
|
||||
}
|
||||
}
|
||||
return new UnaryOpNode(*this, op_code, arg, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_param_lag, adl_lags);
|
||||
}
|
||||
|
||||
inline expr_t
|
||||
DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder)
|
||||
{
|
||||
binary_op_node_map_t::iterator it = binary_op_node_map.find(make_pair(make_pair(make_pair(arg1, arg2), powerDerivOrder), op_code));
|
||||
if (it != binary_op_node_map.end())
|
||||
return it->second;
|
||||
|
||||
// Try to reduce to a constant
|
||||
try
|
||||
{
|
||||
double argval1 = arg1->eval(eval_context_t());
|
||||
double argval2 = arg2->eval(eval_context_t());
|
||||
double val = BinaryOpNode::eval_opcode(argval1, op_code, argval2, powerDerivOrder);
|
||||
return AddPossiblyNegativeConstant(val);
|
||||
}
|
||||
catch (ExprNode::EvalException &e)
|
||||
{
|
||||
}
|
||||
return new BinaryOpNode(*this, arg1, op_code, arg2, powerDerivOrder);
|
||||
}
|
||||
|
||||
inline expr_t
|
||||
DataTree::AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3)
|
||||
{
|
||||
trinary_op_node_map_t::iterator it = trinary_op_node_map.find(make_pair(make_pair(make_pair(arg1, arg2), arg3), op_code));
|
||||
if (it != trinary_op_node_map.end())
|
||||
return it->second;
|
||||
|
||||
// Try to reduce to a constant
|
||||
try
|
||||
{
|
||||
double argval1 = arg1->eval(eval_context_t());
|
||||
double argval2 = arg2->eval(eval_context_t());
|
||||
double argval3 = arg3->eval(eval_context_t());
|
||||
double val = TrinaryOpNode::eval_opcode(argval1, op_code, argval2, argval3);
|
||||
return AddPossiblyNegativeConstant(val);
|
||||
}
|
||||
catch (ExprNode::EvalException &e)
|
||||
{
|
||||
}
|
||||
return new TrinaryOpNode(*this, arg1, op_code, arg2, arg3);
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,623 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2018 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _DYNAMICMODEL_HH
|
||||
#define _DYNAMICMODEL_HH
|
||||
|
||||
using namespace std;
|
||||
#define ZERO_BAND 1e-8
|
||||
|
||||
#include <fstream>
|
||||
#include <boost/crc.hpp>
|
||||
|
||||
#include "StaticModel.hh"
|
||||
|
||||
//! Stores a dynamic model
|
||||
class DynamicModel : public ModelTree
|
||||
{
|
||||
private:
|
||||
//! Stores equations declared as [static]
|
||||
/*! They will be used in toStatic() to replace equations marked as [dynamic] */
|
||||
vector<BinaryOpNode *> static_only_equations;
|
||||
|
||||
//! Stores line numbers of equations declared as [static]
|
||||
vector<int> static_only_equations_lineno;
|
||||
|
||||
//! Stores the equation tags of equations declared as [static]
|
||||
vector<vector<pair<string, string> > > static_only_equations_equation_tags;
|
||||
|
||||
typedef map<pair<int, int>, int> deriv_id_table_t;
|
||||
//! Maps a pair (symbol_id, lag) to a deriv ID
|
||||
deriv_id_table_t deriv_id_table;
|
||||
//! Maps a deriv ID to a pair (symbol_id, lag)
|
||||
vector<pair<int, int> > inv_deriv_id_table;
|
||||
|
||||
//! Maps a deriv_id to the column index of the dynamic Jacobian
|
||||
/*! Contains only endogenous, exogenous and exogenous deterministic */
|
||||
map<int, int> dyn_jacobian_cols_table;
|
||||
|
||||
//! Maximum lag and lead over all types of variables (positive values)
|
||||
/*! Set by computeDerivIDs() */
|
||||
int max_lag, max_lead;
|
||||
//! Maximum lag and lead over endogenous variables (positive values)
|
||||
/*! Set by computeDerivIDs() */
|
||||
int max_endo_lag, max_endo_lead;
|
||||
//! Maximum lag and lead over exogenous variables (positive values)
|
||||
/*! Set by computeDerivIDs() */
|
||||
int max_exo_lag, max_exo_lead;
|
||||
//! Maximum lag and lead over deterministic exogenous variables (positive values)
|
||||
/*! Set by computeDerivIDs() */
|
||||
int max_exo_det_lag, max_exo_det_lead;
|
||||
//! Maximum lag and lead over all types of variables (positive values) of original model
|
||||
int max_lag_orig, max_lead_orig;
|
||||
//! Maximum lag and lead over endogenous variables (positive values) of original model
|
||||
int max_endo_lag_orig, max_endo_lead_orig;
|
||||
//! Maximum lag and lead over exogenous variables (positive values) of original model
|
||||
int max_exo_lag_orig, max_exo_lead_orig;
|
||||
//! Maximum lag and lead over deterministic exogenous variables (positive values) of original model
|
||||
int max_exo_det_lag_orig, max_exo_det_lead_orig;
|
||||
|
||||
//! Cross reference information
|
||||
map<int, ExprNode::EquationInfo> xrefs;
|
||||
map<pair<int, int>, set<int> > xref_param;
|
||||
map<pair<int, int>, set<int> > xref_endo;
|
||||
map<pair<int, int>, set<int> > xref_exo;
|
||||
map<pair<int, int>, set<int> > xref_exo_det;
|
||||
|
||||
//! Nonzero equations in the Hessian
|
||||
map<int, string> nonzero_hessian_eqs;
|
||||
|
||||
//! Number of columns of dynamic jacobian
|
||||
/*! Set by computeDerivID()s and computeDynJacobianCols() */
|
||||
int dynJacobianColsNbr;
|
||||
//! Temporary terms for block decomposed models
|
||||
vector< vector<temporary_terms_t> > v_temporary_terms;
|
||||
|
||||
vector<temporary_terms_inuse_t> v_temporary_terms_inuse;
|
||||
|
||||
//! Store the derivatives or the chainrule derivatives:map<pair< equation, pair< variable, lead_lag >, expr_t>
|
||||
typedef map< pair< int, pair< int, int> >, expr_t> first_chain_rule_derivatives_t;
|
||||
first_chain_rule_derivatives_t first_chain_rule_derivatives;
|
||||
|
||||
//! Writes dynamic model file (Matlab version)
|
||||
void writeDynamicMFile(const string &dynamic_basename) const;
|
||||
//! Writes dynamic model file (Julia version)
|
||||
void writeDynamicJuliaFile(const string &dynamic_basename) const;
|
||||
//! Write Var Expectation calls
|
||||
void writeVarExpectationCalls(ostream &output) const;
|
||||
//! Writes dynamic model file (C version)
|
||||
/*! \todo add third derivatives handling */
|
||||
void writeDynamicCFile(const string &dynamic_basename, const int order) const;
|
||||
//! Writes dynamic model file when SparseDLL option is on
|
||||
void writeSparseDynamicMFile(const string &dynamic_basename, const string &basename) const;
|
||||
//! Writes the dynamic model equations and its derivatives
|
||||
/*! \todo add third derivatives handling in C output */
|
||||
void writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia) const;
|
||||
//! Writes the Block reordred structure of the model in M output
|
||||
void writeModelEquationsOrdered_M(const string &dynamic_basename) const;
|
||||
//! Writes the code of the Block reordred structure of the model in virtual machine bytecode
|
||||
void writeModelEquationsCode_Block(string &file_name, const string &bin_basename, const map_idx_t &map_idx) const;
|
||||
//! Writes the code of the model in virtual machine bytecode
|
||||
void writeModelEquationsCode(string &file_name, const string &bin_basename, const map_idx_t &map_idx) const;
|
||||
|
||||
//! Computes jacobian and prepares for equation normalization
|
||||
/*! Using values from initval/endval blocks and parameter initializations:
|
||||
- computes the jacobian for the model w.r. to contemporaneous variables
|
||||
- removes edges of the incidence matrix when derivative w.r. to the corresponding variable is too close to zero (below the cutoff)
|
||||
*/
|
||||
//void evaluateJacobian(const eval_context_t &eval_context, jacob_map *j_m, bool dynamic);
|
||||
|
||||
//! return a map on the block jacobian
|
||||
map<pair<pair<int, pair<int, int> >, pair<int, int> >, int> get_Derivatives(int block);
|
||||
//! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables
|
||||
void computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives);
|
||||
|
||||
string reform(string name) const;
|
||||
map_idx_t map_idx;
|
||||
|
||||
//! sorts the temporary terms in the blocks order
|
||||
void computeTemporaryTermsOrdered();
|
||||
|
||||
//! creates a mapping from the index of temporary terms to a natural index
|
||||
void computeTemporaryTermsMapping();
|
||||
//! Write derivative code of an equation w.r. to a variable
|
||||
void compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, int lag, const map_idx_t &map_idx) const;
|
||||
//! Write chain rule derivative code of an equation w.r. to a variable
|
||||
void compileChainRuleDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int var, int lag, const map_idx_t &map_idx) const;
|
||||
|
||||
//! Get the type corresponding to a derivation ID
|
||||
virtual SymbolType getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException);
|
||||
//! Get the lag corresponding to a derivation ID
|
||||
virtual int getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException);
|
||||
//! Get the symbol ID corresponding to a derivation ID
|
||||
virtual int getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException);
|
||||
//! Compute the column indices of the dynamic Jacobian
|
||||
void computeDynJacobianCols(bool jacobianExo);
|
||||
//! Computes derivatives of the Jacobian w.r. to trend vars and tests that they are equal to zero
|
||||
void testTrendDerivativesEqualToZero(const eval_context_t &eval_context);
|
||||
//! Collect only the first derivatives
|
||||
map<pair<int, pair<int, int> >, expr_t> collect_first_order_derivatives_endogenous();
|
||||
|
||||
//! Allocates the derivation IDs for all dynamic variables of the model
|
||||
/*! Also computes max_{endo,exo}_{lead_lag}, and initializes dynJacobianColsNbr to the number of dynamic endos */
|
||||
void computeDerivIDs();
|
||||
|
||||
//! Write chain rule derivative of a recursive equation w.r. to a variable
|
||||
void writeChainRuleDerivative(ostream &output, int eq, int var, int lag, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const;
|
||||
|
||||
//! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous
|
||||
void collect_block_first_order_derivatives();
|
||||
|
||||
//! Collecte the informations about exogenous, deterministic exogenous and endogenous from the previous block for each block
|
||||
void collectBlockVariables();
|
||||
|
||||
//! Factorized code for substitutions of leads/lags
|
||||
/*! \param[in] type determines which type of variables is concerned
|
||||
\param[in] deterministic_model whether we are in a deterministic model (only for exogenous leads/lags)
|
||||
\param[in] subset variables to which to apply the transformation (only for diff of forward vars)
|
||||
*/
|
||||
void substituteLeadLagInternal(aux_var_t type, bool deterministic_model, const vector<string> &subset);
|
||||
|
||||
private:
|
||||
//! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true
|
||||
bool global_temporary_terms;
|
||||
|
||||
//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation
|
||||
equation_type_and_normalized_equation_t equation_type_and_normalized_equation;
|
||||
|
||||
//! for each block contains pair< Simulation_Type, pair < Block_Size, Recursive_part_Size > >
|
||||
block_type_firstequation_size_mfs_t block_type_firstequation_size_mfs;
|
||||
|
||||
//! for all blocks derivatives description
|
||||
blocks_derivatives_t blocks_derivatives;
|
||||
|
||||
//! The jacobian without the elements below the cutoff
|
||||
dynamic_jacob_map_t dynamic_jacobian;
|
||||
|
||||
//! Vector indicating if the block is linear in endogenous variable (true) or not (false)
|
||||
vector<bool> blocks_linear;
|
||||
|
||||
//! Map the derivatives for a block pair<lag, make_pair(make_pair(eq, var)), expr_t>
|
||||
typedef map<pair< int, pair<int, int> >, expr_t> derivative_t;
|
||||
//! Vector of derivative for each blocks
|
||||
vector<derivative_t> derivative_endo, derivative_other_endo, derivative_exo, derivative_exo_det;
|
||||
|
||||
//!List for each block and for each lag-lead all the other endogenous variables and exogenous variables
|
||||
typedef set<int> var_t;
|
||||
typedef map<int, var_t> lag_var_t;
|
||||
vector<lag_var_t> other_endo_block, exo_block, exo_det_block;
|
||||
|
||||
//!List for each block the exogenous variables
|
||||
vector<pair<var_t, int> > block_var_exo;
|
||||
|
||||
map< int, map<int, int> > block_exo_index, block_det_exo_index, block_other_endo_index;
|
||||
|
||||
//! for each block described the number of static, forward, backward and mixed variables in the block
|
||||
/*! pair< pair<static, forward>, pair<backward,mixed> > */
|
||||
vector<pair< pair<int, int>, pair<int, int> > > block_col_type;
|
||||
|
||||
//! Help computeXrefs to compute the reverse references (i.e. param->eqs, endo->eqs, etc)
|
||||
void computeRevXref(map<pair<int, int>, set<int> > &xrefset, const set<pair<int, int> > &eiref, int eqn);
|
||||
|
||||
//! Write reverse cross references
|
||||
void writeRevXrefs(ostream &output, const map<pair<int, int>, set<int> > &xrefmap, const string &type) const;
|
||||
|
||||
//! List for each variable its block number and its maximum lag and lead inside the block
|
||||
vector<pair<int, pair<int, int> > > variable_block_lead_lag;
|
||||
//! List for each equation its block number
|
||||
vector<int> equation_block;
|
||||
|
||||
//! Used for var_expectation and var_model
|
||||
map<string, set<int> > var_expectation_functions_to_write;
|
||||
|
||||
//! Used for pac_expectation operator
|
||||
set<const PacExpectationNode *> pac_expectation_info; // PacExpectationNode pointers
|
||||
|
||||
//!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous
|
||||
vector<pair<int, int> > endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
|
||||
|
||||
public:
|
||||
DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_argx);
|
||||
//! Adds a variable node
|
||||
/*! This implementation allows for non-zero lag */
|
||||
virtual VariableNode *AddVariable(int symb_id, int lag = 0);
|
||||
|
||||
//! Compute cross references
|
||||
void computeXrefs();
|
||||
|
||||
//! Write cross references
|
||||
void writeXrefs(ostream &output) const;
|
||||
|
||||
//! Execute computations (variable sorting + derivation)
|
||||
/*!
|
||||
\param jacobianExo whether derivatives w.r. to exo and exo_det should be in the Jacobian (derivatives w.r. to endo are always computed)
|
||||
\param hessian whether 2nd derivatives w.r. to exo, exo_det and endo should be computed (implies jacobianExo = true)
|
||||
\param thirdDerivatives whether 3rd derivatives w.r. to endo/exo/exo_det should be computed (implies jacobianExo = true)
|
||||
\param paramsDerivsOrder order of derivatives w.r. to a pair (endo/exo/exo_det, parameter) to be computed (>0 implies jacobianExo = true)
|
||||
\param eval_context evaluation context for normalization
|
||||
\param no_tmp_terms if true, no temporary terms will be computed in the dynamic files
|
||||
*/
|
||||
void computingPass(bool jacobianExo, bool hessian, bool thirdDerivatives, int paramsDerivsOrder,
|
||||
const eval_context_t &eval_context, bool no_tmp_terms, bool block, bool use_dll, bool bytecode, const bool nopreprocessoroutput);
|
||||
//! Writes model initialization and lead/lag incidence matrix to output
|
||||
void writeOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present, bool compute_xrefs, bool julia) const;
|
||||
|
||||
//! Write JSON Output
|
||||
void writeJsonOutput(ostream &output) const;
|
||||
|
||||
//! Write JSON Output representation of original dynamic model
|
||||
void writeJsonOriginalModelOutput(ostream &output) const;
|
||||
|
||||
//! Write JSON Output representation of model info (useful stuff from M_)
|
||||
void writeJsonDynamicModelInfo(ostream &output) const;
|
||||
|
||||
//! Write JSON Output representation of dynamic model after computing pass
|
||||
void writeJsonComputingPassOutput(ostream &output, bool writeDetails) const;
|
||||
|
||||
//! Write JSON prams derivatives file
|
||||
void writeJsonParamsDerivativesFile(ostream &output, bool writeDetails) const;
|
||||
|
||||
//! Write cross reference output if the xref maps have been filed
|
||||
void writeJsonXrefs(ostream &output) const;
|
||||
void writeJsonXrefsHelper(ostream &output, const map<pair<int, int>, set<int> > &xrefs) const;
|
||||
|
||||
//! Print equations that have non-zero second derivatives
|
||||
void printNonZeroHessianEquations(ostream &output) const;
|
||||
|
||||
//! Set the equations that have non-zero second derivatives
|
||||
void setNonZeroHessianEquations(map<int, string> &eqs);
|
||||
|
||||
//! Get equation info associated with equation tags from var_model
|
||||
void getVarModelVariablesFromEqTags(vector<string> &var_model_eqtags,
|
||||
vector<int> &eqnumber,
|
||||
vector<int> &lhs,
|
||||
vector<set<pair<int, int> > > &rhs,
|
||||
vector<bool> &nonstationary) const;
|
||||
|
||||
// Get equtaino information on diff operator
|
||||
void getDiffInfo(vector<int> &eqnumber, vector<bool> &diff, vector<int> &orig_diff_var) const;
|
||||
|
||||
//! Set indices for var expectation in dynamic model file
|
||||
void setVarExpectationIndices(map<string, pair<SymbolList, int> > &var_model_info);
|
||||
//! Add aux equations (and aux variables) for variables declared in var_model at max order if they don't already exist
|
||||
void addEquationsForVar(map<string, pair<SymbolList, int> > &var_model_info);
|
||||
//! Get Pac equation parameter info
|
||||
void walkPacParameters();
|
||||
//! Add var_model info to pac_expectation nodes
|
||||
void fillPacExpectationVarInfo(string &var_model_name,
|
||||
vector<int> &lhs,
|
||||
map<int, set<int > > &rhs,
|
||||
vector<bool> &nonstationary);
|
||||
//! Substitutes pac_expectation operator
|
||||
void substitutePacExpectation();
|
||||
|
||||
//! Adds informations for simulation in a binary file
|
||||
void Write_Inf_To_Bin_File_Block(const string &dynamic_basename, const string &bin_basename,
|
||||
const int &num, int &u_count_int, bool &file_open, bool is_two_boundaries) const;
|
||||
//! Writes dynamic model file
|
||||
void writeDynamicFile(const string &basename, bool block, bool bytecode, bool use_dll, int order, bool julia) const;
|
||||
//! Writes file containing parameters derivatives
|
||||
void writeParamsDerivativesFile(const string &basename, bool julia) const;
|
||||
|
||||
//! Converts to static model (only the equations)
|
||||
/*! It assumes that the static model given in argument has just been allocated */
|
||||
void toStatic(StaticModel &static_model) const;
|
||||
|
||||
//! Find endogenous variables not used in model
|
||||
set<int> findUnusedEndogenous();
|
||||
//! Find exogenous variables not used in model
|
||||
set<int> findUnusedExogenous();
|
||||
|
||||
//! Set the max leads/lags of the original model
|
||||
void setLeadsLagsOrig();
|
||||
|
||||
//! Copies a dynamic model (only the equations)
|
||||
/*! It assumes that the dynamic model given in argument has just been allocated */
|
||||
void cloneDynamic(DynamicModel &dynamic_model) const;
|
||||
|
||||
//! Replaces model equations with derivatives of Lagrangian w.r.t. endogenous
|
||||
void computeRamseyPolicyFOCs(const StaticModel &static_model, const bool nopreprocessoroutput);
|
||||
//! Replaces the model equations in dynamic_model with those in this model
|
||||
void replaceMyEquations(DynamicModel &dynamic_model) const;
|
||||
|
||||
//! Adds an equation marked as [static]
|
||||
void addStaticOnlyEquation(expr_t eq, int lineno, const vector<pair<string, string> > &eq_tags);
|
||||
|
||||
//! Returns number of static only equations
|
||||
size_t staticOnlyEquationsNbr() const;
|
||||
|
||||
//! Returns number of dynamic only equations
|
||||
size_t dynamicOnlyEquationsNbr() const;
|
||||
|
||||
//! Writes LaTeX file with the equations of the dynamic model
|
||||
void writeLatexFile(const string &basename, const bool write_equation_tags) const;
|
||||
|
||||
//! Writes LaTeX file with the equations of the dynamic model (for the original model)
|
||||
void writeLatexOriginalFile(const string &basename, const bool write_equation_tags) const;
|
||||
|
||||
virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException);
|
||||
virtual int getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException);
|
||||
virtual void addAllParamDerivId(set<int> &deriv_id_set);
|
||||
|
||||
//! Returns true indicating that this is a dynamic model
|
||||
virtual bool
|
||||
isDynamic() const
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
//! Drive test of detrended equations
|
||||
void runTrendTest(const eval_context_t &eval_context);
|
||||
|
||||
//! Transforms the model by removing all leads greater or equal than 2 on endos
|
||||
/*! Note that this can create new lags on endos and exos */
|
||||
void substituteEndoLeadGreaterThanTwo(bool deterministic_model);
|
||||
|
||||
//! Transforms the model by removing all lags greater or equal than 2 on endos
|
||||
void substituteEndoLagGreaterThanTwo(bool deterministic_model);
|
||||
|
||||
//! Transforms the model by removing all leads on exos
|
||||
/*! Note that this can create new lags on endos and exos */
|
||||
void substituteExoLead(bool deterministic_model);
|
||||
|
||||
//! Transforms the model by removing all lags on exos
|
||||
void substituteExoLag(bool deterministic_model);
|
||||
|
||||
//! Transforms the model by removing all oExpectation
|
||||
void substituteExpectation(bool partial_information_model);
|
||||
|
||||
//! Transforms the model by decreasing the lead/lag of predetermined variables in model equations by one
|
||||
void transformPredeterminedVariables();
|
||||
|
||||
//! Transforms the model by removing trends specified by the user
|
||||
void detrendEquations();
|
||||
|
||||
//! Substitutes adl operator
|
||||
void substituteAdl();
|
||||
|
||||
//! Substitutes diff operator
|
||||
void substituteDiff();
|
||||
|
||||
//! Fill var_expectation_functions_to_write
|
||||
void fillVarExpectationFunctionsToWrite();
|
||||
|
||||
//! Get var_expectation_functions_to_write
|
||||
map<string, set<int> > getVarExpectationFunctionsToWrite() const;
|
||||
|
||||
//! Transforms the model by replacing trend variables with a 1
|
||||
void removeTrendVariableFromEquations();
|
||||
|
||||
//! Transforms the model by creating aux vars for the diff of forward vars
|
||||
/*! If subset is empty, does the transformation for all fwrd vars; otherwise
|
||||
restrict it to the vars in subset */
|
||||
void differentiateForwardVars(const vector<string> &subset);
|
||||
|
||||
//! Fills eval context with values of model local variables and auxiliary variables
|
||||
void fillEvalContext(eval_context_t &eval_context) const;
|
||||
|
||||
//! Return the number of blocks
|
||||
virtual unsigned int
|
||||
getNbBlocks() const
|
||||
{
|
||||
return (block_type_firstequation_size_mfs.size());
|
||||
};
|
||||
//! Determine the simulation type of each block
|
||||
virtual BlockSimulationType
|
||||
getBlockSimulationType(int block_number) const
|
||||
{
|
||||
return (block_type_firstequation_size_mfs[block_number].first.first);
|
||||
};
|
||||
//! Return the first equation number of a block
|
||||
virtual unsigned int
|
||||
getBlockFirstEquation(int block_number) const
|
||||
{
|
||||
return (block_type_firstequation_size_mfs[block_number].first.second);
|
||||
};
|
||||
//! Return the size of the block block_number
|
||||
virtual unsigned int
|
||||
getBlockSize(int block_number) const
|
||||
{
|
||||
return (block_type_firstequation_size_mfs[block_number].second.first);
|
||||
};
|
||||
//! Return the number of exogenous variable in the block block_number
|
||||
virtual unsigned int
|
||||
getBlockExoSize(int block_number) const
|
||||
{
|
||||
return (block_var_exo[block_number].first.size());
|
||||
};
|
||||
//! Return the number of colums in the jacobian matrix for exogenous variable in the block block_number
|
||||
virtual unsigned int
|
||||
getBlockExoColSize(int block_number) const
|
||||
{
|
||||
return (block_var_exo[block_number].second);
|
||||
};
|
||||
//! Return the number of feedback variable of the block block_number
|
||||
virtual unsigned int
|
||||
getBlockMfs(int block_number) const
|
||||
{
|
||||
return (block_type_firstequation_size_mfs[block_number].second.second);
|
||||
};
|
||||
//! Return the maximum lag in a block
|
||||
virtual unsigned int
|
||||
getBlockMaxLag(int block_number) const
|
||||
{
|
||||
return (block_lag_lead[block_number].first);
|
||||
};
|
||||
//! Return the maximum lead in a block
|
||||
virtual unsigned int
|
||||
getBlockMaxLead(int block_number) const
|
||||
{
|
||||
return (block_lag_lead[block_number].second);
|
||||
};
|
||||
//! Return the type of equation (equation_number) belonging to the block block_number
|
||||
virtual EquationType
|
||||
getBlockEquationType(int block_number, int equation_number) const
|
||||
{
|
||||
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first);
|
||||
};
|
||||
//! Return true if the equation has been normalized
|
||||
virtual bool
|
||||
isBlockEquationRenormalized(int block_number, int equation_number) const
|
||||
{
|
||||
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first == E_EVALUATE_S);
|
||||
};
|
||||
//! Return the expr_t of the equation equation_number belonging to the block block_number
|
||||
virtual expr_t
|
||||
getBlockEquationExpr(int block_number, int equation_number) const
|
||||
{
|
||||
return (equations[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]]);
|
||||
};
|
||||
//! Return the expr_t of the renormalized equation equation_number belonging to the block block_number
|
||||
virtual expr_t
|
||||
getBlockEquationRenormalizedExpr(int block_number, int equation_number) const
|
||||
{
|
||||
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].second);
|
||||
};
|
||||
//! Return the original number of equation equation_number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockEquationID(int block_number, int equation_number) const
|
||||
{
|
||||
return (equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]);
|
||||
};
|
||||
//! Return the original number of variable variable_number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockVariableID(int block_number, int variable_number) const
|
||||
{
|
||||
return (variable_reordered[block_type_firstequation_size_mfs[block_number].first.second+variable_number]);
|
||||
};
|
||||
//! Return the original number of the exogenous variable varexo_number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockVariableExoID(int block_number, int variable_number) const
|
||||
{
|
||||
map<int, var_t>::const_iterator it = exo_block[block_number].find(variable_number);
|
||||
return (it->first);
|
||||
};
|
||||
//! Return the position of equation_number in the block number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockInitialEquationID(int block_number, int equation_number) const
|
||||
{
|
||||
return ((int) inv_equation_reordered[equation_number] - (int) block_type_firstequation_size_mfs[block_number].first.second);
|
||||
};
|
||||
//! Return the position of variable_number in the block number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockInitialVariableID(int block_number, int variable_number) const
|
||||
{
|
||||
return ((int) inv_variable_reordered[variable_number] - (int) block_type_firstequation_size_mfs[block_number].first.second);
|
||||
};
|
||||
//! Return the block number containing the endogenous variable variable_number
|
||||
int
|
||||
getBlockVariableID(int variable_number) const
|
||||
{
|
||||
return (variable_block_lead_lag[variable_number].first);
|
||||
};
|
||||
//! Return the position of the exogenous variable_number in the block number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockInitialExogenousID(int block_number, int variable_number) const
|
||||
{
|
||||
map< int, map<int, int> >::const_iterator it = block_exo_index.find(block_number);
|
||||
if (it != block_exo_index.end())
|
||||
{
|
||||
map<int, int>::const_iterator it1 = it->second.find(variable_number);
|
||||
if (it1 != it->second.end())
|
||||
return it1->second;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return (-1);
|
||||
};
|
||||
//! Return the position of the deterministic exogenous variable_number in the block number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockInitialDetExogenousID(int block_number, int variable_number) const
|
||||
{
|
||||
map< int, map<int, int> >::const_iterator it = block_det_exo_index.find(block_number);
|
||||
if (it != block_det_exo_index.end())
|
||||
{
|
||||
map<int, int>::const_iterator it1 = it->second.find(variable_number);
|
||||
if (it1 != it->second.end())
|
||||
return it1->second;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return (-1);
|
||||
};
|
||||
//! Return the position of the other endogenous variable_number in the block number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockInitialOtherEndogenousID(int block_number, int variable_number) const
|
||||
{
|
||||
map< int, map<int, int> >::const_iterator it = block_other_endo_index.find(block_number);
|
||||
if (it != block_other_endo_index.end())
|
||||
{
|
||||
map<int, int>::const_iterator it1 = it->second.find(variable_number);
|
||||
if (it1 != it->second.end())
|
||||
return it1->second;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return (-1);
|
||||
};
|
||||
bool isModelLocalVariableUsed() const;
|
||||
|
||||
//! Returns true if a parameter was used in the model block with a lead or lag
|
||||
bool ParamUsedWithLeadLag() const;
|
||||
|
||||
//! Writes model initialization and lead/lag incidence matrix to C output
|
||||
void writeCOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present) const;
|
||||
//! Writes model initialization and lead/lag incidence matrix to Cpp output
|
||||
void writeCCOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present) const;
|
||||
//! Writes C file containing residuals
|
||||
void writeResidualsC(const string &basename, bool cuda) const;
|
||||
//! Writes C file containing first order derivatives of model evaluated at steady state
|
||||
void writeFirstDerivativesC(const string &basename, bool cuda) const;
|
||||
//! Writes C file containing first order derivatives of model evaluated at steady state (conpressed sparse column)
|
||||
void writeFirstDerivativesC_csr(const string &basename, bool cuda) const;
|
||||
//! Writes C file containing second order derivatives of model evaluated at steady state (compressed sparse column)
|
||||
void writeSecondDerivativesC_csr(const string &basename, bool cuda) const;
|
||||
//! Writes C file containing third order derivatives of model evaluated at steady state (compressed sparse column)
|
||||
void writeThirdDerivativesC_csr(const string &basename, bool cuda) const;
|
||||
|
||||
bool isChecksumMatching(const string &basename) const;
|
||||
};
|
||||
|
||||
//! Classes to re-order derivatives for various sparse storage formats
|
||||
class derivative
|
||||
{
|
||||
public:
|
||||
long unsigned int linear_address;
|
||||
long unsigned int col_nbr;
|
||||
unsigned int row_nbr;
|
||||
expr_t value;
|
||||
derivative(long unsigned int arg1, long unsigned int arg2, int arg3, expr_t arg4) :
|
||||
linear_address(arg1), col_nbr(arg2), row_nbr(arg3), value(arg4)
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
class derivative_less_than
|
||||
{
|
||||
public:
|
||||
bool
|
||||
operator()(const derivative &d1, const derivative &d2) const
|
||||
{
|
||||
return d1.linear_address < d2.linear_address;
|
||||
}
|
||||
};
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,413 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#ifndef PACKAGE_VERSION
|
||||
# define PACKAGE_VERSION 4.
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include "ParsingDriver.hh"
|
||||
#include "ExtendedPreprocessorTypes.hh"
|
||||
#include "ConfigFile.hh"
|
||||
|
||||
/* Prototype for second part of main function
|
||||
Splitting main() in two parts was necessary because ParsingDriver.h and MacroDriver.h can't be
|
||||
included simultaneously (because of Bison limitations).
|
||||
*/
|
||||
void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear_global,
|
||||
bool no_tmp_terms, bool no_log, bool no_warn, bool warn_uninit, bool console,
|
||||
bool nograph, bool nointeractive, bool parallel, ConfigFile &config_file,
|
||||
WarningConsolidation &warnings_arg, bool nostrict, bool stochastic, bool check_model_changes,
|
||||
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
|
||||
LanguageOutputType lang, int params_derivs_order
|
||||
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
|
||||
, bool cygwin, bool msvc, bool mingw
|
||||
#endif
|
||||
, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple
|
||||
, bool nopreprocessoroutput
|
||||
);
|
||||
|
||||
void main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool save_macro, string &save_macro_file,
|
||||
bool no_line_macro, bool no_empty_line_macro, map<string, string> &defines, vector<string> &path, stringstream ¯o_output);
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [noemptylinemacro] [notmpterms] [nolog] [warn_uninit]"
|
||||
<< " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]"
|
||||
<< " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] [compute_xrefs] [output=dynamic|first|second|third] [language=C|C++|julia]"
|
||||
<< " [params_derivs_order=0|1|2]"
|
||||
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
|
||||
<< " [cygwin] [msvc] [mingw]"
|
||||
#endif
|
||||
<< " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] [nopathchange] [nopreprocessoroutput]"
|
||||
<< endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
/*
|
||||
Redirect stderr to stdout.
|
||||
Made necessary because MATLAB/Octave can only capture stdout (but not
|
||||
stderr), in order to put it in the logfile (see issue #306)
|
||||
*/
|
||||
dup2(STDOUT_FILENO, STDERR_FILENO);
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
cerr << "Missing model file!" << endl;
|
||||
usage();
|
||||
}
|
||||
|
||||
bool clear_all = true;
|
||||
bool clear_global = false;
|
||||
bool save_macro = false;
|
||||
string save_macro_file;
|
||||
bool debug = false;
|
||||
bool no_tmp_terms = false;
|
||||
bool only_macro = false;
|
||||
bool no_line_macro = false;
|
||||
bool no_empty_line_macro = false;
|
||||
bool no_log = false;
|
||||
bool no_warn = false;
|
||||
int params_derivs_order = 2;
|
||||
bool warn_uninit = false;
|
||||
bool console = false;
|
||||
bool nograph = false;
|
||||
bool nointeractive = false;
|
||||
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
|
||||
bool cygwin = false;
|
||||
bool msvc = false;
|
||||
bool mingw = false;
|
||||
#endif
|
||||
string parallel_config_file;
|
||||
bool parallel = false;
|
||||
string cluster_name;
|
||||
bool parallel_slave_open_mode = false;
|
||||
bool parallel_test = false;
|
||||
bool nostrict = false;
|
||||
bool stochastic = false;
|
||||
bool check_model_changes = false;
|
||||
bool minimal_workspace = false;
|
||||
bool compute_xrefs = false;
|
||||
map<string, string> defines;
|
||||
vector<string> path;
|
||||
FileOutputType output_mode = none;
|
||||
JsonOutputPointType json = nojson;
|
||||
JsonFileOutputType json_output_mode = file;
|
||||
bool onlyjson = false;
|
||||
bool jsonderivsimple = false;
|
||||
LanguageOutputType language = matlab;
|
||||
bool nopreprocessoroutput = false;
|
||||
|
||||
// Parse options
|
||||
for (int arg = 2; arg < argc; arg++)
|
||||
{
|
||||
if (!strcmp(argv[arg], "debug"))
|
||||
debug = true;
|
||||
else if (!strcmp(argv[arg], "noclearall"))
|
||||
clear_all = false;
|
||||
else if (strlen(argv[arg]) >= 19 && !strncmp(argv[arg], "params_derivs_order", 19))
|
||||
{
|
||||
if (strlen(argv[arg]) >= 22 || argv[arg][19] != '='
|
||||
|| !(argv[arg][20] == '0' || argv[arg][20] == '1' || argv[arg][20] == '2'))
|
||||
{
|
||||
cerr << "Incorrect syntax for params_derivs_order option" << endl;
|
||||
usage();
|
||||
}
|
||||
params_derivs_order = atoi(argv[arg] + 20);
|
||||
}
|
||||
else if (!strcmp(argv[arg], "onlyclearglobals"))
|
||||
{
|
||||
clear_all = false;
|
||||
clear_global = true;
|
||||
}
|
||||
else if (!strcmp(argv[arg], "onlymacro"))
|
||||
only_macro = true;
|
||||
else if (strlen(argv[arg]) >= 9 && !strncmp(argv[arg], "savemacro", 9))
|
||||
{
|
||||
save_macro = true;
|
||||
if (strlen(argv[arg]) > 9)
|
||||
{
|
||||
if (strlen(argv[arg]) == 10 || argv[arg][9] != '=')
|
||||
{
|
||||
cerr << "Incorrect syntax for savemacro option" << endl;
|
||||
usage();
|
||||
}
|
||||
save_macro_file = string(argv[arg] + 10);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[arg], "nolinemacro"))
|
||||
no_line_macro = true;
|
||||
else if (!strcmp(argv[arg], "noemptylinemacro"))
|
||||
no_empty_line_macro = true;
|
||||
else if (!strcmp(argv[arg], "notmpterms"))
|
||||
no_tmp_terms = true;
|
||||
else if (!strcmp(argv[arg], "nolog"))
|
||||
no_log = true;
|
||||
else if (!strcmp(argv[arg], "nowarn"))
|
||||
no_warn = true;
|
||||
else if (!strcmp(argv[arg], "warn_uninit"))
|
||||
warn_uninit = true;
|
||||
else if (!strcmp(argv[arg], "console"))
|
||||
console = true;
|
||||
else if (!strcmp(argv[arg], "nograph"))
|
||||
nograph = true;
|
||||
else if (!strcmp(argv[arg], "nointeractive"))
|
||||
nointeractive = true;
|
||||
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
|
||||
else if (!strcmp(argv[arg], "cygwin"))
|
||||
cygwin = true;
|
||||
else if (!strcmp(argv[arg], "msvc"))
|
||||
msvc = true;
|
||||
else if (!strcmp(argv[arg], "mingw"))
|
||||
mingw = true;
|
||||
#endif
|
||||
else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "conffile", 8))
|
||||
{
|
||||
if (strlen(argv[arg]) <= 9 || argv[arg][8] != '=')
|
||||
{
|
||||
cerr << "Incorrect syntax for conffile option" << endl;
|
||||
usage();
|
||||
}
|
||||
parallel_config_file = string(argv[arg] + 9);
|
||||
}
|
||||
else if (!strcmp(argv[arg], "parallel_slave_open_mode"))
|
||||
parallel_slave_open_mode = true;
|
||||
else if (!strcmp(argv[arg], "parallel_test"))
|
||||
parallel_test = true;
|
||||
else if (!strcmp(argv[arg], "nostrict"))
|
||||
nostrict = true;
|
||||
else if (!strcmp(argv[arg], "stochastic"))
|
||||
stochastic = true;
|
||||
else if (!strcmp(argv[arg], "fast"))
|
||||
check_model_changes = true;
|
||||
else if (!strcmp(argv[arg], "minimal_workspace"))
|
||||
minimal_workspace = true;
|
||||
else if (!strcmp(argv[arg], "compute_xrefs"))
|
||||
compute_xrefs = true;
|
||||
else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "parallel", 8))
|
||||
{
|
||||
parallel = true;
|
||||
if (strlen(argv[arg]) > 8)
|
||||
{
|
||||
if (strlen(argv[arg]) == 9 || argv[arg][8] != '=')
|
||||
{
|
||||
cerr << "Incorrect syntax for parallel option" << endl;
|
||||
usage();
|
||||
}
|
||||
cluster_name = string(argv[arg] + 9);
|
||||
}
|
||||
}
|
||||
else if (strlen(argv[arg]) >= 2 && !strncmp(argv[arg], "-D", 2))
|
||||
{
|
||||
if (strlen(argv[arg]) == 2)
|
||||
{
|
||||
cerr << "Incorrect syntax for command line define: the defined variable "
|
||||
<< "must not be separated from -D by whitespace." << endl;
|
||||
usage();
|
||||
}
|
||||
|
||||
size_t equal_index = string(argv[arg]).find('=');
|
||||
if (equal_index != string::npos)
|
||||
{
|
||||
string key = string(argv[arg]).erase(equal_index).erase(0, 2);
|
||||
defines[key] = string(argv[arg]).erase(0, equal_index+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
string key = string(argv[arg]).erase(0, 2);
|
||||
defines[key] = "1";
|
||||
}
|
||||
}
|
||||
else if (strlen(argv[arg]) >= 2 && !strncmp(argv[arg], "-I", 2))
|
||||
{
|
||||
if (strlen(argv[arg]) == 2)
|
||||
{
|
||||
cerr << "Incorrect syntax for command line define: the defined variable "
|
||||
<< "must not be separated from -I by whitespace." << endl;
|
||||
usage();
|
||||
}
|
||||
path.push_back(string(argv[arg]).erase(0, 2));
|
||||
}
|
||||
else if (strlen(argv[arg]) >= 6 && !strncmp(argv[arg], "output", 6))
|
||||
{
|
||||
if (strlen(argv[arg]) <= 7 || argv[arg][6] != '=')
|
||||
{
|
||||
cerr << "Incorrect syntax for output option" << endl;
|
||||
usage();
|
||||
}
|
||||
if (strlen(argv[arg]) == 14 && !strncmp(argv[arg] + 7, "dynamic", 7))
|
||||
output_mode = dynamic;
|
||||
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 7, "first", 5))
|
||||
output_mode = first;
|
||||
else if (strlen(argv[arg]) == 13 && !strncmp(argv[arg] + 7, "second", 6))
|
||||
output_mode = second;
|
||||
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 7, "third", 5))
|
||||
output_mode = third;
|
||||
else
|
||||
{
|
||||
cerr << "Incorrect syntax for output option" << endl;
|
||||
usage();
|
||||
}
|
||||
}
|
||||
else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "language", 8))
|
||||
{
|
||||
if (strlen(argv[arg]) <= 9 || argv[arg][8] != '=')
|
||||
{
|
||||
cerr << "Incorrect syntax for language option" << endl;
|
||||
usage();
|
||||
}
|
||||
|
||||
if (strlen(argv[arg]) == 14 && !strncmp(argv[arg] + 9, "julia", 5))
|
||||
language = julia;
|
||||
else
|
||||
{
|
||||
// we don't want temp terms in external functions (except Julia)
|
||||
no_tmp_terms = true;
|
||||
if (strlen(argv[arg]) == 10 && !strncmp(argv[arg] + 9, "C", 1))
|
||||
language = c;
|
||||
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 9, "C++", 3))
|
||||
language = cpp;
|
||||
else if (strlen(argv[arg]) == 13 && !strncmp(argv[arg] + 9, "cuda", 4))
|
||||
language = cuda;
|
||||
else if (strlen(argv[arg]) == 15 && !strncmp(argv[arg] + 9, "python", 6))
|
||||
language = python;
|
||||
else
|
||||
{
|
||||
cerr << "Incorrect syntax for language option" << endl;
|
||||
usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[arg], "jsonstdout"))
|
||||
json_output_mode = standardout;
|
||||
else if (!strcmp(argv[arg], "onlyjson"))
|
||||
onlyjson = true;
|
||||
else if (!strcmp(argv[arg], "nopreprocessoroutput"))
|
||||
nopreprocessoroutput = true;
|
||||
else if (!strcmp(argv[arg], "jsonderivsimple"))
|
||||
jsonderivsimple = true;
|
||||
else if (strlen(argv[arg]) >= 4 && !strncmp(argv[arg], "json", 4))
|
||||
{
|
||||
if (strlen(argv[arg]) <= 5 || argv[arg][4] != '=')
|
||||
{
|
||||
cerr << "Incorrect syntax for json option" << endl;
|
||||
usage();
|
||||
}
|
||||
if (strlen(argv[arg]) == 10 && !strncmp(argv[arg] + 5, "parse", 5))
|
||||
json = parsing;
|
||||
else if (strlen(argv[arg]) == 10 && !strncmp(argv[arg] + 5, "check", 5))
|
||||
json = checkpass;
|
||||
else if (strlen(argv[arg]) == 14 && !strncmp(argv[arg] + 5, "transform", 9))
|
||||
json = transformpass;
|
||||
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 5, "compute", 7))
|
||||
json = computingpass;
|
||||
else
|
||||
{
|
||||
cerr << "Incorrect syntax for json option" << endl;
|
||||
usage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Unknown option: " << argv[arg] << endl;
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (!nopreprocessoroutput)
|
||||
cout << "Starting Dynare (version " << PACKAGE_VERSION << ")." << endl
|
||||
<< "Starting preprocessing of the model file ..." << endl;
|
||||
|
||||
// Construct basename (i.e. remove file extension if there is one)
|
||||
string basename = argv[1];
|
||||
string modfile, modfiletxt;
|
||||
size_t fsc = basename.find_first_of(';');
|
||||
if (fsc != string::npos)
|
||||
{
|
||||
// If a semicolon is found in argv[1], treat it as the text of the modfile
|
||||
modfile = "mod_file_passed_as_string.mod";
|
||||
basename = "mod_file_passed_as_string";
|
||||
modfiletxt = argv[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// If a semicolon is NOT found in argv[1], treat it as the name of the modfile
|
||||
modfile = argv[1];
|
||||
size_t pos = basename.find_last_of('.');
|
||||
if (pos != string::npos)
|
||||
basename.erase(pos);
|
||||
|
||||
ifstream modfile(argv[1], ios::binary);
|
||||
if (modfile.fail())
|
||||
{
|
||||
cerr << "ERROR: Could not open file: " << argv[1] << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
stringstream buffer;
|
||||
buffer << modfile.rdbuf();
|
||||
modfiletxt = buffer.str();
|
||||
}
|
||||
|
||||
WarningConsolidation warnings(no_warn);
|
||||
|
||||
// Process config file
|
||||
ConfigFile config_file(parallel, parallel_test, parallel_slave_open_mode, cluster_name);
|
||||
config_file.getConfigFileInfo(parallel_config_file);
|
||||
config_file.checkPass(warnings);
|
||||
config_file.transformPass();
|
||||
|
||||
// If Include option was passed to the [paths] block of the config file, add
|
||||
// it to paths before macroprocessing
|
||||
vector<string> config_include_paths = config_file.getIncludePaths();
|
||||
for (vector<string>::const_iterator it = config_include_paths.begin();
|
||||
it != config_include_paths.end(); it++)
|
||||
path.push_back(*it);
|
||||
|
||||
// Do macro processing
|
||||
stringstream macro_output;
|
||||
main1(modfile, basename, modfiletxt, debug, save_macro, save_macro_file, no_line_macro, no_empty_line_macro,
|
||||
defines, path, macro_output);
|
||||
|
||||
if (only_macro)
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
// Do the rest
|
||||
main2(macro_output, basename, debug, clear_all, clear_global,
|
||||
no_tmp_terms, no_log, no_warn, warn_uninit, console, nograph, nointeractive,
|
||||
parallel, config_file, warnings, nostrict, stochastic, check_model_changes, minimal_workspace,
|
||||
compute_xrefs, output_mode, language, params_derivs_order
|
||||
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
|
||||
, cygwin, msvc, mingw
|
||||
#endif
|
||||
, json, json_output_mode, onlyjson, jsonderivsimple, nopreprocessoroutput
|
||||
);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
#include "macro/MacroDriver.hh"
|
||||
|
||||
bool compareNewline (int i, int j) {
|
||||
return i == '\n' && j == '\n';
|
||||
}
|
||||
|
||||
void
|
||||
main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool save_macro, string &save_macro_file,
|
||||
bool no_line_macro, bool no_empty_line_macro, map<string, string> &defines, vector<string> &path, stringstream ¯o_output)
|
||||
{
|
||||
// Do macro processing
|
||||
MacroDriver m;
|
||||
|
||||
m.parse(modfile, basename, modfiletxt, macro_output, debug, no_line_macro, defines, path);
|
||||
if (save_macro)
|
||||
{
|
||||
if (save_macro_file.empty())
|
||||
save_macro_file = basename + "-macroexp.mod";
|
||||
ofstream macro_output_file(save_macro_file.c_str());
|
||||
if (macro_output_file.fail())
|
||||
{
|
||||
cerr << "Cannot open " << save_macro_file << " for macro output" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
string str (macro_output.str());
|
||||
if (no_empty_line_macro)
|
||||
str.erase(unique(str.begin(), str.end(), compareNewline), str.end());
|
||||
macro_output_file << str;
|
||||
macro_output_file.close();
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "ParsingDriver.hh"
|
||||
#include "ModFile.hh"
|
||||
#include "ConfigFile.hh"
|
||||
#include "ExtendedPreprocessorTypes.hh"
|
||||
|
||||
void
|
||||
main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear_global,
|
||||
bool no_tmp_terms, bool no_log, bool no_warn, bool warn_uninit, bool console,
|
||||
bool nograph, bool nointeractive, bool parallel, ConfigFile &config_file,
|
||||
WarningConsolidation &warnings, bool nostrict, bool stochastic, bool check_model_changes,
|
||||
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
|
||||
LanguageOutputType language, int params_derivs_order
|
||||
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
|
||||
, bool cygwin, bool msvc, bool mingw
|
||||
#endif
|
||||
, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple
|
||||
, bool nopreprocessoroutput
|
||||
)
|
||||
{
|
||||
ParsingDriver p(warnings, nostrict);
|
||||
|
||||
// Do parsing and construct internal representation of mod file
|
||||
ModFile *mod_file = p.parse(in, debug);
|
||||
if (json == parsing)
|
||||
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, nopreprocessoroutput);
|
||||
|
||||
// Run checking pass
|
||||
mod_file->checkPass(nostrict, stochastic);
|
||||
if (json == checkpass)
|
||||
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, nopreprocessoroutput);
|
||||
|
||||
// Perform transformations on the model (creation of auxiliary vars and equations)
|
||||
mod_file->transformPass(nostrict, stochastic, compute_xrefs || json == transformpass, nopreprocessoroutput);
|
||||
if (json == transformpass)
|
||||
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, nopreprocessoroutput);
|
||||
|
||||
// Evaluate parameters initialization, initval, endval and pounds
|
||||
mod_file->evalAllExpressions(warn_uninit, nopreprocessoroutput);
|
||||
|
||||
// Do computations
|
||||
mod_file->computingPass(no_tmp_terms, output_mode, params_derivs_order, nopreprocessoroutput);
|
||||
if (json == computingpass)
|
||||
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, nopreprocessoroutput, jsonderivsimple);
|
||||
|
||||
// Write outputs
|
||||
if (output_mode != none)
|
||||
mod_file->writeExternalFiles(basename, output_mode, language, nopreprocessoroutput);
|
||||
else
|
||||
mod_file->writeOutputFiles(basename, clear_all, clear_global, no_log, no_warn, console, nograph,
|
||||
nointeractive, config_file, check_model_changes, minimal_workspace, compute_xrefs
|
||||
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
|
||||
, cygwin, msvc, mingw
|
||||
#endif
|
||||
, nopreprocessoroutput
|
||||
);
|
||||
|
||||
delete mod_file;
|
||||
|
||||
if (!nopreprocessoroutput)
|
||||
cout << "Preprocessing completed." << endl;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _EXTENDED_PREPROCESSOR_TYPES_HH
|
||||
#define _EXTENDED_PREPROCESSOR_TYPES_HH
|
||||
|
||||
enum FileOutputType
|
||||
{
|
||||
none, // outputs files for Matlab/Octave processing
|
||||
dynamic, // outputs <fname>_dynamic.* and related files
|
||||
first, // outputs <fname>_first_derivatives.* and related files
|
||||
second, // outputs <fname>_first_derivatives.*, <fname>_second_derivatives.* and related files
|
||||
third, // outputs <fname>_first_derivatives.*, <fname>_second_derivatives.*, <fname>_third_derivatives.* and related files
|
||||
};
|
||||
|
||||
enum LanguageOutputType
|
||||
{
|
||||
matlab, // outputs files for Matlab/Octave processing
|
||||
c, // outputs files for C
|
||||
cpp, // outputs files for C++
|
||||
cuda, // outputs files for CUDA (not yet implemented)
|
||||
julia, // outputs files for Julia
|
||||
python, // outputs files for Python (not yet implemented) (not yet implemented)
|
||||
};
|
||||
|
||||
enum JsonFileOutputType
|
||||
{
|
||||
file, // output JSON files to file
|
||||
standardout, // output JSON files to stdout
|
||||
};
|
||||
|
||||
enum JsonOutputPointType
|
||||
{
|
||||
nojson, // don't output JSON
|
||||
parsing, // output JSON after the parsing step
|
||||
checkpass, // output JSON after the check pass
|
||||
transformpass, // output JSON after the transform pass
|
||||
computingpass // output JSON after the computing pass
|
||||
};
|
||||
#endif
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2015 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "ExternalFunctionsTable.hh"
|
||||
#include "SymbolTable.hh"
|
||||
|
||||
ExternalFunctionsTable::ExternalFunctionsTable()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function_options &external_function_options_arg, bool track_nargs)
|
||||
{
|
||||
assert(symb_id >= 0);
|
||||
assert(external_function_options_arg.nargs > 0);
|
||||
|
||||
// Change options to be saved so the table is consistent
|
||||
external_function_options external_function_options_chng = external_function_options_arg;
|
||||
if (external_function_options_arg.firstDerivSymbID == eExtFunSetButNoNameProvided)
|
||||
external_function_options_chng.firstDerivSymbID = symb_id;
|
||||
|
||||
if (external_function_options_arg.secondDerivSymbID == eExtFunSetButNoNameProvided)
|
||||
external_function_options_chng.secondDerivSymbID = symb_id;
|
||||
|
||||
if (!track_nargs)
|
||||
external_function_options_chng.nargs = eExtFunNotSet;
|
||||
|
||||
// Ensure 1st & 2nd deriv option consistency
|
||||
if (external_function_options_chng.secondDerivSymbID == symb_id
|
||||
&& external_function_options_chng.firstDerivSymbID != symb_id)
|
||||
{
|
||||
cerr << "ERROR: If the second derivative is provided by the top-level function "
|
||||
<< "the first derivative must also be provided by the same function." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((external_function_options_chng.secondDerivSymbID != symb_id
|
||||
&& external_function_options_chng.firstDerivSymbID == symb_id)
|
||||
&& external_function_options_chng.secondDerivSymbID != eExtFunNotSet)
|
||||
{
|
||||
cerr << "ERROR: If the first derivative is provided by the top-level function, the "
|
||||
<< "second derivative cannot be provided by any other external function." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (external_function_options_chng.secondDerivSymbID != eExtFunNotSet
|
||||
&& external_function_options_chng.firstDerivSymbID == eExtFunNotSet)
|
||||
{
|
||||
cerr << "ERROR: If the second derivative is provided, the first derivative must also be provided." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (external_function_options_chng.secondDerivSymbID == external_function_options_chng.firstDerivSymbID
|
||||
&& external_function_options_chng.firstDerivSymbID != symb_id
|
||||
&& external_function_options_chng.firstDerivSymbID != eExtFunNotSet)
|
||||
{
|
||||
cerr << "ERROR: If the Jacobian and Hessian are provided by the same function, that "
|
||||
<< "function must be the top-level function." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Ensure that if we're overwriting something, we mean to do it
|
||||
if (exists(symb_id))
|
||||
{
|
||||
bool ok_to_overwrite = false;
|
||||
if (getNargs(symb_id) == eExtFunNotSet) // implies that the information stored about this function is not important
|
||||
ok_to_overwrite = true;
|
||||
|
||||
if (!ok_to_overwrite) // prevents multiple non-compatible calls to external_function(name=funcname)
|
||||
{ // e.g. e_f(name=a,nargs=1,fd,sd) and e_f(name=a,nargs=2,fd=b,sd=c) should cause an error
|
||||
if (external_function_options_chng.nargs != getNargs(symb_id))
|
||||
{
|
||||
cerr << "ERROR: The number of arguments passed to the external_function() statement do not "
|
||||
<< "match the number of arguments passed to a previous call or declaration of the top-level function."<< endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (external_function_options_chng.firstDerivSymbID != getFirstDerivSymbID(symb_id))
|
||||
{
|
||||
cerr << "ERROR: The first derivative function passed to the external_function() statement does not "
|
||||
<< "match the first derivative function passed to a previous call or declaration of the top-level function."<< endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (external_function_options_chng.secondDerivSymbID != getSecondDerivSymbID(symb_id))
|
||||
{
|
||||
cerr << "ERROR: The second derivative function passed to the external_function() statement does not "
|
||||
<< "match the second derivative function passed to a previous call or declaration of the top-level function."<< endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
externalFunctionTable[symb_id] = external_function_options_chng;
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2015 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _EXTERNALFUNCTIONSTABLE_HH
|
||||
#define _EXTERNALFUNCTIONSTABLE_HH
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
enum ExternalFunctionSetOrNot
|
||||
{
|
||||
eExtFunSetButNoNameProvided = -2, //! Signifies that the derivative is obtained from the top-level function
|
||||
eExtFunNotSet = -1, //! Signifies that no external function exists that calculates the derivative
|
||||
eExtFunSetDefaultNargs = 1 //! This is the default number of arguments when nargs is not specified
|
||||
};
|
||||
|
||||
//! Handles external functions
|
||||
class ExternalFunctionsTable
|
||||
{
|
||||
public:
|
||||
//! Thrown when trying to access an unknown symbol (by id)
|
||||
class UnknownExternalFunctionSymbolIDException
|
||||
{
|
||||
public:
|
||||
//! Symbol ID
|
||||
int id;
|
||||
UnknownExternalFunctionSymbolIDException(int id_arg) : id(id_arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/* For all arguments, -2 means not set
|
||||
* For firstDerivSymbID and secondDerivSymbID, -1 means that the derivatives are
|
||||
* provided in the main function given in the by the "name" option to the
|
||||
* external_function() statement.
|
||||
*/
|
||||
struct external_function_options
|
||||
{
|
||||
int nargs, firstDerivSymbID, secondDerivSymbID;
|
||||
};
|
||||
typedef map<int, external_function_options> external_function_table_type;
|
||||
private:
|
||||
//! Map containing options provided to external_functions()
|
||||
external_function_table_type externalFunctionTable;
|
||||
public:
|
||||
ExternalFunctionsTable();
|
||||
//! Adds an external function to the table as well as its derivative functions
|
||||
void addExternalFunction(int symb_id, const external_function_options &external_function_options_arg, bool track_nargs);
|
||||
//! See if the function exists in the External Functions Table
|
||||
inline bool exists(int symb_id) const;
|
||||
//! Get the number of arguments for a given external function
|
||||
inline int getNargs(int symb_id) const throw (UnknownExternalFunctionSymbolIDException);
|
||||
//! Get the symbol_id of the first derivative function
|
||||
inline int getFirstDerivSymbID(int symb_id) const throw (UnknownExternalFunctionSymbolIDException);
|
||||
//! Get the symbol_id of the second derivative function
|
||||
inline int getSecondDerivSymbID(int symb_id) const throw (UnknownExternalFunctionSymbolIDException);
|
||||
//! Returns the total number of unique external functions declared or used in the .mod file
|
||||
inline int get_total_number_of_unique_model_block_external_functions() const;
|
||||
};
|
||||
|
||||
inline bool
|
||||
ExternalFunctionsTable::exists(int symb_id) const
|
||||
{
|
||||
external_function_table_type::const_iterator iter = externalFunctionTable.find(symb_id);
|
||||
return (iter != externalFunctionTable.end());
|
||||
}
|
||||
|
||||
inline int
|
||||
ExternalFunctionsTable::getNargs(int symb_id) const throw (UnknownExternalFunctionSymbolIDException)
|
||||
{
|
||||
if (exists(symb_id))
|
||||
return externalFunctionTable.find(symb_id)->second.nargs;
|
||||
else
|
||||
throw UnknownExternalFunctionSymbolIDException(symb_id);
|
||||
}
|
||||
|
||||
inline int
|
||||
ExternalFunctionsTable::getFirstDerivSymbID(int symb_id) const throw (UnknownExternalFunctionSymbolIDException)
|
||||
{
|
||||
if (exists(symb_id))
|
||||
return externalFunctionTable.find(symb_id)->second.firstDerivSymbID;
|
||||
else
|
||||
throw UnknownExternalFunctionSymbolIDException(symb_id);
|
||||
}
|
||||
|
||||
inline int
|
||||
ExternalFunctionsTable::getSecondDerivSymbID(int symb_id) const throw (UnknownExternalFunctionSymbolIDException)
|
||||
{
|
||||
if (exists(symb_id))
|
||||
return externalFunctionTable.find(symb_id)->second.secondDerivSymbID;
|
||||
else
|
||||
throw UnknownExternalFunctionSymbolIDException(symb_id);
|
||||
}
|
||||
|
||||
inline int
|
||||
ExternalFunctionsTable::get_total_number_of_unique_model_block_external_functions() const
|
||||
{
|
||||
int number_of_unique_model_block_external_functions = 0;
|
||||
for (external_function_table_type::const_iterator it = externalFunctionTable.begin();
|
||||
it != externalFunctionTable.end(); it++)
|
||||
if (it->second.nargs > 0)
|
||||
number_of_unique_model_block_external_functions++;
|
||||
|
||||
return number_of_unique_model_block_external_functions;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,95 +0,0 @@
|
|||
SUBDIRS = macro
|
||||
|
||||
BUILT_SOURCES = DynareBison.hh stack.hh position.hh location.hh DynareBison.cc DynareFlex.cc FlexLexer.h
|
||||
|
||||
matlabdir = $(pkglibdir)/matlab
|
||||
|
||||
matlab_PROGRAMS = dynare_m
|
||||
|
||||
# We don't put BUILT_SOURCES in dynare_m_SOURCES, otherwise DynareBison.o and DynareFlex.o will be linked two times (Automake translates DynareFlex.ll and DynareBison.yy into their respective .o); so BUILT_SOURCES is in EXTRA_DIST
|
||||
dynare_m_SOURCES = \
|
||||
DynareFlex.ll \
|
||||
DynareBison.yy \
|
||||
ComputingTasks.cc \
|
||||
ComputingTasks.hh \
|
||||
ModelTree.cc \
|
||||
ModelTree.hh \
|
||||
StaticModel.cc \
|
||||
StaticModel.hh \
|
||||
DynamicModel.cc \
|
||||
DynamicModel.hh \
|
||||
NumericalConstants.cc \
|
||||
NumericalConstants.hh \
|
||||
NumericalInitialization.cc \
|
||||
NumericalInitialization.hh \
|
||||
Shocks.cc \
|
||||
Shocks.hh \
|
||||
SigmaeInitialization.cc \
|
||||
SigmaeInitialization.hh \
|
||||
SymbolTable.cc \
|
||||
SymbolTable.hh \
|
||||
SymbolList.cc \
|
||||
SymbolList.hh \
|
||||
ParsingDriver.cc \
|
||||
ParsingDriver.hh \
|
||||
DataTree.cc \
|
||||
DataTree.hh \
|
||||
ModFile.cc \
|
||||
ModFile.hh \
|
||||
ConfigFile.cc \
|
||||
ConfigFile.hh \
|
||||
Statement.cc \
|
||||
Statement.hh \
|
||||
ExprNode.cc \
|
||||
ExprNode.hh \
|
||||
MinimumFeedbackSet.cc \
|
||||
MinimumFeedbackSet.hh \
|
||||
DynareMain.cc \
|
||||
DynareMain1.cc \
|
||||
DynareMain2.cc \
|
||||
CodeInterpreter.hh \
|
||||
ExternalFunctionsTable.cc \
|
||||
ExternalFunctionsTable.hh \
|
||||
SteadyStateModel.hh \
|
||||
SteadyStateModel.cc \
|
||||
WarningConsolidation.hh \
|
||||
WarningConsolidation.cc \
|
||||
ExtendedPreprocessorTypes.hh
|
||||
|
||||
|
||||
# The -I. is for <FlexLexer.h>
|
||||
dynare_m_CPPFLAGS = $(BOOST_CPPFLAGS) -I.
|
||||
dynare_m_LDFLAGS = $(BOOST_LDFLAGS)
|
||||
dynare_m_LDADD = macro/libmacro.a
|
||||
|
||||
DynareFlex.cc FlexLexer.h: DynareFlex.ll
|
||||
$(LEX) -o DynareFlex.cc DynareFlex.ll
|
||||
cp $(LEXINC)/FlexLexer.h . || test -f ./FlexLexer.h
|
||||
|
||||
DynareBison.cc DynareBison.hh location.hh stack.hh position.hh: DynareBison.yy
|
||||
$(YACC) -o DynareBison.cc DynareBison.yy
|
||||
|
||||
all-local: $(PROGRAMS)
|
||||
if [ -z "`file $(PROGRAMS) | grep x86.64`" ]; then \
|
||||
ARCH="32"; \
|
||||
else \
|
||||
ARCH="64"; \
|
||||
fi; \
|
||||
mkdir -p ../matlab/preprocessor$$ARCH ; \
|
||||
cd ../matlab/preprocessor$$ARCH && $(LN_S) -f $(abs_srcdir)/$(PROGRAMS) $(PROGRAMS) ; \
|
||||
mkdir -p ../../julia/preprocessor$$ARCH ; \
|
||||
cd ../../julia/preprocessor$$ARCH && $(LN_S) -f $(abs_srcdir)/$(PROGRAMS) $(PROGRAMS)
|
||||
|
||||
if HAVE_DOXYGEN
|
||||
html-local:
|
||||
$(DOXYGEN)
|
||||
endif
|
||||
|
||||
clean-local:
|
||||
rm -rf ../matlab/preprocessor* ../julia/preprocessor*
|
||||
rm -rf doc/html/
|
||||
|
||||
EXTRA_DIST = $(BUILT_SOURCES) Doxyfile
|
||||
|
||||
install-exec-local:
|
||||
$(MKDIR_P) $(DESTDIR)$(pkglibdir)/matlab
|
|
@ -1,457 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "MinimumFeedbackSet.hh"
|
||||
|
||||
namespace MFS
|
||||
{
|
||||
void
|
||||
Suppress(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G)
|
||||
{
|
||||
clear_vertex(vertex_to_eliminate, G);
|
||||
remove_vertex(vertex_to_eliminate, G);
|
||||
}
|
||||
|
||||
void
|
||||
Suppress(int vertex_num, AdjacencyList_t &G)
|
||||
{
|
||||
Suppress(vertex(vertex_num, G), G);
|
||||
}
|
||||
|
||||
void
|
||||
Eliminate(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G)
|
||||
{
|
||||
if (in_degree(vertex_to_eliminate, G) > 0 && out_degree(vertex_to_eliminate, G) > 0)
|
||||
{
|
||||
AdjacencyList_t::in_edge_iterator it_in, in_end;
|
||||
AdjacencyList_t::out_edge_iterator it_out, out_end;
|
||||
for (tie(it_in, in_end) = in_edges(vertex_to_eliminate, G); it_in != in_end; ++it_in)
|
||||
for (tie(it_out, out_end) = out_edges(vertex_to_eliminate, G); it_out != out_end; ++it_out)
|
||||
{
|
||||
AdjacencyList_t::edge_descriptor ed;
|
||||
bool exist;
|
||||
tie(ed, exist) = edge(source(*it_in, G), target(*it_out, G), G);
|
||||
if (!exist)
|
||||
add_edge(source(*it_in, G), target(*it_out, G), G);
|
||||
}
|
||||
}
|
||||
Suppress(vertex_to_eliminate, G);
|
||||
}
|
||||
|
||||
bool
|
||||
has_cycle_dfs(AdjacencyList_t &g, AdjacencyList_t::vertex_descriptor u, color_t &color, vector<int> &circuit_stack)
|
||||
{
|
||||
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, g);
|
||||
color[u] = gray_color;
|
||||
graph_traits<AdjacencyList_t>::out_edge_iterator vi, vi_end;
|
||||
for (tie(vi, vi_end) = out_edges(u, g); vi != vi_end; ++vi)
|
||||
if (color[target(*vi, g)] == white_color && has_cycle_dfs(g, target(*vi, g), color, circuit_stack))
|
||||
{
|
||||
// cycle detected, return immediately
|
||||
circuit_stack.push_back(v_index[target(*vi, g)]);
|
||||
return true;
|
||||
}
|
||||
else if (color[target(*vi, g)] == gray_color)
|
||||
{
|
||||
// *vi is an ancestor!
|
||||
circuit_stack.push_back(v_index[target(*vi, g)]);
|
||||
return true;
|
||||
}
|
||||
color[u] = black_color;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
has_cycle(vector<int> &circuit_stack, AdjacencyList_t &g)
|
||||
{
|
||||
// Initialize color map to white
|
||||
color_t color;
|
||||
graph_traits<AdjacencyList_t>::vertex_iterator vi, vi_end;
|
||||
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
color[*vi] = white_color;
|
||||
|
||||
// Perform depth-first search
|
||||
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
if (color[*vi] == white_color && has_cycle_dfs(g, *vi, color, circuit_stack))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Print(AdjacencyList_t &G)
|
||||
{
|
||||
AdjacencyList_t::vertex_iterator it, it_end;
|
||||
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
||||
cout << "Graph\n";
|
||||
cout << "-----\n";
|
||||
for (tie(it, it_end) = vertices(G); it != it_end; ++it)
|
||||
{
|
||||
cout << "vertex[" << v_index[*it] + 1 << "] <-";
|
||||
AdjacencyList_t::in_edge_iterator it_in, in_end;
|
||||
for (tie(it_in, in_end) = in_edges(*it, G); it_in != in_end; ++it_in)
|
||||
cout << v_index[source(*it_in, G)] + 1 << " ";
|
||||
cout << "\n ->";
|
||||
AdjacencyList_t::out_edge_iterator it_out, out_end;
|
||||
for (tie(it_out, out_end) = out_edges(*it, G); it_out != out_end; ++it_out)
|
||||
cout << v_index[target(*it_out, G)] + 1 << " ";
|
||||
cout << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
AdjacencyList_t
|
||||
AM_2_AdjacencyList(bool *AM, unsigned int n)
|
||||
{
|
||||
AdjacencyList_t G(n);
|
||||
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
||||
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
|
||||
for (unsigned int i = 0; i < n; i++)
|
||||
{
|
||||
put(v_index, vertex(i, G), i);
|
||||
put(v_index1, vertex(i, G), i);
|
||||
}
|
||||
for (unsigned int i = 0; i < n; i++)
|
||||
for (unsigned int j = 0; j < n; j++)
|
||||
if (AM[i*n+j])
|
||||
add_edge(vertex(j, G), vertex(i, G), G);
|
||||
return G;
|
||||
}
|
||||
|
||||
AdjacencyList_t
|
||||
extract_subgraph(AdjacencyList_t &G1, set<int> select_index)
|
||||
{
|
||||
unsigned int n = select_index.size();
|
||||
AdjacencyList_t G(n);
|
||||
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
||||
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
|
||||
property_map<AdjacencyList_t, vertex_index_t>::type v1_index = get(vertex_index, G1);
|
||||
map<int, int> reverse_index;
|
||||
set<int>::iterator it;
|
||||
unsigned int i;
|
||||
for (it = select_index.begin(), i = 0; i < n; i++, ++it)
|
||||
{
|
||||
reverse_index[get(v1_index, vertex(*it, G1))] = i;
|
||||
put(v_index, vertex(i, G), get(v1_index, vertex(*it, G1)));
|
||||
put(v_index1, vertex(i, G), i);
|
||||
}
|
||||
for (it = select_index.begin(), i = 0; i < n; i++, ++it)
|
||||
{
|
||||
AdjacencyList_t::out_edge_iterator it_out, out_end;
|
||||
AdjacencyList_t::vertex_descriptor vi = vertex(*it, G1);
|
||||
for (tie(it_out, out_end) = out_edges(vi, G1); it_out != out_end; ++it_out)
|
||||
{
|
||||
int ii = v1_index[target(*it_out, G1)];
|
||||
if (select_index.find(ii) != select_index.end())
|
||||
add_edge(vertex(reverse_index[get(v1_index, source(*it_out, G1))], G), vertex(reverse_index[get(v1_index, target(*it_out, G1))], G), G);
|
||||
}
|
||||
}
|
||||
return G;
|
||||
}
|
||||
|
||||
vector_vertex_descriptor_t
|
||||
Collect_Doublet(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G)
|
||||
{
|
||||
AdjacencyList_t::in_edge_iterator it_in, in_end;
|
||||
AdjacencyList_t::out_edge_iterator it_out, out_end;
|
||||
vector<AdjacencyList_t::vertex_descriptor> Doublet;
|
||||
if (in_degree(vertex, G) > 0 && out_degree(vertex, G) > 0)
|
||||
for (tie(it_in, in_end) = in_edges(vertex, G); it_in != in_end; ++it_in)
|
||||
for (tie(it_out, out_end) = out_edges(vertex, G); it_out != out_end; ++it_out)
|
||||
if (source(*it_in, G) == target(*it_out, G) && source(*it_in, G) != target(*it_in, G)) // not a loop
|
||||
Doublet.push_back(source(*it_in, G));
|
||||
return Doublet;
|
||||
}
|
||||
|
||||
bool
|
||||
Vertex_Belong_to_a_Clique(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G)
|
||||
{
|
||||
vector<AdjacencyList_t::vertex_descriptor> liste;
|
||||
bool agree = true;
|
||||
AdjacencyList_t::in_edge_iterator it_in, in_end;
|
||||
AdjacencyList_t::out_edge_iterator it_out, out_end;
|
||||
tie(it_in, in_end) = in_edges(vertex, G);
|
||||
tie(it_out, out_end) = out_edges(vertex, G);
|
||||
while (it_in != in_end && it_out != out_end && agree)
|
||||
{
|
||||
agree = (source(*it_in, G) == target(*it_out, G) && source(*it_in, G) != target(*it_in, G)); //not a loop
|
||||
liste.push_back(source(*it_in, G));
|
||||
++it_in;
|
||||
++it_out;
|
||||
}
|
||||
if (agree)
|
||||
{
|
||||
if (it_in != in_end || it_out != out_end)
|
||||
agree = false;
|
||||
unsigned int i = 1;
|
||||
while (i < liste.size() && agree)
|
||||
{
|
||||
unsigned int j = i + 1;
|
||||
while (j < liste.size() && agree)
|
||||
{
|
||||
AdjacencyList_t::edge_descriptor ed;
|
||||
bool exist1, exist2;
|
||||
tie(ed, exist1) = edge(liste[i], liste[j], G);
|
||||
tie(ed, exist2) = edge(liste[j], liste[i], G);
|
||||
agree = (exist1 && exist2);
|
||||
j++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return agree;
|
||||
}
|
||||
|
||||
bool
|
||||
Elimination_of_Vertex_With_One_or_Less_Indegree_or_Outdegree_Step(AdjacencyList_t &G)
|
||||
{
|
||||
bool something_has_been_done = false;
|
||||
bool not_a_loop;
|
||||
int i;
|
||||
AdjacencyList_t::vertex_iterator it, it1, ita, it_end;
|
||||
for (tie(it, it_end) = vertices(G), i = 0; it != it_end; ++it, i++)
|
||||
{
|
||||
int in_degree_n = in_degree(*it, G);
|
||||
int out_degree_n = out_degree(*it, G);
|
||||
if (in_degree_n <= 1 || out_degree_n <= 1)
|
||||
{
|
||||
not_a_loop = true;
|
||||
if (in_degree_n >= 1 && out_degree_n >= 1) // Do not eliminate a vertex if it loops on itself!
|
||||
{
|
||||
AdjacencyList_t::in_edge_iterator it_in, in_end;
|
||||
for (tie(it_in, in_end) = in_edges(*it, G); it_in != in_end; ++it_in)
|
||||
if (source(*it_in, G) == target(*it_in, G))
|
||||
{
|
||||
#ifdef verbose
|
||||
cout << v_index[source(*it_in, G)] << " == " << v_index[target(*it_in, G)] << "\n";
|
||||
#endif
|
||||
not_a_loop = false;
|
||||
}
|
||||
}
|
||||
if (not_a_loop)
|
||||
{
|
||||
#ifdef verbose
|
||||
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
||||
cout << "->eliminate vertex[" << v_index[*it] + 1 << "]\n";
|
||||
#endif
|
||||
Eliminate(*it, G);
|
||||
#ifdef verbose
|
||||
Print(G);
|
||||
#endif
|
||||
something_has_been_done = true;
|
||||
if (i > 0)
|
||||
it = ita;
|
||||
else
|
||||
{
|
||||
tie(it, it_end) = vertices(G);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
ita = it;
|
||||
}
|
||||
return something_has_been_done;
|
||||
}
|
||||
|
||||
bool
|
||||
Elimination_of_Vertex_belonging_to_a_clique_Step(AdjacencyList_t &G)
|
||||
{
|
||||
AdjacencyList_t::vertex_iterator it, it1, ita, it_end;
|
||||
bool something_has_been_done = false;
|
||||
int i;
|
||||
for (tie(it, it_end) = vertices(G), i = 0; it != it_end; ++it, i++)
|
||||
{
|
||||
if (Vertex_Belong_to_a_Clique(*it, G))
|
||||
{
|
||||
#ifdef verbose
|
||||
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
||||
cout << "eliminate vertex[" << v_index[*it] + 1 << "]\n";
|
||||
#endif
|
||||
Eliminate(*it, G);
|
||||
something_has_been_done = true;
|
||||
if (i > 0)
|
||||
it = ita;
|
||||
else
|
||||
{
|
||||
tie(it, it_end) = vertices(G);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
ita = it;
|
||||
}
|
||||
return something_has_been_done;
|
||||
}
|
||||
|
||||
bool
|
||||
Suppression_of_Vertex_X_if_it_loops_store_in_set_of_feedback_vertex_Step(set<int> &feed_back_vertices, AdjacencyList_t &G)
|
||||
{
|
||||
bool something_has_been_done = false;
|
||||
AdjacencyList_t::vertex_iterator it, it_end, ita;
|
||||
int i = 0;
|
||||
for (tie(it, it_end) = vertices(G); it != it_end; ++it, i++)
|
||||
{
|
||||
AdjacencyList_t::edge_descriptor ed;
|
||||
bool exist;
|
||||
tie(ed, exist) = edge(*it, *it, G);
|
||||
if (exist)
|
||||
{
|
||||
#ifdef verbose
|
||||
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
||||
cout << "store v[*it] = " << v_index[*it]+1 << "\n";
|
||||
#endif
|
||||
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
|
||||
feed_back_vertices.insert(v_index1[*it]);
|
||||
/*property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
||||
feed_back_vertices.insert(v_index[*it] );*/
|
||||
Suppress(*it, G);
|
||||
something_has_been_done = true;
|
||||
if (i > 0)
|
||||
it = ita;
|
||||
else
|
||||
{
|
||||
tie(it, it_end) = vertices(G);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
ita = it;
|
||||
}
|
||||
return something_has_been_done;
|
||||
}
|
||||
|
||||
AdjacencyList_t
|
||||
Minimal_set_of_feedback_vertex(set<int> &feed_back_vertices, const AdjacencyList_t &G1)
|
||||
{
|
||||
bool something_has_been_done = true;
|
||||
int cut_ = 0;
|
||||
feed_back_vertices.clear();
|
||||
AdjacencyList_t G(G1);
|
||||
while (num_vertices(G) > 0)
|
||||
{
|
||||
while (something_has_been_done && num_vertices(G) > 0)
|
||||
{
|
||||
//Rule 1
|
||||
something_has_been_done = (Elimination_of_Vertex_With_One_or_Less_Indegree_or_Outdegree_Step(G) /*or something_has_been_done*/);
|
||||
#ifdef verbose
|
||||
cout << "1 something_has_been_done=" << something_has_been_done << "\n";
|
||||
#endif
|
||||
|
||||
//Rule 2
|
||||
something_has_been_done = (Elimination_of_Vertex_belonging_to_a_clique_Step(G) || something_has_been_done);
|
||||
#ifdef verbose
|
||||
cout << "2 something_has_been_done=" << something_has_been_done << "\n";
|
||||
#endif
|
||||
|
||||
//Rule 3
|
||||
something_has_been_done = (Suppression_of_Vertex_X_if_it_loops_store_in_set_of_feedback_vertex_Step(feed_back_vertices, G) || something_has_been_done);
|
||||
#ifdef verbose
|
||||
cout << "3 something_has_been_done=" << something_has_been_done << "\n";
|
||||
#endif
|
||||
}
|
||||
vector<int> circuit;
|
||||
if (!has_cycle(circuit, G))
|
||||
{
|
||||
#ifdef verbose
|
||||
cout << "has_cycle=false\n";
|
||||
#endif
|
||||
//sort(feed_back_vertices.begin(), feed_back_vertices.end());
|
||||
return G;
|
||||
}
|
||||
if (num_vertices(G) > 0)
|
||||
{
|
||||
/*if nothing has been done in the five previous rule then cut the vertex with the maximum in_degree+out_degree*/
|
||||
unsigned int max_degree = 0, num = 0;
|
||||
AdjacencyList_t::vertex_iterator it, it_end, max_degree_index;
|
||||
for (tie(it, it_end) = vertices(G); it != it_end; ++it, num++)
|
||||
{
|
||||
if (in_degree(*it, G) + out_degree(*it, G) > max_degree)
|
||||
{
|
||||
max_degree = in_degree(*it, G) + out_degree(*it, G);
|
||||
max_degree_index = it;
|
||||
}
|
||||
}
|
||||
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
|
||||
feed_back_vertices.insert(v_index1[*max_degree_index]);
|
||||
/*property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
||||
feed_back_vertices.insert(v_index[*max_degree_index]);*/
|
||||
//cout << "v_index1[*max_degree_index] = " << v_index1[*max_degree_index] << "\n";
|
||||
cut_++;
|
||||
#ifdef verbose
|
||||
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
||||
cout << "--> cut vertex " << v_index[*max_degree_index] + 1 << "\n";
|
||||
#endif
|
||||
Suppress(*max_degree_index, G);
|
||||
something_has_been_done = true;
|
||||
}
|
||||
}
|
||||
#ifdef verbose
|
||||
cout << "cut_=" << cut_ << "\n";
|
||||
#endif
|
||||
//sort(feed_back_vertices.begin(), feed_back_vertices.end());
|
||||
return G;
|
||||
}
|
||||
|
||||
struct rev
|
||||
{
|
||||
bool
|
||||
operator()(const int a, const int b) const
|
||||
{
|
||||
return (a > b);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
Reorder_the_recursive_variables(const AdjacencyList_t &G1, set<int> &feedback_vertices, vector< int> &Reordered_Vertices)
|
||||
{
|
||||
AdjacencyList_t G(G1);
|
||||
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
||||
set<int>::iterator its, ita;
|
||||
set<int, rev> fv;
|
||||
for (its = feedback_vertices.begin(); its != feedback_vertices.end(); its++)
|
||||
fv.insert(*its);
|
||||
int i = 0;
|
||||
for (its = fv.begin(); its != fv.end(); ++its, i++)
|
||||
Suppress(*its, G);
|
||||
bool something_has_been_done = true;
|
||||
while (something_has_been_done)
|
||||
{
|
||||
something_has_been_done = false;
|
||||
AdjacencyList_t::vertex_iterator it, it_end, ita;
|
||||
for (tie(it, it_end) = vertices(G), i = 0; it != it_end; ++it, i++)
|
||||
{
|
||||
if (in_degree(*it, G) == 0)
|
||||
{
|
||||
Reordered_Vertices.push_back(v_index[*it]);
|
||||
Suppress(*it, G);
|
||||
something_has_been_done = true;
|
||||
if (i > 0)
|
||||
it = ita;
|
||||
else
|
||||
{
|
||||
tie(it, it_end) = vertices(G);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
ita = it;
|
||||
}
|
||||
}
|
||||
if (num_vertices(G))
|
||||
cout << "Error in the computation of feedback vertex set\n";
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _MINIMUMFEEDBACKSET_HH
|
||||
#define _MINIMUMFEEDBACKSET_HH
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
namespace MFS
|
||||
{
|
||||
typedef property<vertex_index_t, int,
|
||||
property<vertex_index1_t, int,
|
||||
property<vertex_degree_t, int,
|
||||
property<vertex_in_degree_t, int,
|
||||
property<vertex_out_degree_t, int > > > > > VertexProperty_t;
|
||||
typedef adjacency_list<listS, listS, bidirectionalS, VertexProperty_t> AdjacencyList_t;
|
||||
typedef map<graph_traits<AdjacencyList_t>::vertex_descriptor, default_color_type> color_t;
|
||||
typedef vector<AdjacencyList_t::vertex_descriptor> vector_vertex_descriptor_t;
|
||||
|
||||
//! Eliminate a vertex i
|
||||
/*! For a vertex i replace all edges e_k_i and e_i_j by a shorcut e_k_j and then Suppress the vertex i*/
|
||||
void Eliminate(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G);
|
||||
//! Collect all doublets (edges e_i_k such that there is an edge e_k_i with k!=i in the graph)
|
||||
/*! Returns the vector of doublets */
|
||||
vector_vertex_descriptor_t Collect_Doublet(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G);
|
||||
//! Detect all the clique (all vertex in a clique are related to each other) in the graph
|
||||
bool Vertex_Belong_to_a_Clique(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G);
|
||||
//! Graph reduction: eliminating purely intermediate variables or variables outside of any circuit
|
||||
bool Elimination_of_Vertex_With_One_or_Less_Indegree_or_Outdegree_Step(AdjacencyList_t &G);
|
||||
//! Graph reduction: elimination of a vertex inside a clique
|
||||
bool Elimination_of_Vertex_belonging_to_a_clique_Step(AdjacencyList_t &G);
|
||||
//! A vertex belong to the feedback vertex set if the vertex loops on itself.
|
||||
/*! We have to suppress this vertex and store it into the feedback set.*/
|
||||
bool Suppression_of_Vertex_X_if_it_loops_store_in_set_of_feedback_vertex_Step(set<int> &feed_back_vertices, AdjacencyList_t &G1);
|
||||
//! Print the Graph
|
||||
void Print(AdjacencyList_t &G);
|
||||
//! Create an adjacency graph from a Adjacency Matrix (an incidence Matrix without the diagonal terms)
|
||||
AdjacencyList_t AM_2_AdjacencyList(bool *AMp, unsigned int n);
|
||||
//! Extracts a subgraph
|
||||
/*!
|
||||
\param[in] G1 The original graph
|
||||
\param[in] select_index The vertex indices to select
|
||||
\return The subgraph
|
||||
|
||||
The property vertex_index of the subgraph contains indices of the original
|
||||
graph, the property vertex_index1 contains new contiguous indices specific
|
||||
to the subgraph.
|
||||
*/
|
||||
AdjacencyList_t extract_subgraph(AdjacencyList_t &G1, set<int> select_index);
|
||||
//! Check if the graph contains any cycle (true if the model contains at least one cycle, false otherwise)
|
||||
bool has_cycle(vector<int> &circuit_stack, AdjacencyList_t &g);
|
||||
bool has_cycle_dfs(AdjacencyList_t &g, AdjacencyList_t::vertex_descriptor u, color_t &color, vector<int> &circuit_stack);
|
||||
//! Return the feedback set
|
||||
AdjacencyList_t Minimal_set_of_feedback_vertex(set<int> &feed_back_vertices, const AdjacencyList_t &G);
|
||||
//! Clear all in and out edges of vertex_to_eliminate and remove vertex_to_eliminate from the graph
|
||||
void Suppress(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G);
|
||||
void Suppress(int vertex_num, AdjacencyList_t &G);
|
||||
//! Reorder the recursive variables
|
||||
/*! They appear first in a quasi triangular form and they are followed by the feedback variables */
|
||||
void Reorder_the_recursive_variables(const AdjacencyList_t &G1, set<int> &feedback_vertices, vector< int> &Reordered_Vertices);
|
||||
};
|
||||
|
||||
#endif // _MINIMUMFEEDBACKSET_HH
|
File diff suppressed because it is too large
Load Diff
|
@ -1,181 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _MOD_FILE_HH
|
||||
#define _MOD_FILE_HH
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <ostream>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "SymbolTable.hh"
|
||||
#include "NumericalConstants.hh"
|
||||
#include "NumericalInitialization.hh"
|
||||
#include "StaticModel.hh"
|
||||
#include "DynamicModel.hh"
|
||||
#include "SteadyStateModel.hh"
|
||||
#include "Statement.hh"
|
||||
#include "ExternalFunctionsTable.hh"
|
||||
#include "ConfigFile.hh"
|
||||
#include "WarningConsolidation.hh"
|
||||
#include "ExtendedPreprocessorTypes.hh"
|
||||
|
||||
// for checksum computation
|
||||
#ifndef PRIVATE_BUFFER_SIZE
|
||||
# define PRIVATE_BUFFER_SIZE 1024
|
||||
#endif
|
||||
|
||||
//! The abstract representation of a "mod" file
|
||||
class ModFile
|
||||
{
|
||||
public:
|
||||
ModFile(WarningConsolidation &warnings_arg);
|
||||
~ModFile();
|
||||
//! Symbol table
|
||||
SymbolTable symbol_table;
|
||||
//! External Functions table
|
||||
ExternalFunctionsTable external_functions_table;
|
||||
//! Numerical constants table
|
||||
NumericalConstants num_constants;
|
||||
//! Expressions outside model block
|
||||
DataTree expressions_tree;
|
||||
//! Original model, as declared in the "model" block, that won't be modified by the preprocessor
|
||||
DynamicModel original_model;
|
||||
//! Dynamic model, as declared in the "model" block
|
||||
DynamicModel dynamic_model;
|
||||
//! A copy of Dynamic model, for testing trends declared by user
|
||||
DynamicModel trend_dynamic_model;
|
||||
//! A model in which to create the FOC for the ramsey problem
|
||||
DynamicModel ramsey_FOC_equations_dynamic_model;
|
||||
//! A copy of the original model, used to test model linearity under ramsey problem
|
||||
DynamicModel orig_ramsey_dynamic_model;
|
||||
//! Static model, as derived from the "model" block when leads and lags have been removed
|
||||
StaticModel static_model;
|
||||
//! Static model, as declared in the "steady_state_model" block if present
|
||||
SteadyStateModel steady_state_model;
|
||||
//! Option linear
|
||||
bool linear;
|
||||
|
||||
//! Is the model block decomposed?
|
||||
bool block;
|
||||
|
||||
//! Is the model stored in bytecode format (byte_code=true) or in a M-file (byte_code=false)
|
||||
bool byte_code;
|
||||
|
||||
//! Is the model stored in a MEX file ? (option "use_dll" of "model")
|
||||
bool use_dll;
|
||||
|
||||
//! Is the static model have to computed (no_static=false) or not (no_static=true). Option of 'model'
|
||||
bool no_static;
|
||||
|
||||
//! Is the 'differentiate_forward_vars' option used?
|
||||
bool differentiate_forward_vars;
|
||||
|
||||
/*! If the 'differentiate_forward_vars' option is used, contains the set of
|
||||
endogenous with respect to which to do the transformation;
|
||||
if empty, means that the transformation must be applied to all endos
|
||||
with a lead */
|
||||
vector<string> differentiate_forward_vars_subset;
|
||||
|
||||
//! Are nonstationary variables present ?
|
||||
bool nonstationary_variables;
|
||||
|
||||
//! Global evaluation context
|
||||
/*! Filled using initval blocks and parameters initializations */
|
||||
eval_context_t global_eval_context;
|
||||
|
||||
//! Parameter used with lead/lag
|
||||
bool param_used_with_lead_lag;
|
||||
|
||||
//! Stores the list of extra files to be transefered during a parallel run
|
||||
/*! (i.e. option parallel_local_files of model block) */
|
||||
vector<string> parallel_local_files;
|
||||
|
||||
private:
|
||||
//! List of statements
|
||||
vector<Statement *> statements;
|
||||
//! Structure of the mod file
|
||||
ModFileStructure mod_file_struct;
|
||||
//! Warnings Encountered
|
||||
WarningConsolidation &warnings;
|
||||
//! Functions used in writing of JSON outut. See writeJsonOutput
|
||||
void writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType json_output_mode, bool transformpass, bool computingpass) const;
|
||||
void writeJsonComputingPassOutput(const string &basename, JsonFileOutputType json_output_mode, bool jsonderivsimple) const;
|
||||
void writeJsonFileHelper(string &fname, ostringstream &output) const;
|
||||
public:
|
||||
//! Add a statement
|
||||
void addStatement(Statement *st);
|
||||
//! Add a statement at the front of the statements vector
|
||||
void addStatementAtFront(Statement *st);
|
||||
//! Evaluate all the statements
|
||||
/*! \param warn_uninit Should a warning be displayed for uninitialized endogenous/exogenous/parameters ? */
|
||||
void evalAllExpressions(bool warn_uninit, const bool nopreprocessoroutput);
|
||||
//! Do some checking and fills mod_file_struct
|
||||
/*! \todo add check for number of equations and endogenous if ramsey_policy is present */
|
||||
void checkPass(bool nostrict, bool stochastic);
|
||||
//! Perform some transformations on the model (creation of auxiliary vars and equations)
|
||||
/*! \param compute_xrefs if true, equation cross references will be computed */
|
||||
void transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const bool nopreprocessoroutput);
|
||||
//! Execute computations
|
||||
/*! \param no_tmp_terms if true, no temporary terms will be computed in the static and dynamic files */
|
||||
/*! \param params_derivs_order compute this order of derivs wrt parameters */
|
||||
void computingPass(bool no_tmp_terms, FileOutputType output, int params_derivs_order, const bool nopreprocessoroutput);
|
||||
//! Writes Matlab/Octave output files
|
||||
/*!
|
||||
\param basename The base name used for writing output files. Should be the name of the mod file without its extension
|
||||
\param clear_all Should a "clear all" instruction be written to output ?
|
||||
\param console Are we in console mode ?
|
||||
\param nograph Should we build the figures?
|
||||
\param nointeractive Should Dynare request user input?
|
||||
\param cygwin Should the MEX command of use_dll be adapted for Cygwin?
|
||||
\param msvc Should the MEX command of use_dll be adapted for MSVC?
|
||||
\param mingw Should the MEX command of use_dll be adapted for MinGW?
|
||||
\param compute_xrefs if true, equation cross references will be computed
|
||||
*/
|
||||
void writeOutputFiles(const string &basename, bool clear_all, bool clear_global, bool no_log, bool no_warn,
|
||||
bool console, bool nograph, bool nointeractive, const ConfigFile &config_file,
|
||||
bool check_model_changes, bool minimal_workspace, bool compute_xrefs
|
||||
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
|
||||
, bool cygwin, bool msvc, bool mingw
|
||||
#endif
|
||||
, const bool nopreprocessoroutput
|
||||
) const;
|
||||
void writeExternalFiles(const string &basename, FileOutputType output, LanguageOutputType language, const bool nopreprocessoroutput) const;
|
||||
void writeExternalFilesC(const string &basename, FileOutputType output) const;
|
||||
void writeExternalFilesCC(const string &basename, FileOutputType output) const;
|
||||
void writeExternalFilesJulia(const string &basename, FileOutputType output, const bool nopreprocessoroutput) const;
|
||||
//! Writes C output files only => No further Matlab processing
|
||||
void writeCOutputFiles(const string &basename) const;
|
||||
void writeModelC(const string &basename) const;
|
||||
//! Writes Cpp output files only => No further Matlab processing
|
||||
void writeCCOutputFiles(const string &basename) const;
|
||||
void writeModelCC(const string &basename) const;
|
||||
|
||||
void computeChecksum();
|
||||
//! Write JSON representation of ModFile object
|
||||
//! Initially created to enable Julia to work with .mod files
|
||||
//! Potentially outputs ModFile after the various parts of processing (parsing, checkPass, transformPass, computingPass)
|
||||
//! Allows user of other host language platforms (python, fortran, etc) to provide support for dynare .mod files
|
||||
void writeJsonOutput(const string &basename, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, const bool nopreprocessoroutput, bool jsonderivsimple = false);
|
||||
};
|
||||
|
||||
#endif // ! MOD_FILE_HH
|
File diff suppressed because it is too large
Load Diff
|
@ -1,412 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _MODELTREE_HH
|
||||
#define _MODELTREE_HH
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
|
||||
#include "DataTree.hh"
|
||||
#include "ExtendedPreprocessorTypes.hh"
|
||||
|
||||
//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation
|
||||
typedef vector<pair<EquationType, expr_t > > equation_type_and_normalized_equation_t;
|
||||
|
||||
//! Vector describing variables: max_lag in the block, max_lead in the block
|
||||
typedef vector<pair< int, int> > lag_lead_vector_t;
|
||||
|
||||
//! for each block contains pair< pair<Simulation_Type, first_equation>, pair < Block_Size, Recursive_part_Size > >
|
||||
typedef vector<pair< pair< BlockSimulationType, int>, pair<int, int> > > block_type_firstequation_size_mfs_t;
|
||||
|
||||
//! for a block contains derivatives pair< pair<block_equation_number, block_variable_number> , pair<lead_lag, expr_t> >
|
||||
typedef vector< pair<pair<int, int>, pair< int, expr_t > > > block_derivatives_equation_variable_laglead_nodeid_t;
|
||||
|
||||
//! for all blocks derivatives description
|
||||
typedef vector<block_derivatives_equation_variable_laglead_nodeid_t> blocks_derivatives_t;
|
||||
|
||||
//! Shared code for static and dynamic models
|
||||
class ModelTree : public DataTree
|
||||
{
|
||||
friend class DynamicModel;
|
||||
friend class StaticModel;
|
||||
protected:
|
||||
//! Stores declared and generated auxiliary equations
|
||||
vector<BinaryOpNode *> equations;
|
||||
|
||||
//! Stores line numbers of declared equations; -1 means undefined
|
||||
vector<int> equations_lineno;
|
||||
|
||||
//! Only stores generated auxiliary equations, in an order meaningful for evaluation
|
||||
deque<BinaryOpNode *> aux_equations;
|
||||
|
||||
//! Stores equation tags
|
||||
vector<pair<int, pair<string, string> > > equation_tags;
|
||||
|
||||
//! Number of non-zero derivatives
|
||||
int NNZDerivatives[3];
|
||||
|
||||
typedef map<pair<int, int>, expr_t> first_derivatives_t;
|
||||
//! First order derivatives
|
||||
/*! First index is equation number, second is variable w.r. to which is computed the derivative.
|
||||
Only non-null derivatives are stored in the map.
|
||||
Variable indices are those of the getDerivID() method.
|
||||
*/
|
||||
first_derivatives_t first_derivatives;
|
||||
|
||||
typedef map<pair<int, pair<int, int> >, expr_t> second_derivatives_t;
|
||||
//! Second order derivatives
|
||||
/*! First index is equation number, second and third are variables w.r. to which is computed the derivative.
|
||||
Only non-null derivatives are stored in the map.
|
||||
Contains only second order derivatives where var1 >= var2 (for obvious symmetry reasons).
|
||||
Variable indices are those of the getDerivID() method.
|
||||
*/
|
||||
second_derivatives_t second_derivatives;
|
||||
|
||||
typedef map<pair<int, pair<int, pair<int, int> > >, expr_t> third_derivatives_t;
|
||||
//! Third order derivatives
|
||||
/*! First index is equation number, second, third and fourth are variables w.r. to which is computed the derivative.
|
||||
Only non-null derivatives are stored in the map.
|
||||
Contains only third order derivatives where var1 >= var2 >= var3 (for obvious symmetry reasons).
|
||||
Variable indices are those of the getDerivID() method.
|
||||
*/
|
||||
third_derivatives_t third_derivatives;
|
||||
|
||||
//! Derivatives of the residuals w.r. to parameters
|
||||
/*! First index is equation number, second is parameter.
|
||||
Only non-null derivatives are stored in the map.
|
||||
Parameter indices are those of the getDerivID() method.
|
||||
*/
|
||||
first_derivatives_t residuals_params_derivatives;
|
||||
|
||||
//! Second derivatives of the residuals w.r. to parameters
|
||||
/*! First index is equation number, second and third indeces are parameters.
|
||||
Only non-null derivatives are stored in the map.
|
||||
Parameter indices are those of the getDerivID() method.
|
||||
*/
|
||||
second_derivatives_t residuals_params_second_derivatives;
|
||||
|
||||
//! Derivatives of the jacobian w.r. to parameters
|
||||
/*! First index is equation number, second is endo/exo/exo_det variable, and third is parameter.
|
||||
Only non-null derivatives are stored in the map.
|
||||
Variable and parameter indices are those of the getDerivID() method.
|
||||
*/
|
||||
second_derivatives_t jacobian_params_derivatives;
|
||||
|
||||
//! Second derivatives of the jacobian w.r. to parameters
|
||||
/*! First index is equation number, second is endo/exo/exo_det variable, and third and fourth are parameters.
|
||||
Only non-null derivatives are stored in the map.
|
||||
Variable and parameter indices are those of the getDerivID() method.
|
||||
*/
|
||||
third_derivatives_t jacobian_params_second_derivatives;
|
||||
|
||||
//! Derivatives of the hessian w.r. to parameters
|
||||
/*! First index is equation number, first and second are endo/exo/exo_det variable, and third is parameter.
|
||||
Only non-null derivatives are stored in the map.
|
||||
Variable and parameter indices are those of the getDerivID() method.
|
||||
*/
|
||||
third_derivatives_t hessian_params_derivatives;
|
||||
|
||||
//! Temporary terms for the static/dynamic file (those which will be noted Txxxx)
|
||||
temporary_terms_t temporary_terms;
|
||||
temporary_terms_t temporary_terms_res;
|
||||
temporary_terms_t temporary_terms_g1;
|
||||
temporary_terms_t temporary_terms_g2;
|
||||
temporary_terms_t temporary_terms_g3;
|
||||
|
||||
//! Temporary terms for the file containing parameters derivatives
|
||||
temporary_terms_t params_derivs_temporary_terms;
|
||||
temporary_terms_t params_derivs_temporary_terms_res;
|
||||
temporary_terms_t params_derivs_temporary_terms_g1;
|
||||
temporary_terms_t params_derivs_temporary_terms_res2;
|
||||
temporary_terms_t params_derivs_temporary_terms_g12;
|
||||
temporary_terms_t params_derivs_temporary_terms_g2;
|
||||
|
||||
//! Trend variables and their growth factors
|
||||
map<int, expr_t> trend_symbols_map;
|
||||
|
||||
//! for all trends; the boolean is true if this is a log-trend, false otherwise
|
||||
typedef map<int, pair<bool, expr_t> > nonstationary_symbols_map_t;
|
||||
|
||||
//! Nonstationary variables and their deflators
|
||||
nonstationary_symbols_map_t nonstationary_symbols_map;
|
||||
|
||||
//! vector of block reordered variables and equations
|
||||
vector<int> equation_reordered, variable_reordered, inv_equation_reordered, inv_variable_reordered;
|
||||
|
||||
//! the file containing the model and the derivatives code
|
||||
ofstream code_file;
|
||||
|
||||
//! Computes 1st derivatives
|
||||
/*! \param vars the derivation IDs w.r. to which compute the derivatives */
|
||||
void computeJacobian(const set<int> &vars);
|
||||
//! Computes 2nd derivatives
|
||||
/*! \param vars the derivation IDs w.r. to which derive the 1st derivatives */
|
||||
void computeHessian(const set<int> &vars);
|
||||
//! Computes 3rd derivatives
|
||||
/*! \param vars the derivation IDs w.r. to which derive the 2nd derivatives */
|
||||
void computeThirdDerivatives(const set<int> &vars);
|
||||
//! Computes derivatives of the Jacobian and Hessian w.r. to parameters
|
||||
void computeParamsDerivatives(int paramsDerivsOrder);
|
||||
//! Write derivative of an equation w.r. to a variable
|
||||
void writeDerivative(ostream &output, int eq, int symb_id, int lag, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const;
|
||||
//! Computes temporary terms (for all equations and derivatives)
|
||||
void computeTemporaryTerms(bool is_matlab);
|
||||
//! Computes temporary terms for the file containing parameters derivatives
|
||||
void computeParamsDerivativesTemporaryTerms();
|
||||
//! Writes temporary terms
|
||||
void writeTemporaryTerms(const temporary_terms_t &tt, const temporary_terms_t &ttm1, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const;
|
||||
void writeJsonTemporaryTerms(const temporary_terms_t &tt, const temporary_terms_t &ttm1, ostream &output, deriv_node_temp_terms_t &tef_terms, string &concat) const;
|
||||
//! Compiles temporary terms
|
||||
void compileTemporaryTerms(ostream &code_file, unsigned int &instruction_number, const temporary_terms_t &tt, map_idx_t map_idx, bool dynamic, bool steady_dynamic) const;
|
||||
//! Adds informations for simulation in a binary file
|
||||
void Write_Inf_To_Bin_File(const string &basename, int &u_count_int, bool &file_open, bool is_two_boundaries, int block_mfs) const;
|
||||
//! Fixes output when there are more than 32 nested parens, Issue #1201
|
||||
void fixNestedParenthesis(ostringstream &output, map<string, string> &tmp_paren_vars, bool &message_printed) const;
|
||||
//! Tests if string contains more than 32 nested parens, Issue #1201
|
||||
bool testNestedParenthesis(const string &str) const;
|
||||
//! Writes model local variables
|
||||
/*! No temporary term is used in the output, so that local parameters declarations can be safely put before temporary terms declaration in the output files */
|
||||
void writeModelLocalVariables(ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const;
|
||||
//! Writes model equations
|
||||
void writeModelEquations(ostream &output, ExprNodeOutputType output_type) const;
|
||||
//! Writes JSON model equations
|
||||
//! if residuals = true, we are writing the dynamic/static model.
|
||||
//! Otherwise, just the model equations (with line numbers, no tmp terms)
|
||||
void writeJsonModelEquations(ostream &output, bool residuals) const;
|
||||
void writeJsonModelLocalVariables(ostream &output, deriv_node_temp_terms_t &tef_terms) const;
|
||||
//! Compiles model equations
|
||||
void compileModelEquations(ostream &code_file, unsigned int &instruction_number, const temporary_terms_t &tt, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic) const;
|
||||
|
||||
//! Writes LaTeX model file
|
||||
void writeLatexModelFile(const string &basename, ExprNodeOutputType output_type, const bool write_equation_tags) const;
|
||||
|
||||
//! Sparse matrix of double to store the values of the Jacobian
|
||||
/*! First index is equation number, second index is endogenous type specific ID */
|
||||
typedef map<pair<int, int>, double> jacob_map_t;
|
||||
|
||||
//! Sparse matrix of double to store the values of the Jacobian
|
||||
/*! First index is lag, second index is equation number, third index is endogenous type specific ID */
|
||||
typedef map<pair<int, pair<int, int> >, expr_t> dynamic_jacob_map_t;
|
||||
|
||||
//! Normalization of equations
|
||||
/*! Maps endogenous type specific IDs to equation numbers */
|
||||
vector<int> endo2eq;
|
||||
|
||||
//! number of equation in the prologue and in the epilogue
|
||||
unsigned int epilogue, prologue;
|
||||
|
||||
//! for each block contains pair< max_lag, max_lead>
|
||||
lag_lead_vector_t block_lag_lead;
|
||||
|
||||
//! Compute the matching between endogenous and variable using the jacobian contemporaneous_jacobian
|
||||
/*!
|
||||
\param contemporaneous_jacobian Jacobian used as an incidence matrix: all elements declared in the map (even if they are zero), are used as vertices of the incidence matrix
|
||||
\return True if a complete normalization has been achieved
|
||||
*/
|
||||
bool computeNormalization(const jacob_map_t &contemporaneous_jacobian, bool verbose);
|
||||
|
||||
//! Try to compute the matching between endogenous and variable using a decreasing cutoff
|
||||
/*!
|
||||
Applied to the jacobian contemporaneous_jacobian and stop when a matching is found.
|
||||
If no matching is found using a strictly positive cutoff, then a zero cutoff is applied (i.e. use a symbolic normalization); in that case, the method adds zeros in the jacobian matrices to reflect all the edges in the symbolic incidence matrix.
|
||||
If no matching is found with a zero cutoff close to zero an error message is printout.
|
||||
*/
|
||||
void computeNonSingularNormalization(jacob_map_t &contemporaneous_jacobian, double cutoff, jacob_map_t &static_jacobian, dynamic_jacob_map_t &dynamic_jacobian);
|
||||
|
||||
//! Try to normalized each unnormalized equation (matched endogenous variable only on the LHS)
|
||||
void computeNormalizedEquations(multimap<int, int> &endo2eqs) const;
|
||||
//! Evaluate the jacobian and suppress all the elements below the cutoff
|
||||
void evaluateAndReduceJacobian(const eval_context_t &eval_context, jacob_map_t &contemporaneous_jacobian, jacob_map_t &static_jacobian, dynamic_jacob_map_t &dynamic_jacobian, double cutoff, bool verbose);
|
||||
//! Search the equations and variables belonging to the prologue and the epilogue of the model
|
||||
void computePrologueAndEpilogue(const jacob_map_t &static_jacobian, vector<int> &equation_reordered, vector<int> &variable_reordered);
|
||||
//! Determine the type of each equation of model and try to normalized the unnormalized equation using computeNormalizedEquations
|
||||
equation_type_and_normalized_equation_t equationTypeDetermination(const map<pair<int, pair<int, int> >, expr_t> &first_order_endo_derivatives, const vector<int> &Index_Var_IM, const vector<int> &Index_Equ_IM, int mfs) const;
|
||||
//! Compute the block decomposition and for a non-recusive block find the minimum feedback set
|
||||
void computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob_map_t &static_jacobian, const dynamic_jacob_map_t &dynamic_jacobian, vector<int> &equation_reordered, vector<int> &variable_reordered, vector<pair<int, int> > &blocks, const equation_type_and_normalized_equation_t &Equation_Type, bool verbose_, bool select_feedback_variable, int mfs, vector<int> &inv_equation_reordered, vector<int> &inv_variable_reordered, lag_lead_vector_t &equation_lag_lead, lag_lead_vector_t &variable_lag_lead_t, vector<unsigned int> &n_static, vector<unsigned int> &n_forward, vector<unsigned int> &n_backward, vector<unsigned int> &n_mixed) const;
|
||||
//! Reduce the number of block merging the same type equation in the prologue and the epilogue and determine the type of each block
|
||||
block_type_firstequation_size_mfs_t reduceBlocksAndTypeDetermination(const dynamic_jacob_map_t &dynamic_jacobian, vector<pair<int, int> > &blocks, const equation_type_and_normalized_equation_t &Equation_Type, const vector<int> &variable_reordered, const vector<int> &equation_reordered, vector<unsigned int> &n_static, vector<unsigned int> &n_forward, vector<unsigned int> &n_backward, vector<unsigned int> &n_mixed, vector<pair< pair<int, int>, pair<int, int> > > &block_col_type);
|
||||
//! Determine the maximum number of lead and lag for the endogenous variable in a bloc
|
||||
void getVariableLeadLagByBlock(const dynamic_jacob_map_t &dynamic_jacobian, const vector<int> &components_set, int nb_blck_sim, lag_lead_vector_t &equation_lead_lag, lag_lead_vector_t &variable_lead_lag, const vector<int> &equation_reordered, const vector<int> &variable_reordered) const;
|
||||
//! Print an abstract of the block structure of the model
|
||||
void printBlockDecomposition(const vector<pair<int, int> > &blocks) const;
|
||||
//! Determine for each block if it is linear or not
|
||||
vector<bool> BlockLinear(const blocks_derivatives_t &blocks_derivatives, const vector<int> &variable_reordered) const;
|
||||
|
||||
//! Determine the simulation type of each block
|
||||
virtual BlockSimulationType getBlockSimulationType(int block_number) const = 0;
|
||||
//! Return the number of blocks
|
||||
virtual unsigned int getNbBlocks() const = 0;
|
||||
//! Return the first equation number of a block
|
||||
virtual unsigned int getBlockFirstEquation(int block_number) const = 0;
|
||||
//! Return the size of the block block_number
|
||||
virtual unsigned int getBlockSize(int block_number) const = 0;
|
||||
//! Return the number of exogenous variable in the block block_number
|
||||
virtual unsigned int getBlockExoSize(int block_number) const = 0;
|
||||
//! Return the number of colums in the jacobian matrix for exogenous variable in the block block_number
|
||||
virtual unsigned int getBlockExoColSize(int block_number) const = 0;
|
||||
//! Return the number of feedback variable of the block block_number
|
||||
virtual unsigned int getBlockMfs(int block_number) const = 0;
|
||||
//! Return the maximum lag in a block
|
||||
virtual unsigned int getBlockMaxLag(int block_number) const = 0;
|
||||
//! Return the maximum lead in a block
|
||||
virtual unsigned int getBlockMaxLead(int block_number) const = 0;
|
||||
inline void
|
||||
setBlockLeadLag(int block, int max_lag, int max_lead)
|
||||
{
|
||||
block_lag_lead[block] = make_pair(max_lag, max_lead);
|
||||
};
|
||||
|
||||
//! Return the type of equation (equation_number) belonging to the block block_number
|
||||
virtual EquationType getBlockEquationType(int block_number, int equation_number) const = 0;
|
||||
//! Return true if the equation has been normalized
|
||||
virtual bool isBlockEquationRenormalized(int block_number, int equation_number) const = 0;
|
||||
//! Return the expr_t of the equation equation_number belonging to the block block_number
|
||||
virtual expr_t getBlockEquationExpr(int block_number, int equation_number) const = 0;
|
||||
//! Return the expr_t of the renormalized equation equation_number belonging to the block block_number
|
||||
virtual expr_t getBlockEquationRenormalizedExpr(int block_number, int equation_number) const = 0;
|
||||
//! Return the original number of equation equation_number belonging to the block block_number
|
||||
virtual int getBlockEquationID(int block_number, int equation_number) const = 0;
|
||||
//! Return the original number of variable variable_number belonging to the block block_number
|
||||
virtual int getBlockVariableID(int block_number, int variable_number) const = 0;
|
||||
//! Return the original number of the exogenous variable varexo_number belonging to the block block_number
|
||||
virtual int getBlockVariableExoID(int block_number, int variable_number) const = 0;
|
||||
//! Return the position of equation_number in the block number belonging to the block block_number
|
||||
virtual int getBlockInitialEquationID(int block_number, int equation_number) const = 0;
|
||||
//! Return the position of variable_number in the block number belonging to the block block_number
|
||||
virtual int getBlockInitialVariableID(int block_number, int variable_number) const = 0;
|
||||
//! Return the position of variable_number in the block number belonging to the block block_number
|
||||
virtual int getBlockInitialExogenousID(int block_number, int variable_number) const = 0;
|
||||
//! Return the position of the deterministic exogenous variable_number in the block number belonging to the block block_number
|
||||
virtual int getBlockInitialDetExogenousID(int block_number, int variable_number) const = 0;
|
||||
//! Return the position of the other endogenous variable_number in the block number belonging to the block block_number
|
||||
virtual int getBlockInitialOtherEndogenousID(int block_number, int variable_number) const = 0;
|
||||
//! Initialize equation_reordered & variable_reordered
|
||||
void initializeVariablesAndEquations();
|
||||
public:
|
||||
ModelTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg);
|
||||
//! Absolute value under which a number is considered to be zero
|
||||
double cutoff;
|
||||
//! Compute the minimum feedback set
|
||||
/*! 0 : all endogenous variables are considered as feedback variables
|
||||
1 : the variables belonging to non normalized equation are considered as feedback variables
|
||||
2 : the variables belonging to a non linear equation are considered as feedback variables
|
||||
3 : the variables belonging to a non normalizable non linear equation are considered as feedback variables
|
||||
default value = 0 */
|
||||
int mfs;
|
||||
//! Declare a node as an equation of the model; also give its line number
|
||||
void addEquation(expr_t eq, int lineno);
|
||||
//! Declare a node as an equation of the model, also giving its tags
|
||||
void addEquation(expr_t eq, int lineno, const vector<pair<string, string> > &eq_tags);
|
||||
//! Declare a node as an auxiliary equation of the model, adding it at the end of the list of auxiliary equations
|
||||
void addAuxEquation(expr_t eq);
|
||||
//! Returns the number of equations in the model
|
||||
int equation_number() const;
|
||||
//! Adds a trend variable with its growth factor
|
||||
void addTrendVariables(vector<int> trend_vars, expr_t growth_factor) throw (TrendException);
|
||||
//! Adds a nonstationary variables with their (common) deflator
|
||||
void addNonstationaryVariables(vector<int> nonstationary_vars, bool log_deflator, expr_t deflator) throw (TrendException);
|
||||
//! Is a given variable non-stationary?
|
||||
bool isNonstationary(int symb_id) const;
|
||||
void set_cutoff_to_zero();
|
||||
//! Helper for writing the Jacobian elements in MATLAB and C
|
||||
/*! Writes either (i+1,j+1) or [i+j*no_eq] */
|
||||
void jacobianHelper(ostream &output, int eq_nb, int col_nb, ExprNodeOutputType output_type) const;
|
||||
//! Helper for writing the sparse Hessian or third derivatives in MATLAB and C
|
||||
/*! If order=2, writes either v2(i+1,j+1) or v2[i+j*NNZDerivatives[1]]
|
||||
If order=3, writes either v3(i+1,j+1) or v3[i+j*NNZDerivatives[2]] */
|
||||
void sparseHelper(int order, ostream &output, int row_nb, int col_nb, ExprNodeOutputType output_type) const;
|
||||
inline static std::string
|
||||
c_Equation_Type(int type)
|
||||
{
|
||||
char c_Equation_Type[4][13] =
|
||||
{
|
||||
"E_UNKNOWN ",
|
||||
"E_EVALUATE ",
|
||||
"E_EVALUATE_S",
|
||||
"E_SOLVE "
|
||||
};
|
||||
return (c_Equation_Type[type]);
|
||||
};
|
||||
|
||||
inline static std::string
|
||||
BlockType0(BlockType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case SIMULTANS:
|
||||
return ("SIMULTANEOUS TIME SEPARABLE ");
|
||||
break;
|
||||
case PROLOGUE:
|
||||
return ("PROLOGUE ");
|
||||
break;
|
||||
case EPILOGUE:
|
||||
return ("EPILOGUE ");
|
||||
break;
|
||||
case SIMULTAN:
|
||||
return ("SIMULTANEOUS TIME UNSEPARABLE");
|
||||
break;
|
||||
default:
|
||||
return ("UNKNOWN ");
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
inline static std::string
|
||||
BlockSim(int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EVALUATE_FORWARD:
|
||||
return ("EVALUATE FORWARD ");
|
||||
break;
|
||||
case EVALUATE_BACKWARD:
|
||||
return ("EVALUATE BACKWARD ");
|
||||
break;
|
||||
case SOLVE_FORWARD_SIMPLE:
|
||||
return ("SOLVE FORWARD SIMPLE ");
|
||||
break;
|
||||
case SOLVE_BACKWARD_SIMPLE:
|
||||
return ("SOLVE BACKWARD SIMPLE ");
|
||||
break;
|
||||
case SOLVE_TWO_BOUNDARIES_SIMPLE:
|
||||
return ("SOLVE TWO BOUNDARIES SIMPLE ");
|
||||
break;
|
||||
case SOLVE_FORWARD_COMPLETE:
|
||||
return ("SOLVE FORWARD COMPLETE ");
|
||||
break;
|
||||
case SOLVE_BACKWARD_COMPLETE:
|
||||
return ("SOLVE BACKWARD COMPLETE ");
|
||||
break;
|
||||
case SOLVE_TWO_BOUNDARIES_COMPLETE:
|
||||
return ("SOLVE TWO BOUNDARIES COMPLETE");
|
||||
break;
|
||||
default:
|
||||
return ("UNKNOWN ");
|
||||
break;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2012 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "NumericalConstants.hh"
|
||||
|
||||
int
|
||||
NumericalConstants::AddNonNegativeConstant(const string &iConst)
|
||||
{
|
||||
map<string, int>::const_iterator iter = numConstantsIndex.find(iConst);
|
||||
|
||||
if (iter != numConstantsIndex.end())
|
||||
return iter->second;
|
||||
|
||||
int id = (int) mNumericalConstants.size();
|
||||
mNumericalConstants.push_back(iConst);
|
||||
numConstantsIndex[iConst] = id;
|
||||
|
||||
double val = strtod(iConst.c_str(), NULL);
|
||||
|
||||
/* Note that we allow underflows (will be converted to 0) and overflows (will
|
||||
be converted to Inf), as MATLAB and Octave do. */
|
||||
|
||||
assert(val >= 0 || isnan(val)); // Check we have a positive constant or a NaN
|
||||
double_vals.push_back(val);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
string
|
||||
NumericalConstants::get(int ID) const
|
||||
{
|
||||
assert(ID >= 0 && ID < (int) mNumericalConstants.size());
|
||||
return mNumericalConstants[ID];
|
||||
}
|
||||
|
||||
double
|
||||
NumericalConstants::getDouble(int ID) const
|
||||
{
|
||||
assert(ID >= 0 && ID < (int) double_vals.size());
|
||||
return (double_vals[ID]);
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2016 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _NUMERICALCONSTANTS_HH
|
||||
#define _NUMERICALCONSTANTS_HH
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
//! Handles non-negative numerical constants
|
||||
class NumericalConstants
|
||||
{
|
||||
private:
|
||||
//! Vector of numerical constants
|
||||
vector<string> mNumericalConstants;
|
||||
//! Double values of these constants
|
||||
vector<double> double_vals;
|
||||
//! Map matching constants to their id
|
||||
map<string, int> numConstantsIndex;
|
||||
public:
|
||||
//! Adds a non-negative constant (possibly Inf or NaN) and returns its ID
|
||||
int AddNonNegativeConstant(const string &iConst);
|
||||
//! Get a constant in string form
|
||||
string get(int ID) const;
|
||||
//! Get a constant in double form
|
||||
double getDouble(int ID) const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,649 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "NumericalInitialization.hh"
|
||||
|
||||
InitParamStatement::InitParamStatement(int symb_id_arg,
|
||||
const expr_t param_value_arg,
|
||||
const SymbolTable &symbol_table_arg) :
|
||||
symb_id(symb_id_arg),
|
||||
param_value(param_value_arg),
|
||||
symbol_table(symbol_table_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
InitParamStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
|
||||
{
|
||||
if (symbol_table.getName(symb_id) == "dsge_prior_weight")
|
||||
mod_file_struct.dsge_prior_weight_initialized = true;
|
||||
}
|
||||
|
||||
void
|
||||
InitParamStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
int id = symbol_table.getTypeSpecificID(symb_id) + 1;
|
||||
output << "M_.params( " << id << " ) = ";
|
||||
param_value->writeOutput(output);
|
||||
output << ";" << endl;
|
||||
if (!minimal_workspace)
|
||||
output << symbol_table.getName(symb_id) << " = M_.params( " << id << " );" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
InitParamStatement::writeJuliaOutput(ostream &output, const string &basename)
|
||||
{
|
||||
int id = symbol_table.getTypeSpecificID(symb_id) + 1;
|
||||
output << "model_.params[ " << id << " ] = ";
|
||||
param_value->writeOutput(output);
|
||||
output << endl;
|
||||
// Do we really need this?
|
||||
// if (!minimal_workspace)
|
||||
// output << symbol_table.getName(symb_id) << " = model_.params[ " << id << " ]" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
InitParamStatement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
deriv_node_temp_terms_t tef_terms;
|
||||
output << "{\"statementName\": \"param_init\", \"name\": \"" << symbol_table.getName(symb_id) << "\", " << "\"value\": \"";
|
||||
param_value->writeJsonOutput(output, temporary_terms_t(), tef_terms);
|
||||
output << "\"}";
|
||||
}
|
||||
|
||||
void
|
||||
InitParamStatement::writeCOutput(ostream &output, const string &basename)
|
||||
{
|
||||
int id = symbol_table.getTypeSpecificID(symb_id);
|
||||
output << "params[ " << id << " ] = ";
|
||||
param_value->writeOutput(output);
|
||||
output << ";" << endl;
|
||||
output << "double " << symbol_table.getName(symb_id) << " = params[ " << id << " ];" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
InitParamStatement::fillEvalContext(eval_context_t &eval_context) const
|
||||
{
|
||||
try
|
||||
{
|
||||
eval_context[symb_id] = param_value->eval(eval_context);
|
||||
}
|
||||
catch (ExprNode::EvalException &e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
InitOrEndValStatement::InitOrEndValStatement(const init_values_t &init_values_arg,
|
||||
const SymbolTable &symbol_table_arg,
|
||||
const bool &all_values_required_arg) :
|
||||
init_values(init_values_arg),
|
||||
symbol_table(symbol_table_arg),
|
||||
all_values_required(all_values_required_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
InitOrEndValStatement::fillEvalContext(eval_context_t &eval_context) const
|
||||
{
|
||||
for (init_values_t::const_iterator it = init_values.begin();
|
||||
it != init_values.end(); it++)
|
||||
{
|
||||
try
|
||||
{
|
||||
eval_context[it->first] = (it->second)->eval(eval_context);
|
||||
}
|
||||
catch (ExprNode::EvalException &e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set<int>
|
||||
InitOrEndValStatement::getUninitializedVariables(SymbolType type)
|
||||
{
|
||||
set<int> unused;
|
||||
if (!all_values_required)
|
||||
return unused;
|
||||
|
||||
if (type == eEndogenous)
|
||||
unused = symbol_table.getEndogenous();
|
||||
else if (type == eExogenous)
|
||||
unused = symbol_table.getExogenous();
|
||||
else
|
||||
{
|
||||
cerr << "ERROR: Shouldn't arrive here." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
set<int>::iterator sit;
|
||||
for (init_values_t::const_iterator it = init_values.begin();
|
||||
it != init_values.end(); it++)
|
||||
{
|
||||
sit = unused.find(it->first);
|
||||
if (sit != unused.end())
|
||||
unused.erase(sit);
|
||||
}
|
||||
return unused;
|
||||
}
|
||||
|
||||
void
|
||||
InitOrEndValStatement::writeInitValues(ostream &output) const
|
||||
{
|
||||
for (init_values_t::const_iterator it = init_values.begin();
|
||||
it != init_values.end(); it++)
|
||||
{
|
||||
const int symb_id = it->first;
|
||||
const expr_t expression = it->second;
|
||||
|
||||
SymbolType type = symbol_table.getType(symb_id);
|
||||
int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
|
||||
|
||||
if (type == eEndogenous)
|
||||
output << "oo_.steady_state";
|
||||
else if (type == eExogenous)
|
||||
output << "oo_.exo_steady_state";
|
||||
else if (type == eExogenousDet)
|
||||
output << "oo_.exo_det_steady_state";
|
||||
|
||||
output << "( " << tsid << " ) = ";
|
||||
expression->writeOutput(output);
|
||||
output << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
InitOrEndValStatement::writeJsonInitValues(ostream &output) const
|
||||
{
|
||||
deriv_node_temp_terms_t tef_terms;
|
||||
for (init_values_t::const_iterator it = init_values.begin();
|
||||
it != init_values.end(); it++)
|
||||
{
|
||||
if (it != init_values.begin())
|
||||
output << ", ";
|
||||
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\", " << "\"value\": \"";
|
||||
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
|
||||
output << "\"}";
|
||||
}
|
||||
}
|
||||
|
||||
InitValStatement::InitValStatement(const init_values_t &init_values_arg,
|
||||
const SymbolTable &symbol_table_arg,
|
||||
const bool &all_values_required_arg) :
|
||||
InitOrEndValStatement(init_values_arg, symbol_table_arg, all_values_required_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
InitValStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
|
||||
{
|
||||
set<int> exogs = getUninitializedVariables(eExogenous);
|
||||
set<int> endogs = getUninitializedVariables(eEndogenous);
|
||||
|
||||
if (endogs.size() > 0)
|
||||
{
|
||||
cerr << "ERROR: You have not set the following endogenous variables in initval:";
|
||||
for (set<int>::const_iterator it = endogs.begin(); it != endogs.end(); it++)
|
||||
cerr << " " << symbol_table.getName(*it);
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
if (exogs.size() > 0)
|
||||
{
|
||||
cerr << "ERROR: You have not set the following exogenous variables in initval:";
|
||||
for (set<int>::const_iterator it = exogs.begin(); it != exogs.end(); it++)
|
||||
cerr << " " << symbol_table.getName(*it);
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
if (endogs.size() > 0 || exogs.size() > 0)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void
|
||||
InitValStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
output << "%" << endl
|
||||
<< "% INITVAL instructions" << endl
|
||||
<< "%" << endl;
|
||||
// Writing initval block to set initial values for variables
|
||||
output << "options_.initval_file = 0;" << endl;
|
||||
|
||||
writeInitValues(output);
|
||||
}
|
||||
|
||||
void
|
||||
InitValStatement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
output << "{\"statementName\": \"init_val\", \"vals\": [";
|
||||
writeJsonInitValues(output);
|
||||
output << "]}";
|
||||
}
|
||||
|
||||
void
|
||||
InitValStatement::writeOutputPostInit(ostream &output) const
|
||||
{
|
||||
output << "if M_.exo_nbr > 0" << endl
|
||||
<< "\too_.exo_simul = ones(M_.maximum_lag,1)*oo_.exo_steady_state';" << endl
|
||||
<<"end" << endl
|
||||
<< "if M_.exo_det_nbr > 0" << endl
|
||||
<< "\too_.exo_det_simul = ones(M_.maximum_lag,1)*oo_.exo_det_steady_state';" << endl
|
||||
<<"end" << endl;
|
||||
}
|
||||
|
||||
EndValStatement::EndValStatement(const init_values_t &init_values_arg,
|
||||
const SymbolTable &symbol_table_arg,
|
||||
const bool &all_values_required_arg) :
|
||||
InitOrEndValStatement(init_values_arg, symbol_table_arg, all_values_required_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
EndValStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
|
||||
{
|
||||
set<int> exogs = getUninitializedVariables(eExogenous);
|
||||
set<int> endogs = getUninitializedVariables(eEndogenous);
|
||||
|
||||
if (endogs.size() > 0)
|
||||
{
|
||||
cerr << "ERROR: You have not set the following endogenous variables in endval:";
|
||||
for (set<int>::const_iterator it = endogs.begin(); it != endogs.end(); it++)
|
||||
cerr << " " << symbol_table.getName(*it);
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
if (exogs.size() > 0)
|
||||
{
|
||||
cerr << "ERROR: You have not set the following exogenous variables in endval:";
|
||||
for (set<int>::const_iterator it = exogs.begin(); it != exogs.end(); it++)
|
||||
cerr << " " << symbol_table.getName(*it);
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
if (endogs.size() > 0 || exogs.size() > 0)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void
|
||||
EndValStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
output << "%" << endl
|
||||
<< "% ENDVAL instructions" << endl
|
||||
<< "%" << endl;
|
||||
// Writing endval block to set terminal values for variables
|
||||
output << "ys0_= oo_.steady_state;" << endl
|
||||
<< "ex0_ = oo_.exo_steady_state;" << endl;
|
||||
|
||||
writeInitValues(output);
|
||||
}
|
||||
|
||||
void
|
||||
EndValStatement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
output << "{\"statementName\": \"end_val\", \"vals\": [";
|
||||
writeJsonInitValues(output);
|
||||
output << "]}";
|
||||
}
|
||||
|
||||
HistValStatement::HistValStatement(const hist_values_t &hist_values_arg,
|
||||
const hist_vals_wrong_lag_t hist_vals_wrong_lag_arg,
|
||||
const SymbolTable &symbol_table_arg,
|
||||
const bool &all_values_required_arg) :
|
||||
hist_values(hist_values_arg),
|
||||
hist_vals_wrong_lag(hist_vals_wrong_lag_arg),
|
||||
symbol_table(symbol_table_arg),
|
||||
all_values_required(all_values_required_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
HistValStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
|
||||
{
|
||||
if (all_values_required)
|
||||
{
|
||||
set<int> unused_endo = symbol_table.getEndogenous();
|
||||
set<int> unused_exo = symbol_table.getExogenous();
|
||||
|
||||
set<int>::iterator sit;
|
||||
for (hist_values_t::const_iterator it = hist_values.begin();
|
||||
it != hist_values.end(); it++)
|
||||
{
|
||||
sit = unused_endo.find(it->first.first);
|
||||
if (sit != unused_endo.end())
|
||||
unused_endo.erase(sit);
|
||||
|
||||
sit = unused_exo.find(it->first.first);
|
||||
if (sit != unused_exo.end())
|
||||
unused_exo.erase(sit);
|
||||
}
|
||||
|
||||
if (unused_endo.size() > 0)
|
||||
{
|
||||
cerr << "ERROR: You have not set the following endogenous variables in histval:";
|
||||
for (set<int>::const_iterator it = unused_endo.begin(); it != unused_endo.end(); it++)
|
||||
cerr << " " << symbol_table.getName(*it);
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
if (unused_exo.size() > 0)
|
||||
{
|
||||
cerr << "ERROR: You have not set the following exogenous variables in endval:";
|
||||
for (set<int>::const_iterator it = unused_exo.begin(); it != unused_exo.end(); it++)
|
||||
cerr << " " << symbol_table.getName(*it);
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
if (unused_endo.size() > 0 || unused_exo.size() > 0)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
mod_file_struct.hist_vals_wrong_lag = hist_vals_wrong_lag;
|
||||
}
|
||||
|
||||
void
|
||||
HistValStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
output << "%" << endl
|
||||
<< "% HISTVAL instructions" << endl
|
||||
<< "%" << endl
|
||||
<< "M_.endo_histval = zeros(M_.endo_nbr,M_.maximum_lag);" << endl
|
||||
<< "M_.exo_histval = zeros(M_.exo_nbr,M_.maximum_lag);" << endl
|
||||
<< "M_.exo_det_histval = zeros(M_.exo_det_nbr,M_.maximum_lag);" << endl;
|
||||
|
||||
for (hist_values_t::const_iterator it = hist_values.begin();
|
||||
it != hist_values.end(); it++)
|
||||
{
|
||||
int symb_id = it->first.first;
|
||||
int lag = it->first.second;
|
||||
const expr_t expression = it->second;
|
||||
|
||||
SymbolType type = symbol_table.getType(symb_id);
|
||||
|
||||
// For a lag greater than 1 on endo, or for any exo, lookup for auxiliary variable
|
||||
if ((type == eEndogenous && lag < 0) || type == eExogenous)
|
||||
{
|
||||
try
|
||||
{
|
||||
// This function call must remain the 1st statement in this block
|
||||
symb_id = symbol_table.searchAuxiliaryVars(symb_id, lag);
|
||||
lag = 0;
|
||||
type = eEndogenous;
|
||||
}
|
||||
catch (SymbolTable::SearchFailedException &e)
|
||||
{
|
||||
if (type == eEndogenous)
|
||||
{
|
||||
cerr << "HISTVAL: internal error of Dynare, please contact the developers";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// We don't fail for exogenous, because they are not replaced by
|
||||
// auxiliary variables in deterministic mode.
|
||||
}
|
||||
}
|
||||
|
||||
int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
|
||||
|
||||
if (type == eEndogenous)
|
||||
output << "M_.endo_histval( " << tsid << ", M_.maximum_lag + " << lag << ") = ";
|
||||
else if (type == eExogenous)
|
||||
output << "M_.exo_histval( " << tsid << ", M_.maximum_lag + " << lag << ") = ";
|
||||
else if (type == eExogenousDet)
|
||||
output << "M_.exo_det_histval( " << tsid << ", M_.maximum_lag + " << lag << ") = ";
|
||||
|
||||
expression->writeOutput(output);
|
||||
output << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HistValStatement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
deriv_node_temp_terms_t tef_terms;
|
||||
output << "{\"statementName\": \"hist_val\", \"vals\": [";
|
||||
for (hist_values_t::const_iterator it = hist_values.begin();
|
||||
it != hist_values.end(); it++)
|
||||
{
|
||||
if (it != hist_values.begin())
|
||||
output << ", ";
|
||||
output << "{ \"name\": \"" << symbol_table.getName(it->first.first) << "\""
|
||||
<< ", \"lag\": " << it->first.second
|
||||
<< ", \"value\": \"";
|
||||
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
|
||||
output << "\"}";
|
||||
}
|
||||
output << "]}";
|
||||
}
|
||||
|
||||
InitvalFileStatement::InitvalFileStatement(const string &filename_arg) :
|
||||
filename(filename_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
InitvalFileStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
output << "%" << endl
|
||||
<< "% INITVAL_FILE statement" << endl
|
||||
<< "%" << endl
|
||||
<< "options_.initval_file = 1;" << endl
|
||||
<< "initvalf('" << filename << "');" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
InitvalFileStatement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
output << "{\"statementName\": \"init_val_file\""
|
||||
<< ", \"filename\": \"" << filename << "\""
|
||||
<< "}";
|
||||
}
|
||||
|
||||
HistvalFileStatement::HistvalFileStatement(const string &filename_arg) :
|
||||
filename(filename_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
HistvalFileStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
output << "histvalf('" << filename << "');" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
HistvalFileStatement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
output << "{\"statementName\": \"hist_val_file\""
|
||||
<< ", \"filename\": \"" << filename << "\""
|
||||
<< "}";
|
||||
}
|
||||
|
||||
HomotopyStatement::HomotopyStatement(const homotopy_values_t &homotopy_values_arg,
|
||||
const SymbolTable &symbol_table_arg) :
|
||||
homotopy_values(homotopy_values_arg),
|
||||
symbol_table(symbol_table_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
HomotopyStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
output << "%" << endl
|
||||
<< "% HOMOTOPY_SETUP instructions" << endl
|
||||
<< "%" << endl
|
||||
<< "options_.homotopy_values = [];" << endl;
|
||||
|
||||
for (homotopy_values_t::const_iterator it = homotopy_values.begin();
|
||||
it != homotopy_values.end(); it++)
|
||||
{
|
||||
const int &symb_id = it->first;
|
||||
const expr_t expression1 = it->second.first;
|
||||
const expr_t expression2 = it->second.second;
|
||||
|
||||
const SymbolType type = symbol_table.getType(symb_id);
|
||||
const int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
|
||||
|
||||
output << "options_.homotopy_values = vertcat(options_.homotopy_values, [ " << type << ", " << tsid << ", ";
|
||||
if (expression1 != NULL)
|
||||
expression1->writeOutput(output);
|
||||
else
|
||||
output << "NaN";
|
||||
output << ", ";
|
||||
expression2->writeOutput(output);
|
||||
output << "]);" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HomotopyStatement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
deriv_node_temp_terms_t tef_terms;
|
||||
output << "{\"statementName\": \"homotopy\", "
|
||||
<< "\"values\": [";
|
||||
for (homotopy_values_t::const_iterator it = homotopy_values.begin();
|
||||
it != homotopy_values.end(); it++)
|
||||
{
|
||||
if (it != homotopy_values.begin())
|
||||
output << ", ";
|
||||
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\""
|
||||
<< ", \"initial_value\": \"";
|
||||
if (it->second.first != NULL)
|
||||
it->second.first->writeJsonOutput(output, temporary_terms_t(), tef_terms);
|
||||
else
|
||||
output << "NaN";
|
||||
output << "\", \"final_value\": \"";
|
||||
it->second.second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
|
||||
output << "\"}";
|
||||
}
|
||||
output << "]"
|
||||
<< "}";
|
||||
}
|
||||
|
||||
SaveParamsAndSteadyStateStatement::SaveParamsAndSteadyStateStatement(const string &filename_arg) :
|
||||
filename(filename_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SaveParamsAndSteadyStateStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
output << "save_params_and_steady_state('" << filename << "');" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
SaveParamsAndSteadyStateStatement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
output << "{\"statementName\": \"save_params_and_steady_state\""
|
||||
<< ", \"filename\": \"" << filename << "\""
|
||||
<< "}";
|
||||
}
|
||||
|
||||
LoadParamsAndSteadyStateStatement::LoadParamsAndSteadyStateStatement(const string &filename,
|
||||
const SymbolTable &symbol_table_arg,
|
||||
WarningConsolidation &warnings) :
|
||||
symbol_table(symbol_table_arg)
|
||||
{
|
||||
cout << "Reading " << filename << "." << endl;
|
||||
|
||||
ifstream f;
|
||||
f.open(filename.c_str(), ios::in);
|
||||
if (f.fail())
|
||||
{
|
||||
cerr << "ERROR: Can't open " << filename << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
string symb_name, value;
|
||||
f >> symb_name >> value;
|
||||
if (f.eof())
|
||||
break;
|
||||
|
||||
try
|
||||
{
|
||||
int symb_id = symbol_table.getID(symb_name);
|
||||
content[symb_id] = value;
|
||||
}
|
||||
catch (SymbolTable::UnknownSymbolNameException &e)
|
||||
{
|
||||
warnings << "WARNING: Unknown symbol " << symb_name << " in " << filename << endl;
|
||||
}
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
|
||||
void
|
||||
LoadParamsAndSteadyStateStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
for (map<int, string>::const_iterator it = content.begin();
|
||||
it != content.end(); it++)
|
||||
{
|
||||
switch (symbol_table.getType(it->first))
|
||||
{
|
||||
case eParameter:
|
||||
output << "M_.params";
|
||||
break;
|
||||
case eEndogenous:
|
||||
output << "oo_.steady_state";
|
||||
break;
|
||||
case eExogenous:
|
||||
output << "oo_.exo_steady_state";
|
||||
break;
|
||||
case eExogenousDet:
|
||||
output << "oo_.exo_det_steady_state";
|
||||
break;
|
||||
default:
|
||||
cerr << "ERROR: Unsupported variable type for " << symbol_table.getName(it->first) << " in load_params_and_steady_state" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int tsid = symbol_table.getTypeSpecificID(it->first) + 1;
|
||||
output << "(" << tsid << ") = " << it->second << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LoadParamsAndSteadyStateStatement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
deriv_node_temp_terms_t tef_terms;
|
||||
output << "{\"statementName\": \"load_params_and_steady_state\""
|
||||
<< "\"values\": [";
|
||||
for (map<int, string>::const_iterator it = content.begin();
|
||||
it != content.end(); it++)
|
||||
{
|
||||
if (it != content.begin())
|
||||
output << ", ";
|
||||
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\""
|
||||
<< ", \"value\": \"" << it->second << "\"}";
|
||||
}
|
||||
output << "]"
|
||||
<< "}";
|
||||
}
|
||||
|
||||
void
|
||||
LoadParamsAndSteadyStateStatement::fillEvalContext(eval_context_t &eval_context) const
|
||||
{
|
||||
for (map<int, string>::const_iterator it = content.begin();
|
||||
it != content.end(); it++)
|
||||
eval_context[it->first] = atof(it->second.c_str());
|
||||
}
|
|
@ -1,190 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _NUMERICALINITIALIZATION_HH
|
||||
#define _NUMERICALINITIALIZATION_HH
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "SymbolTable.hh"
|
||||
#include "ExprNode.hh"
|
||||
#include "Statement.hh"
|
||||
|
||||
class InitParamStatement : public Statement
|
||||
{
|
||||
private:
|
||||
const int symb_id;
|
||||
const expr_t param_value;
|
||||
const SymbolTable &symbol_table;
|
||||
public:
|
||||
InitParamStatement(int symb_id_arg, const expr_t param_value_arg,
|
||||
const SymbolTable &symbol_table_arg);
|
||||
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJuliaOutput(ostream &output, const string &basename);
|
||||
virtual void writeCOutput(ostream &output, const string &basename);
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
//! Fill eval context with parameter value
|
||||
void fillEvalContext(eval_context_t &eval_context) const;
|
||||
};
|
||||
|
||||
class InitOrEndValStatement : public Statement
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
We use a vector instead of a map, since the order of declaration matters:
|
||||
an initialization can depend on a previously initialized variable inside the block
|
||||
*/
|
||||
typedef vector<pair<int, expr_t> > init_values_t;
|
||||
protected:
|
||||
const init_values_t init_values;
|
||||
const SymbolTable &symbol_table;
|
||||
const bool all_values_required;
|
||||
public:
|
||||
InitOrEndValStatement(const init_values_t &init_values_arg,
|
||||
const SymbolTable &symbol_table_arg,
|
||||
const bool &all_values_required_arg);
|
||||
//! Return set of unused variables by type
|
||||
set<int> getUninitializedVariables(SymbolType type);
|
||||
//! Fill eval context with variables values
|
||||
void fillEvalContext(eval_context_t &eval_context) const;
|
||||
protected:
|
||||
void writeInitValues(ostream &output) const;
|
||||
void writeJsonInitValues(ostream &output) const;
|
||||
};
|
||||
|
||||
class InitValStatement : public InitOrEndValStatement
|
||||
{
|
||||
public:
|
||||
InitValStatement(const init_values_t &init_values_arg,
|
||||
const SymbolTable &symbol_table_arg,
|
||||
const bool &all_values_required_arg);
|
||||
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
//! Writes initializations for oo_.exo_simul and oo_.exo_det_simul
|
||||
void writeOutputPostInit(ostream &output) const;
|
||||
};
|
||||
|
||||
class EndValStatement : public InitOrEndValStatement
|
||||
{
|
||||
public:
|
||||
EndValStatement(const init_values_t &init_values_arg,
|
||||
const SymbolTable &symbol_table_arg,
|
||||
const bool &all_values_required_arg);
|
||||
//! Workaround for trac ticket #35
|
||||
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
class HistValStatement : public Statement
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
Contrary to Initval and Endval, we use a map, since it is impossible to reuse
|
||||
a given initialization value in a second initialization inside the block.
|
||||
Maps pairs (symbol_id, lag) to expr_t
|
||||
*/
|
||||
typedef map<pair<int, int>, expr_t> hist_values_t;
|
||||
typedef map<int, int> hist_vals_wrong_lag_t;
|
||||
private:
|
||||
const hist_values_t hist_values;
|
||||
const hist_vals_wrong_lag_t hist_vals_wrong_lag;
|
||||
const SymbolTable &symbol_table;
|
||||
const bool all_values_required;
|
||||
public:
|
||||
HistValStatement(const hist_values_t &hist_values_arg,
|
||||
const hist_vals_wrong_lag_t hist_vals_wrong_lag_arg,
|
||||
const SymbolTable &symbol_table_arg,
|
||||
const bool &all_values_required_arg);
|
||||
//! Workaround for trac ticket #157
|
||||
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
class InitvalFileStatement : public Statement
|
||||
{
|
||||
private:
|
||||
const string filename;
|
||||
public:
|
||||
InitvalFileStatement(const string &filename_arg);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
class HistvalFileStatement : public Statement
|
||||
{
|
||||
private:
|
||||
const string filename;
|
||||
public:
|
||||
HistvalFileStatement(const string &filename_arg);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
class HomotopyStatement : public Statement
|
||||
{
|
||||
public:
|
||||
//! Stores the declarations of homotopy_setup
|
||||
/*! Order matter so we use a vector. First expr_t can be NULL if no initial value given. */
|
||||
typedef vector<pair<int, pair<expr_t, expr_t> > > homotopy_values_t;
|
||||
private:
|
||||
const homotopy_values_t homotopy_values;
|
||||
const SymbolTable &symbol_table;
|
||||
public:
|
||||
HomotopyStatement(const homotopy_values_t &homotopy_values_arg,
|
||||
const SymbolTable &symbol_table_arg);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
class SaveParamsAndSteadyStateStatement : public Statement
|
||||
{
|
||||
private:
|
||||
const string filename;
|
||||
public:
|
||||
SaveParamsAndSteadyStateStatement(const string &filename_arg);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
class LoadParamsAndSteadyStateStatement : public Statement
|
||||
{
|
||||
private:
|
||||
const SymbolTable &symbol_table;
|
||||
//! Content of the file
|
||||
/*! Maps symbol ID to numeric value (stored as string) */
|
||||
map<int, string> content;
|
||||
public:
|
||||
LoadParamsAndSteadyStateStatement(const string &filename,
|
||||
const SymbolTable &symbol_table_arg,
|
||||
WarningConsolidation &warnings);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
//! Fill eval context with parameters/variables values
|
||||
void fillEvalContext(eval_context_t &eval_context) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,842 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2018 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _PARSING_DRIVER_HH
|
||||
#define _PARSING_DRIVER_HH
|
||||
|
||||
#ifdef _MACRO_DRIVER_HH
|
||||
# error Impossible to include both ParsingDriver.hh and MacroDriver.hh
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <istream>
|
||||
#include <stack>
|
||||
|
||||
#include "ModFile.hh"
|
||||
#include "SymbolList.hh"
|
||||
|
||||
class ParsingDriver;
|
||||
#include "ExprNode.hh"
|
||||
#include "DynareBison.hh"
|
||||
|
||||
#include "ComputingTasks.hh"
|
||||
#include "Shocks.hh"
|
||||
#include "SigmaeInitialization.hh"
|
||||
#include "NumericalInitialization.hh"
|
||||
#include "DynamicModel.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Declare DynareFlexLexer class
|
||||
#ifndef __FLEX_LEXER_H
|
||||
# define yyFlexLexer DynareFlexLexer
|
||||
# include <FlexLexer.h>
|
||||
# undef yyFlexLexer
|
||||
#endif
|
||||
|
||||
//! The lexer class
|
||||
/*! Actually it was necessary to subclass the DynareFlexLexer class generated by Flex,
|
||||
since the prototype for DynareFlexLexer::yylex() was not convenient.
|
||||
*/
|
||||
class DynareFlex : public DynareFlexLexer
|
||||
{
|
||||
public:
|
||||
DynareFlex(istream *in = 0, ostream *out = 0);
|
||||
|
||||
//! The main lexing function
|
||||
Dynare::parser::token_type lex(Dynare::parser::semantic_type *yylval,
|
||||
Dynare::parser::location_type *yylloc,
|
||||
ParsingDriver &driver);
|
||||
|
||||
//! The filename being parsed
|
||||
/*! The bison parser locations (begin and end) contain a pointer to that string */
|
||||
string filename;
|
||||
|
||||
//! Increment the location counter given a token
|
||||
void location_increment(Dynare::parser::location_type *yylloc, const char *yytext);
|
||||
|
||||
//! Count parens in dates statement
|
||||
int dates_parens_nb;
|
||||
};
|
||||
|
||||
//! Drives the scanning and parsing of the .mod file, and constructs its abstract representation
|
||||
/*! It is built along the guidelines given in Bison 2.3 manual. */
|
||||
class ParsingDriver
|
||||
{
|
||||
private:
|
||||
//! Checks that a given symbol exists, and stops with an error message if it doesn't
|
||||
void check_symbol_existence(const string &name);
|
||||
|
||||
//! Checks that a given symbol exists and is a parameter, and stops with an error message if it isn't
|
||||
void check_symbol_is_parameter(string *name);
|
||||
|
||||
//! Checks that a given symbol was assigned within a Statement
|
||||
void check_symbol_is_statement_variable(string *name);
|
||||
|
||||
//! Checks that a given symbol exists and is a endogenous or exogenous, and stops with an error message if it isn't
|
||||
void check_symbol_is_endogenous_or_exogenous(string *name);
|
||||
|
||||
//! Checks that a given symbol exists and is a exogenous, and stops with an error message if it isn't
|
||||
void check_symbol_is_exogenous(string *name);
|
||||
|
||||
//! Checks for symbol existence in model block. If it doesn't exist, an error message is stored to be printed at
|
||||
//! the end of the model block
|
||||
void check_symbol_existence_in_model_block(const string &name);
|
||||
|
||||
//! Helper to add a symbol declaration
|
||||
void declare_symbol(const string *name, SymbolType type, const string *tex_name, const vector<pair<string *, string *> *> *partition_value);
|
||||
|
||||
//! Creates option "optim_opt" in OptionsList if it doesn't exist, else add a comma, and adds the option name
|
||||
void optim_options_helper(const string &name);
|
||||
void sampling_options_helper(const string &name);
|
||||
|
||||
//! Stores temporary symbol table
|
||||
SymbolList symbol_list;
|
||||
|
||||
//! The data tree in which to add expressions currently parsed
|
||||
DataTree *data_tree;
|
||||
|
||||
//! The model tree in which to add expressions currently parsed
|
||||
/*! It is only a dynamic cast of data_tree pointer, and is therefore null if data_tree is not a ModelTree instance */
|
||||
ModelTree *model_tree;
|
||||
|
||||
//! The dynamic model tree in which to add expressions currently parsed
|
||||
/*! It is only a dynamic cast of data_tree pointer, and is therefore null if data_tree is not a DynamicModel instance */
|
||||
DynamicModel *dynamic_model;
|
||||
|
||||
//! Sets data_tree and model_tree pointers
|
||||
void set_current_data_tree(DataTree *data_tree_arg);
|
||||
|
||||
//! Stores options lists
|
||||
OptionsList options_list;
|
||||
//! Temporary storage for trend elements
|
||||
ObservationTrendsStatement::trend_elements_t trend_elements;
|
||||
//! Temporary storage for filename list of ModelComparison (contains weights)
|
||||
ModelComparisonStatement::filename_list_t filename_list;
|
||||
//! Temporary storage for list of EstimationParams (from estimated_params* statements)
|
||||
vector<EstimationParams> estim_params_list;
|
||||
//! Temporary storage for list of OsrParams (from osr_params_block statements)
|
||||
vector<OsrParams> osr_params_list;
|
||||
//! Temporary storage of variances from optim_weights
|
||||
OptimWeightsStatement::var_weights_t var_weights;
|
||||
//! Temporary storage of covariances from optim_weights
|
||||
OptimWeightsStatement::covar_weights_t covar_weights;
|
||||
//! Temporary storage for deterministic shocks
|
||||
ShocksStatement::det_shocks_t det_shocks;
|
||||
//! Temporary storage for periods of deterministic shocks
|
||||
vector<pair<int, int> > det_shocks_periods;
|
||||
//! Temporary storage for values of deterministic shocks
|
||||
vector<expr_t> det_shocks_values;
|
||||
//! Temporary storage for variances of shocks
|
||||
ShocksStatement::var_and_std_shocks_t var_shocks;
|
||||
//! Temporary storage for standard errors of shocks
|
||||
ShocksStatement::var_and_std_shocks_t std_shocks;
|
||||
//! Temporary storage for covariances of shocks
|
||||
ShocksStatement::covar_and_corr_shocks_t covar_shocks;
|
||||
//! Temporary storage for correlations of shocks
|
||||
ShocksStatement::covar_and_corr_shocks_t corr_shocks;
|
||||
//! Temporary storage for Sigma_e rows
|
||||
SigmaeStatement::row_t sigmae_row;
|
||||
//! Temporary storage for Sigma_e matrix
|
||||
SigmaeStatement::matrix_t sigmae_matrix;
|
||||
//! Temporary storage for initval/endval blocks
|
||||
InitOrEndValStatement::init_values_t init_values;
|
||||
//! Temporary storage for histval blocks
|
||||
HistValStatement::hist_values_t hist_values;
|
||||
//! Temporary storage for histval blocks
|
||||
HistValStatement::hist_vals_wrong_lag_t hist_vals_wrong_lag;
|
||||
//! Temporary storage for homotopy_setup blocks
|
||||
HomotopyStatement::homotopy_values_t homotopy_values;
|
||||
//! Temporary storage for moment_calibration
|
||||
MomentCalibration::constraints_t moment_calibration_constraints;
|
||||
//! Temporary storage for irf_calibration
|
||||
IrfCalibration::constraints_t irf_calibration_constraints;
|
||||
//! Temporary storage for ramsey_constraints
|
||||
RamseyConstraintsStatement::constraints_t ramsey_constraints;
|
||||
//! Temporary storage for svar_identification blocks
|
||||
SvarIdentificationStatement::svar_identification_restrictions_t svar_ident_restrictions;
|
||||
//! Temporary storage for mapping the equation number to the restrictions within an svar_identification block
|
||||
map<int, vector<int> > svar_equation_restrictions;
|
||||
//! Temporary storage for restrictions in an equation within an svar_identification block
|
||||
vector<int> svar_restriction_symbols;
|
||||
//! Temporary storage for constants exculsion within an svar_identification
|
||||
bool svar_constants_exclusion;
|
||||
//! Temporary storage for upper cholesky within an svar_identification block
|
||||
bool svar_upper_cholesky;
|
||||
//! Temporary storage for lower cholesky within an svar_identification block
|
||||
bool svar_lower_cholesky;
|
||||
//! Temporary storage for equation number for a restriction within an svar_identification block
|
||||
int svar_equation_nbr;
|
||||
//! Temporary storage for left/right handside of a restriction equation within an svar_identificaton block
|
||||
bool svar_left_handside;
|
||||
//! Temporary storage for current restriction number in svar_identification block
|
||||
map<int, int> svar_Qi_restriction_nbr;
|
||||
map<int, int> svar_Ri_restriction_nbr;
|
||||
//! Stores undeclared model variables
|
||||
set<string> undeclared_model_vars;
|
||||
//! Temporary storage for restriction type
|
||||
enum SvarRestrictionType
|
||||
{
|
||||
NOT_SET,
|
||||
Qi_TYPE,
|
||||
Ri_TYPE
|
||||
};
|
||||
SvarRestrictionType svar_restriction_type;
|
||||
//! Temporary storage for generate_irfs
|
||||
vector<string> generate_irf_names;
|
||||
vector<map<string, double> > generate_irf_elements;
|
||||
map<string, double> generate_irf_exos;
|
||||
//! Temporary storage for argument list of external function
|
||||
stack<vector<expr_t> > stack_external_function_args;
|
||||
//! Temporary storage for parameters in joint prior statement
|
||||
vector<string> joint_parameters;
|
||||
//! Temporary storage for the symb_id associated with the "name" symbol of the current external_function statement
|
||||
int current_external_function_id;
|
||||
//! Temporary storage for option list provided to external_function()
|
||||
ExternalFunctionsTable::external_function_options current_external_function_options;
|
||||
//! Temporary storage for declaring trend variables
|
||||
vector<int> declared_trend_vars;
|
||||
//! Temporary storage for declaring nonstationary variables
|
||||
vector<int> declared_nonstationary_vars;
|
||||
//! Temporary storage for a variance declared in the prior statement
|
||||
expr_t prior_variance;
|
||||
SubsamplesStatement::subsample_declaration_map_t subsample_declaration_map;
|
||||
//! Temporary storage for subsample statement: map<pair<var_name1, var_name2>>, subsample_declaration_map >
|
||||
typedef map<pair<string, string >, SubsamplesStatement::subsample_declaration_map_t > subsample_declarations_t;
|
||||
subsample_declarations_t subsample_declarations;
|
||||
//! Temporary storage for shock_groups
|
||||
vector<string> shock_group;
|
||||
vector<ShockGroupsStatement::Group> shock_groups;
|
||||
//! Temporary storage for ramsey policy. Workaround for issue #1355
|
||||
vector<string> ramsey_policy_list;
|
||||
//! reset the values for temporary storage
|
||||
void reset_current_external_function_options();
|
||||
//! Adds a model lagged variable to ModelTree and VariableTable
|
||||
expr_t add_model_variable(int symb_id, int lag);
|
||||
//! For parsing the graph_format option
|
||||
SymbolList graph_formats;
|
||||
//! Temporary storage for equation tags
|
||||
vector<pair<string, string> > eq_tags;
|
||||
|
||||
//! Map Var name to variables
|
||||
map<string, vector<string> > var_map;
|
||||
|
||||
//! The mod file representation constructed by this ParsingDriver
|
||||
ModFile *mod_file;
|
||||
|
||||
WarningConsolidation &warnings;
|
||||
|
||||
bool nostrict;
|
||||
|
||||
bool model_error_encountered;
|
||||
|
||||
ostringstream model_errors;
|
||||
|
||||
//! Used by VAR restrictions
|
||||
void clear_VAR_storage();
|
||||
|
||||
//! Used by pac_expectation
|
||||
string pac_expectation_model_name, pac_expectation_var_model_name, pac_expectation_discount, pac_expectation_growth;
|
||||
|
||||
public:
|
||||
ParsingDriver(WarningConsolidation &warnings_arg, bool nostrict_arg) : warnings(warnings_arg), nostrict(nostrict_arg), model_error_encountered(false)
|
||||
{
|
||||
};
|
||||
|
||||
//! Starts parsing, and constructs the MOD file representation
|
||||
/*! The returned pointer should be deleted after use */
|
||||
ModFile *parse(istream &in, bool debug);
|
||||
|
||||
//! Reference to the lexer
|
||||
class DynareFlex *lexer;
|
||||
|
||||
//! Copy of parsing location, maintained by YYLLOC_DEFAULT macro in DynareBison.yy
|
||||
Dynare::parser::location_type location;
|
||||
|
||||
//! Estimation parameters
|
||||
EstimationParams estim_params;
|
||||
|
||||
//! OSR parameters
|
||||
OsrParams osr_params;
|
||||
|
||||
//! Temporary storage for the prior shape
|
||||
PriorDistributions prior_shape;
|
||||
|
||||
//! VAR restrictions
|
||||
//! > exclusion restrictions
|
||||
map<int, SymbolList> exclusion_restriction;
|
||||
map<int, map<int, SymbolList> > exclusion_restrictions;
|
||||
//! > equation and crossequation restrictions
|
||||
pair<int, pair<int, int> > var_restriction_coeff;
|
||||
typedef pair<pair<int, pair<int, int> >, expr_t> var_restriction_eq_crosseq_t;
|
||||
vector<var_restriction_eq_crosseq_t> var_restriction_eq_or_crosseq;
|
||||
pair<pair<var_restriction_eq_crosseq_t, var_restriction_eq_crosseq_t>, double> var_restriction_equation_or_crossequation;
|
||||
map<int, pair<pair<var_restriction_eq_crosseq_t, var_restriction_eq_crosseq_t>, double> > equation_restrictions;
|
||||
vector<pair<pair<var_restriction_eq_crosseq_t, var_restriction_eq_crosseq_t>, double> > crossequation_restrictions;
|
||||
//! > covariance restrictions
|
||||
map<pair<int, int>, double> covariance_number_restriction;
|
||||
map<pair<int, int>, pair<int, int> > covariance_pair_restriction;
|
||||
|
||||
//! Error handler with explicit location
|
||||
void error(const Dynare::parser::location_type &l, const string &m) __attribute__ ((noreturn));
|
||||
//! Error handler using saved location
|
||||
void error(const string &m) __attribute__ ((noreturn));
|
||||
//! Warning handler using saved location
|
||||
void warning(const string &m);
|
||||
|
||||
//! Error handler with explicit location (used in model block, accumulating error messages to be printed later)
|
||||
void model_error(const string &m);
|
||||
|
||||
//! Code shared between model_error() and error()
|
||||
void create_error_string(const Dynare::parser::location_type &l, const string &m, ostream &stream);
|
||||
|
||||
//! Check if a given symbol exists in the parsing context, and is not a mod file local variable
|
||||
bool symbol_exists_and_is_not_modfile_local_or_external_function(const char *s);
|
||||
//! Sets mode of ModelTree class to use C output
|
||||
void use_dll();
|
||||
//! the modelis block decomposed
|
||||
void block();
|
||||
//! the model is stored in a binary file
|
||||
void byte_code();
|
||||
//! the static model is not computed
|
||||
void no_static();
|
||||
//! the differentiate_forward_vars option is enabled (for all vars)
|
||||
void differentiate_forward_vars_all();
|
||||
//! the differentiate_forward_vars option is enabled (for a subset of vars)
|
||||
void differentiate_forward_vars_some();
|
||||
//! cutoff option of model block
|
||||
void cutoff(string *value);
|
||||
//! mfs option of model block
|
||||
void mfs(string *value);
|
||||
//! Sets the FILENAME for the initial value in initval
|
||||
void initval_file(string *filename);
|
||||
//! Declares an endogenous variable
|
||||
void declare_endogenous(string *name, string *tex_name = NULL, vector<pair<string *, string *> *> *partition_value = NULL);
|
||||
//! Declares an exogenous variable
|
||||
void declare_exogenous(string *name, string *tex_name = NULL, vector<pair<string *, string *> *> *partition_value = NULL);
|
||||
//! Declares an exogenous deterministic variable
|
||||
void declare_exogenous_det(string *name, string *tex_name = NULL, vector<pair<string *, string *> *> *partition_value = NULL);
|
||||
//! Declares a parameter
|
||||
void declare_parameter(string *name, string *tex_name = NULL, vector<pair<string *, string *> *> *partition_value = NULL);
|
||||
//! Declares a VAR variable and adds to symbol_list
|
||||
void declare_var_endogenous(string *name);
|
||||
//! Declares a model local variable
|
||||
void declare_model_local_variable(string *name, string *tex_name = NULL);
|
||||
//! Declares a statement local variable
|
||||
void declare_statement_local_variable(string *name);
|
||||
//! Completes a subsample statement
|
||||
void set_subsamples(string *name1, string *name2);
|
||||
//! Declares a subsample, assigning the value to name
|
||||
void set_subsample_name_equal_to_date_range(string *name, string *date1, string *date2);
|
||||
//! Checks that a subsample statement (and given name) were provided for the pair name1 & name2
|
||||
void check_subsample_declaration_exists(string *name1, string *subsample_name);
|
||||
void check_subsample_declaration_exists(string *name1, string *name2, string *subsample_name);
|
||||
//! Copies the set of subsamples from_name to_name
|
||||
void copy_subsamples(string *to_name1, string *to_name2, string *from_name1, string *from_name2);
|
||||
//! Declares declare_optimal_policy_discount_factor as a parameter and initializes it to exprnode
|
||||
void declare_optimal_policy_discount_factor_parameter(expr_t exprnode);
|
||||
//! Adds a predetermined_variable
|
||||
void add_predetermined_variable(string *name);
|
||||
//! Declares and initializes a local parameter
|
||||
void declare_and_init_model_local_variable(string *name, expr_t rhs);
|
||||
//! Changes type of a symbol
|
||||
void change_type(SymbolType new_type, vector<string *> *var_list);
|
||||
//! Adds a list of tags for the current equation
|
||||
void add_equation_tags(string *key, string *value);
|
||||
//! Adds a non-negative constant to DataTree
|
||||
expr_t add_non_negative_constant(string *constant);
|
||||
//! Adds a NaN constant to DataTree
|
||||
expr_t add_nan_constant();
|
||||
//! Adds an Inf constant to DataTree
|
||||
expr_t add_inf_constant();
|
||||
//! Adds a model variable to ModelTree and VariableTable
|
||||
expr_t add_model_variable(string *name);
|
||||
//! Adds an Expression's variable
|
||||
expr_t add_expression_variable(string *name);
|
||||
//! Adds a "periods" statement
|
||||
void periods(string *periods);
|
||||
//! Adds a "dsample" statement
|
||||
void dsample(string *arg1);
|
||||
//! Adds a "dsample" statement
|
||||
void dsample(string *arg1, string *arg2);
|
||||
//! Writes parameter intitialisation expression
|
||||
void init_param(string *name, expr_t rhs);
|
||||
//! Writes an initval block
|
||||
void init_val(string *name, expr_t rhs);
|
||||
//! Writes an histval block
|
||||
void hist_val(string *name, string *lag, expr_t rhs);
|
||||
//! Adds an entry in a homotopy_setup block
|
||||
/*! Second argument "val1" can be NULL if no initial value provided */
|
||||
void homotopy_val(string *name, expr_t val1, expr_t val2);
|
||||
//! Writes end of an initval block
|
||||
void end_initval(bool all_values_required);
|
||||
//! Writes end of an endval block
|
||||
void end_endval(bool all_values_required);
|
||||
//! Writes end of an histval block
|
||||
void end_histval(bool all_values_required);
|
||||
//! Writes end of an homotopy_setup block
|
||||
void end_homotopy();
|
||||
//! Begin a model block
|
||||
void begin_model();
|
||||
//! End a model block, printing errors that were encountered in parsing
|
||||
void end_model();
|
||||
//! Writes a shocks statement
|
||||
void end_shocks(bool overwrite);
|
||||
//! Writes a mshocks statement
|
||||
void end_mshocks(bool overwrite);
|
||||
//! Adds a deterministic shock or a path element inside a conditional_forecast_paths block
|
||||
void add_det_shock(string *var, bool conditional_forecast);
|
||||
//! Adds a std error chock
|
||||
void add_stderr_shock(string *var, expr_t value);
|
||||
//! Adds a variance chock
|
||||
void add_var_shock(string *var, expr_t value);
|
||||
//! Adds a covariance chock
|
||||
void add_covar_shock(string *var1, string *var2, expr_t value);
|
||||
//! Adds a correlated chock
|
||||
void add_correl_shock(string *var1, string *var2, expr_t value);
|
||||
//! Adds a shock period range
|
||||
void add_period(string *p1, string *p2);
|
||||
//! Adds a shock period
|
||||
void add_period(string *p1);
|
||||
//! Adds a deterministic shock value
|
||||
void add_value(expr_t value);
|
||||
//! Adds a deterministic shock value
|
||||
/*! \param v a string containing a (possibly negative) numeric constant */
|
||||
void add_value(string *v);
|
||||
//! Writes a Sigma_e block
|
||||
void do_sigma_e();
|
||||
//! Ends row of Sigma_e block
|
||||
void end_of_row();
|
||||
//! Adds a constant element to current row of Sigma_e
|
||||
void add_to_row_const(string *v);
|
||||
//! Adds an expression element to current row of Sigma_e
|
||||
void add_to_row(expr_t v);
|
||||
//! Write a steady command
|
||||
void steady();
|
||||
//! Sets an option to a numerical value
|
||||
void option_num(const string &name_option, string *opt);
|
||||
//! Sets an option to a numerical value
|
||||
void option_num(const string &name_option, const string &opt);
|
||||
//! Sets an option to a numerical value
|
||||
void option_num(const string &name_option, string *opt1, string *opt2);
|
||||
//! Sets an option to a string value
|
||||
void option_str(const string &name_option, string *opt);
|
||||
//! Sets an option to a string value
|
||||
void option_str(const string &name_option, const string &opt);
|
||||
//! Sets an option to a date value
|
||||
void option_date(const string &name_option, string *opt);
|
||||
//! Sets an option to a date value
|
||||
void option_date(const string &name_option, const string &opt);
|
||||
//! Sets an option to a list of symbols (used in conjunction with add_in_symbol_list())
|
||||
void option_symbol_list(const string &name_option);
|
||||
//! Sets an option to a vector of integers
|
||||
void option_vec_int(const string &name_option, const vector<int> *opt);
|
||||
//! Sets an option to a vector of strings
|
||||
void option_vec_str(const string &name_option, const vector<string> *opt);
|
||||
//! Indicates that the model is linear
|
||||
void linear();
|
||||
//! Adds a variable to temporary symbol list
|
||||
void add_in_symbol_list(string *tmp_var);
|
||||
//! Writes a rplot() command
|
||||
void rplot();
|
||||
//! Writes a stock_simul command
|
||||
void stoch_simul();
|
||||
//! Writes a var (vector autoregression) command
|
||||
void var_model();
|
||||
//! Writes a simul command
|
||||
void simul();
|
||||
//! Writes check command
|
||||
void check();
|
||||
//! Writes model_info command
|
||||
void model_info();
|
||||
//! Writes estimated params command
|
||||
void estimated_params();
|
||||
//! Writes estimated params init command
|
||||
void estimated_params_init(bool use_calibration = false);
|
||||
//! Writes estimated params bound command
|
||||
void estimated_params_bounds();
|
||||
//! Adds a declaration for a user-defined external function
|
||||
void external_function();
|
||||
//! Sets an external_function option to a string value
|
||||
void external_function_option(const string &name_option, string *opt);
|
||||
//! Sets an external_function option to a string value
|
||||
void external_function_option(const string &name_option, const string &opt);
|
||||
//! Add a line in an estimated params block
|
||||
void add_estimated_params_element();
|
||||
//! Writes osr params bounds command
|
||||
void osr_params_bounds();
|
||||
//! Add a line in an osr params block
|
||||
void add_osr_params_element();
|
||||
//! Sets the frequency of the data
|
||||
void set_time(string *arg);
|
||||
//! Estimation Data
|
||||
void estimation_data();
|
||||
//! Sets the prior for a parameter
|
||||
void set_prior(string *arg1, string *arg2);
|
||||
//! Sets the joint prior for a set of parameters
|
||||
void set_joint_prior(vector<string *> *symbol_vec);
|
||||
//! Adds a parameters to the list of joint parameters
|
||||
void add_joint_parameter(string *name);
|
||||
//! Adds the variance option to its temporary holding place
|
||||
void set_prior_variance(expr_t variance = NULL);
|
||||
//! Copies the prior from_name to_name
|
||||
void copy_prior(string *to_declaration_type, string *to_name1, string *to_name2, string *to_subsample_name,
|
||||
string *from_declaration_type, string *from_name1, string *from_name2, string *from_subsample_name);
|
||||
//! Sets the options for a parameter
|
||||
void set_options(string *arg1, string *arg2);
|
||||
//! Copies the options from_name to_name
|
||||
void copy_options(string *to_declaration_type, string *to_name1, string *to_name2, string *to_subsample_name,
|
||||
string *from_declaration_type, string *from_name1, string *from_name2, string *from_subsample_name);
|
||||
//! Sets the prior for estimated std dev
|
||||
void set_std_prior(string *arg1, string *arg2);
|
||||
//! Sets the options for estimated std dev
|
||||
void set_std_options(string *arg1, string *arg2);
|
||||
//! Sets the prior for estimated correlation
|
||||
void set_corr_prior(string *arg1, string *arg2, string *arg3);
|
||||
//! Sets the options for estimated correlation
|
||||
void set_corr_options(string *arg1, string *arg2, string *arg3);
|
||||
//! Runs estimation process
|
||||
void run_estimation();
|
||||
//! Runs dynare_sensitivy()
|
||||
void dynare_sensitivity();
|
||||
//! Adds an optimization option (string value)
|
||||
void optim_options_string(string *name, string *value);
|
||||
//! Adds an optimization option (numeric value)
|
||||
void optim_options_num(string *name, string *value);
|
||||
//! Adds an sampling option (string value)
|
||||
void sampling_options_string(string *name, string *value);
|
||||
//! Adds an sampling option (numeric value)
|
||||
void sampling_options_num(string *name, string *value);
|
||||
//! Check that no observed variable has yet be defined
|
||||
void check_varobs();
|
||||
//! Add a new observed variable
|
||||
void add_varobs(string *name);
|
||||
//! Check that no observed exogenous variable has yet be defined
|
||||
void check_varexobs();
|
||||
//! Add a new observed exogenous variable
|
||||
void add_varexobs(string *name);
|
||||
//! Svar_Identification Statement
|
||||
void begin_svar_identification();
|
||||
void end_svar_identification();
|
||||
//! Svar_Identification Statement: match list of restrictions and equation number with lag
|
||||
void combine_lag_and_restriction(string *lag);
|
||||
//! Svar_Identification Statement: match list of restrictions with equation number
|
||||
void add_restriction_in_equation(string *equation);
|
||||
//! Svar_Identification Statement: add list of restriction symbol ids
|
||||
void add_in_svar_restriction_symbols(string *name);
|
||||
//! Svar_Identification Statement: add exclusions of constants
|
||||
void add_constants_exclusion();
|
||||
//! Svar_Identification Statement: add equation number for following restriction equations
|
||||
void add_restriction_equation_nbr(string *eq_nbr);
|
||||
//! Svar_Identification Statement: record presence of equal sign
|
||||
void add_restriction_equal();
|
||||
//! Svar_Idenditification Statement: add coefficient of a linear restriction (positive value)
|
||||
void add_positive_restriction_element(expr_t value, string *variable, string *lag);
|
||||
//! Svar_Idenditification Statement: add unit coefficient of a linear restriction
|
||||
void add_positive_restriction_element(string *variable, string *lag);
|
||||
//! Svar_Idenditification Statement: add coefficient of a linear restriction (negative value)
|
||||
void add_negative_restriction_element(expr_t value, string *variable, string *lag);
|
||||
//! Svar_Idenditification Statement: add negative unit coefficient of a linear restriction
|
||||
void add_negative_restriction_element(string *variable, string *lag);
|
||||
//! Svar_Idenditification Statement: add restriction element
|
||||
void add_restriction_element(expr_t value, string *variable, string *lag);
|
||||
//! Svar_Identification Statement: check that restriction is homogenous
|
||||
void check_restriction_expression_constant(expr_t value);
|
||||
//! Svar_Identification Statement: restriction of form upper cholesky
|
||||
void add_upper_cholesky();
|
||||
//! Svar_Identification Statement: restriction of form lower cholesky
|
||||
void add_lower_cholesky();
|
||||
//! Svar_Global_Identification_Check Statement
|
||||
void add_svar_global_identification_check();
|
||||
//! generate_irfs Block
|
||||
void end_generate_irfs();
|
||||
void add_generate_irfs_element(string *name);
|
||||
void add_generate_irfs_exog_element(string *exo, string *value);
|
||||
//! Forecast Statement
|
||||
void forecast();
|
||||
void set_trends();
|
||||
void set_trend_element(string *arg1, expr_t arg2);
|
||||
void set_unit_root_vars();
|
||||
void optim_weights();
|
||||
void set_optim_weights(string *name, expr_t value);
|
||||
void set_optim_weights(string *name1, string *name2, expr_t value);
|
||||
void set_osr_params();
|
||||
void run_osr();
|
||||
void run_dynasave(string *filename);
|
||||
void run_dynatype(string *filename);
|
||||
void run_load_params_and_steady_state(string *filename);
|
||||
void run_save_params_and_steady_state(string *filename);
|
||||
void run_identification();
|
||||
void add_mc_filename(string *filename, string *prior = new string ("1"));
|
||||
void run_model_comparison();
|
||||
//! Begin a planner_objective statement
|
||||
void begin_planner_objective();
|
||||
//! End a planner objective statement
|
||||
void end_planner_objective(expr_t expr);
|
||||
//! Ramsey model statement
|
||||
void ramsey_model();
|
||||
//! Ramsey constraints statement
|
||||
void add_ramsey_constraints_statement();
|
||||
//! Ramsey less constraint
|
||||
void ramsey_constraint_add_less(const string *name, const expr_t rhs);
|
||||
//! Ramsey greater constraint
|
||||
void ramsey_constraint_add_greater(const string *name, const expr_t rhs);
|
||||
//! Ramsey less or equal constraint
|
||||
void ramsey_constraint_add_less_equal(const string *name, const expr_t rhs);
|
||||
//! Ramsey greater or equal constraint
|
||||
void ramsey_constraint_add_greater_equal(const string *name, const expr_t rhs);
|
||||
//! Ramsey constraint helper function
|
||||
void add_ramsey_constraint(const string *name, BinaryOpcode op_code, const expr_t rhs);
|
||||
//! Ramsey policy statement
|
||||
void ramsey_policy();
|
||||
//! Discretionary policy statement
|
||||
void discretionary_policy();
|
||||
//! Adds a write_latex_dynamic_model statement
|
||||
void write_latex_dynamic_model(bool write_equation_tags);
|
||||
//! Adds a write_latex_static_model statement
|
||||
void write_latex_static_model(bool write_equation_tags);
|
||||
//! Adds a write_latex_original_model statement
|
||||
void write_latex_original_model(bool write_equation_tags);
|
||||
//! Adds a write_latex_steady_state_model statement
|
||||
void write_latex_steady_state_model();
|
||||
//! BVAR marginal density
|
||||
void bvar_density(string *maxnlags);
|
||||
//! BVAR forecast
|
||||
void bvar_forecast(string *nlags);
|
||||
//! SBVAR statement
|
||||
void sbvar();
|
||||
//! Markov Switching Statement: Estimation
|
||||
void ms_estimation();
|
||||
//! Markov Switching Statement: Simulation
|
||||
void ms_simulation();
|
||||
//! Markov Switching Statement: MDD
|
||||
void ms_compute_mdd();
|
||||
//! Markov Switching Statement: Probabilities
|
||||
void ms_compute_probabilities();
|
||||
//! Markov Switching Statement: IRF
|
||||
void ms_irf();
|
||||
//! Markov Switching Statement: Forecast
|
||||
void ms_forecast();
|
||||
//! Markov Switching Statement: Variance Decomposition
|
||||
void ms_variance_decomposition();
|
||||
//! Svar statement
|
||||
void svar();
|
||||
//! MarkovSwitching statement
|
||||
void markov_switching();
|
||||
//! Shock decomposition
|
||||
void shock_decomposition();
|
||||
//! Realtime Shock decomposition
|
||||
void realtime_shock_decomposition();
|
||||
//! Plot Shock decomposition
|
||||
void plot_shock_decomposition();
|
||||
//! Initial Condition decomposition
|
||||
void initial_condition_decomposition();
|
||||
//! Conditional forecast statement
|
||||
void conditional_forecast();
|
||||
//! Conditional forecast paths block
|
||||
void conditional_forecast_paths();
|
||||
//! Plot conditional forecast statement
|
||||
void plot_conditional_forecast(string *periods = NULL);
|
||||
//! Smoother on calibrated models
|
||||
void calib_smoother();
|
||||
//! Extended path
|
||||
void extended_path();
|
||||
//! Writes token "arg1=arg2" to model tree
|
||||
expr_t add_model_equal(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "arg=0" to model tree
|
||||
expr_t add_model_equal_with_zero_rhs(expr_t arg);
|
||||
//! Writes token "arg1+arg2" to model tree
|
||||
expr_t add_plus(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "arg1-arg2" to model tree
|
||||
expr_t add_minus(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "-arg1" to model tree
|
||||
expr_t add_uminus(expr_t arg1);
|
||||
//! Writes token "arg1*arg2" to model tree
|
||||
expr_t add_times(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "arg1/arg2" to model tree
|
||||
expr_t add_divide(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "arg1<arg2" to model tree
|
||||
expr_t add_less(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "arg1>arg2" to model treeexpr_t
|
||||
expr_t add_greater(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "arg1<=arg2" to model treeexpr_t
|
||||
expr_t add_less_equal(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "arg1>=arg2" to model treeexpr_t
|
||||
expr_t add_greater_equal(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "arg1==arg2" to model treeexpr_texpr_t
|
||||
expr_t add_equal_equal(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "arg1!=arg2" to model treeexpr_texpr_t
|
||||
expr_t add_different(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "arg1^arg2" to model tree
|
||||
expr_t add_power(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "E(arg1)(arg2)" to model tree
|
||||
expr_t add_expectation(string *arg1, expr_t arg2);
|
||||
//! Writes token "VAR_EXPECTATION(arg1, arg2, arg3)" to model tree
|
||||
expr_t add_var_expectation(string *arg1, string *arg2, string *arg3);
|
||||
//! Writes token "PAC_EXPECTATION(model_name, discount, growth)" to model tree
|
||||
expr_t add_pac_expectation();
|
||||
//! Adds arguments for pac_expectation
|
||||
void add_pac_expectation_model_name(string *arg);
|
||||
void add_pac_expectation_var_model_name(string *arg);
|
||||
void add_pac_expectation_discount(string *arg);
|
||||
void add_pac_expectation_growth(string *arg);
|
||||
//! Writes token "diff(arg1)" to model tree
|
||||
expr_t add_diff(expr_t arg1);
|
||||
//! Writes token "adl(arg1, lag)" to model tree
|
||||
expr_t add_adl(expr_t arg1, string *name, string *lag);
|
||||
expr_t add_adl(expr_t arg1, string *name, vector<int> *lags);
|
||||
//! Writes token "exp(arg1)" to model tree
|
||||
expr_t add_exp(expr_t arg1);
|
||||
//! Writes token "log(arg1)" to model tree
|
||||
expr_t add_log(expr_t arg1);
|
||||
//! Writes token "log10(arg1)" to model tree
|
||||
expr_t add_log10(expr_t arg1);
|
||||
//! Writes token "cos(arg1)" to model tree
|
||||
expr_t add_cos(expr_t arg1);
|
||||
//! Writes token "sin(arg1)" to model tree
|
||||
expr_t add_sin(expr_t arg1);
|
||||
//! Writes token "tan(arg1)" to model tree
|
||||
expr_t add_tan(expr_t arg1);
|
||||
//! Writes token "acos(arg1)" to model tree
|
||||
expr_t add_acos(expr_t arg1);
|
||||
//! Writes token "asin(arg1)" to model tree
|
||||
expr_t add_asin(expr_t arg1);
|
||||
//! Writes token "atan(arg1)" to model tree
|
||||
expr_t add_atan(expr_t arg1);
|
||||
//! Writes token "cosh(arg1)" to model tree
|
||||
expr_t add_cosh(expr_t arg1);
|
||||
//! Writes token "sinh(arg1)" to model tree
|
||||
expr_t add_sinh(expr_t arg1);
|
||||
//! Writes token "tanh(arg1)" to model tree
|
||||
expr_t add_tanh(expr_t arg1);
|
||||
//! Writes token "acosh(arg1)" to model tree
|
||||
expr_t add_acosh(expr_t arg1);
|
||||
//! Writes token "asin(arg1)" to model tree
|
||||
expr_t add_asinh(expr_t arg1);
|
||||
//! Writes token "atanh(arg1)" to model tree
|
||||
expr_t add_atanh(expr_t arg1);
|
||||
//! Writes token "sqrt(arg1)" to model tree
|
||||
expr_t add_sqrt(expr_t arg1);
|
||||
//! Writes token "abs(arg1)" to model tree
|
||||
expr_t add_abs(expr_t arg1);
|
||||
//! Writes token "sign(arg1)" to model tree
|
||||
expr_t add_sign(expr_t arg1);
|
||||
//! Writes token "max(arg1,arg2)" to model tree
|
||||
expr_t add_max(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "min(arg1,arg2)" to model tree
|
||||
expr_t add_min(expr_t arg1, expr_t arg2);
|
||||
//! Writes token "normcdf(arg1,arg2,arg3)" to model tree
|
||||
expr_t add_normcdf(expr_t arg1, expr_t arg2, expr_t arg3);
|
||||
//! Writes token "normcdf(arg,0,1)" to model tree
|
||||
expr_t add_normcdf(expr_t arg);
|
||||
//! Writes token "normpdf(arg1,arg2,arg3)" to model tree
|
||||
expr_t add_normpdf(expr_t arg1, expr_t arg2, expr_t arg3);
|
||||
//! Writes token "normpdf(arg,0,1)" to model tree
|
||||
expr_t add_normpdf(expr_t arg);
|
||||
//! Writes token "erf(arg)" to model tree
|
||||
expr_t add_erf(expr_t arg);
|
||||
//! Writes token "steadyState(arg1)" to model tree
|
||||
expr_t add_steady_state(expr_t arg1);
|
||||
//! Pushes empty vector onto stack when a symbol is encountered (mod_var or ext_fun)
|
||||
void push_external_function_arg_vector_onto_stack();
|
||||
//! Adds an external function argument
|
||||
void add_external_function_arg(expr_t arg);
|
||||
//! Test to see if model/external function has exactly one integer argument
|
||||
pair<bool, double> is_there_one_integer_argument() const;
|
||||
//! Adds an external function call node
|
||||
expr_t add_model_var_or_external_function(string *function_name, bool in_model_block);
|
||||
//! Adds a native statement
|
||||
void add_native(const string &s);
|
||||
//! Adds a native statement, first removing the set of characters passed in token (and everything after)
|
||||
void add_native_remove_charset(const char *s, const string &token);
|
||||
//! Adds a verbatim statement
|
||||
void add_verbatim(const string &s);
|
||||
//! Adds a verbatim statement, first removing the set of characters passed in token (and everything after)
|
||||
void add_verbatim_remove_charset(const char *s, const string &token);
|
||||
//! Resets data_tree and model_tree pointers to default (i.e. mod_file->expressions_tree)
|
||||
void reset_data_tree();
|
||||
//! Begin a steady_state_model block
|
||||
void begin_steady_state_model();
|
||||
//! Add an assignment equation in steady_state_model block
|
||||
void add_steady_state_model_equal(string *varname, expr_t expr);
|
||||
//! Add a multiple assignment equation in steady_state_model block
|
||||
void add_steady_state_model_equal_multiple(expr_t expr);
|
||||
//! Switches datatree
|
||||
void begin_trend();
|
||||
//! Declares a trend variable with its growth factor
|
||||
void declare_trend_var(bool log_trend, string *name, string *tex_name = NULL);
|
||||
//! Ends declaration of trend variable
|
||||
void end_trend_var(expr_t growth_factor);
|
||||
//! Declares a nonstationary variable with its deflator
|
||||
void declare_nonstationary_var(string *name, string *tex_name = NULL, vector<pair<string *, string *> *> *partition_value = NULL);
|
||||
//! Ends declaration of nonstationary variable
|
||||
void end_nonstationary_var(bool log_deflator, expr_t deflator);
|
||||
//! Add a graph format to the list of formats requested
|
||||
void add_graph_format(const string &name);
|
||||
//! Add the graph_format option to the OptionsList structure
|
||||
void process_graph_format_option();
|
||||
//! Add the graph_format option to the plot_shock_decomp substructure of the OptionsList structure
|
||||
void plot_shock_decomp_process_graph_format_option();
|
||||
//! Model diagnostics
|
||||
void model_diagnostics();
|
||||
//! Processing the parallel_local_files option
|
||||
void add_parallel_local_file(string *filename);
|
||||
//! Add an item of a moment_calibration statement
|
||||
void add_moment_calibration_item(string *endo1, string *endo2, string *lags, vector<string *> *range);
|
||||
//! End a moment_calibration statement
|
||||
void end_moment_calibration();
|
||||
//! Add an item of an irf_calibration statement
|
||||
void add_irf_calibration_item(string *endo, string *periods, string *exo, vector<string *> *range);
|
||||
//! End a moment_calibration statement
|
||||
void end_irf_calibration();
|
||||
//! Add a shock to a group
|
||||
void add_shock_group_element(string *name);
|
||||
//! Add a set of shock groups
|
||||
void add_shock_group(string *name);
|
||||
//! End shock groups declaration
|
||||
void end_shock_groups(const string *name);
|
||||
//! Add an element to the ramsey policy list
|
||||
void add_to_ramsey_policy_list(string *name);
|
||||
void smoother2histval();
|
||||
void histval_file(string *filename);
|
||||
void perfect_foresight_setup();
|
||||
void perfect_foresight_solver();
|
||||
void prior_posterior_function(bool prior_func);
|
||||
//! VAR Restrictions
|
||||
void begin_VAR_restrictions();
|
||||
void end_VAR_restrictions(string *var_model_name);
|
||||
void add_VAR_exclusion_restriction(string *lagstr);
|
||||
void add_VAR_restriction_exclusion_equation(string *name);
|
||||
void add_VAR_restriction_coeff(string *name1, string *name2, string *lagstr);
|
||||
void add_VAR_restriction_eq_or_crosseq(expr_t expr);
|
||||
void add_VAR_restriction_equation_or_crossequation(string *numberstr);
|
||||
void multiply_arg2_by_neg_one();
|
||||
void add_VAR_restriction_equation_or_crossequation_final(string *name);
|
||||
void add_VAR_covariance_number_restriction(string *name1, string *name2, string *valuestr);
|
||||
void add_VAR_covariance_pair_restriction(string *name11, string *name12, string *name21, string *name22);
|
||||
//! Runs VAR estimation process
|
||||
void run_var_estimation();
|
||||
//! GMM Estimation statement
|
||||
void gmm_estimation();
|
||||
//! SMM Estimation statement
|
||||
void smm_estimation();
|
||||
};
|
||||
|
||||
#endif // ! PARSING_DRIVER_HH
|
|
@ -1,631 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include "Shocks.hh"
|
||||
|
||||
AbstractShocksStatement::AbstractShocksStatement(bool mshocks_arg,
|
||||
bool overwrite_arg,
|
||||
const det_shocks_t &det_shocks_arg,
|
||||
const SymbolTable &symbol_table_arg) :
|
||||
mshocks(mshocks_arg),
|
||||
overwrite(overwrite_arg),
|
||||
det_shocks(det_shocks_arg),
|
||||
symbol_table(symbol_table_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AbstractShocksStatement::writeDetShocks(ostream &output) const
|
||||
{
|
||||
int exo_det_length = 0;
|
||||
|
||||
for (det_shocks_t::const_iterator it = det_shocks.begin();
|
||||
it != det_shocks.end(); it++)
|
||||
{
|
||||
int id = symbol_table.getTypeSpecificID(it->first) + 1;
|
||||
bool exo_det = (symbol_table.getType(it->first) == eExogenousDet);
|
||||
|
||||
for (size_t i = 0; i < it->second.size(); i++)
|
||||
{
|
||||
const int &period1 = it->second[i].period1;
|
||||
const int &period2 = it->second[i].period2;
|
||||
const expr_t value = it->second[i].value;
|
||||
|
||||
output << "M_.det_shocks = [ M_.det_shocks;" << endl
|
||||
<< "struct('exo_det'," << (int) exo_det
|
||||
<< ",'exo_id'," << id
|
||||
<< ",'multiplicative'," << (int) mshocks
|
||||
<< ",'periods'," << period1 << ":" << period2
|
||||
<< ",'value',";
|
||||
value->writeOutput(output);
|
||||
output << ") ];" << endl;
|
||||
|
||||
if (exo_det && (period2 > exo_det_length))
|
||||
exo_det_length = period2;
|
||||
}
|
||||
}
|
||||
output << "M_.exo_det_length = " << exo_det_length << ";\n";
|
||||
}
|
||||
|
||||
void
|
||||
AbstractShocksStatement::writeJsonDetShocks(ostream &output) const
|
||||
{
|
||||
deriv_node_temp_terms_t tef_terms;
|
||||
output << "\"deterministic_shocks\": [";
|
||||
for (det_shocks_t::const_iterator it = det_shocks.begin();
|
||||
it != det_shocks.end(); it++)
|
||||
{
|
||||
if (it != det_shocks.begin())
|
||||
output << ", ";
|
||||
output << "{\"var\": \"" << symbol_table.getName(it->first) << "\", "
|
||||
<< "\"values\": [";
|
||||
for (vector<DetShockElement>::const_iterator it1 = it->second.begin();
|
||||
it1 != it->second.end(); it1++)
|
||||
{
|
||||
if (it1 != it->second.begin())
|
||||
output << ", ";
|
||||
output << "{\"period1\": " << it1->period1 << ", "
|
||||
<< "\"period2\": " << it1->period2 << ", "
|
||||
<< "\"value\": \"";
|
||||
it1->value->writeJsonOutput(output, temporary_terms_t(), tef_terms);
|
||||
output << "\"}";
|
||||
}
|
||||
output << "]}";
|
||||
}
|
||||
output << "]";
|
||||
}
|
||||
|
||||
ShocksStatement::ShocksStatement(bool overwrite_arg,
|
||||
const det_shocks_t &det_shocks_arg,
|
||||
const var_and_std_shocks_t &var_shocks_arg,
|
||||
const var_and_std_shocks_t &std_shocks_arg,
|
||||
const covar_and_corr_shocks_t &covar_shocks_arg,
|
||||
const covar_and_corr_shocks_t &corr_shocks_arg,
|
||||
const SymbolTable &symbol_table_arg) :
|
||||
AbstractShocksStatement(false, overwrite_arg, det_shocks_arg, symbol_table_arg),
|
||||
var_shocks(var_shocks_arg),
|
||||
std_shocks(std_shocks_arg),
|
||||
covar_shocks(covar_shocks_arg),
|
||||
corr_shocks(corr_shocks_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ShocksStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
output << "%" << endl
|
||||
<< "% SHOCKS instructions" << endl
|
||||
<< "%" << endl;
|
||||
|
||||
if (overwrite)
|
||||
{
|
||||
output << "M_.det_shocks = [];" << endl;
|
||||
|
||||
output << "M_.Sigma_e = zeros(" << symbol_table.exo_nbr() << ", "
|
||||
<< symbol_table.exo_nbr() << ");" << endl
|
||||
<< "M_.Correlation_matrix = eye(" << symbol_table.exo_nbr() << ", "
|
||||
<< symbol_table.exo_nbr() << ");" << endl;
|
||||
|
||||
if (has_calibrated_measurement_errors())
|
||||
output << "M_.H = zeros(" << symbol_table.observedVariablesNbr() << ", "
|
||||
<< symbol_table.observedVariablesNbr() << ");" << endl
|
||||
<< "M_.Correlation_matrix_ME = eye(" << symbol_table.observedVariablesNbr() << ", "
|
||||
<< symbol_table.observedVariablesNbr() << ");" << endl;
|
||||
else
|
||||
output << "M_.H = 0;" << endl
|
||||
<< "M_.Correlation_matrix_ME = 1;" << endl;
|
||||
|
||||
}
|
||||
|
||||
writeDetShocks(output);
|
||||
writeVarAndStdShocks(output);
|
||||
writeCovarAndCorrShocks(output);
|
||||
|
||||
/* M_.sigma_e_is_diagonal is initialized to 1 by ModFile.cc.
|
||||
If there are no off-diagonal elements, and we are not in overwrite mode,
|
||||
then we don't reset it to 1, since there might be previous shocks blocks
|
||||
with off-diagonal elements. */
|
||||
if (covar_shocks.size()+corr_shocks.size() > 0)
|
||||
output << "M_.sigma_e_is_diagonal = 0;" << endl;
|
||||
else if (overwrite)
|
||||
output << "M_.sigma_e_is_diagonal = 1;" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
ShocksStatement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
deriv_node_temp_terms_t tef_terms;
|
||||
output << "{\"statementName\": \"shocks\""
|
||||
<< ", \"overwrite\": ";
|
||||
if (overwrite)
|
||||
output << "true";
|
||||
else
|
||||
output << "false";
|
||||
if (!det_shocks.empty())
|
||||
{
|
||||
output << ", ";
|
||||
writeJsonDetShocks(output);
|
||||
}
|
||||
output<< ", \"variance\": [";
|
||||
for (var_and_std_shocks_t::const_iterator it = var_shocks.begin(); it != var_shocks.end(); it++)
|
||||
{
|
||||
if (it != var_shocks.begin())
|
||||
output << ", ";
|
||||
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\", "
|
||||
<< "\"variance\": \"";
|
||||
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
|
||||
output << "\"}";
|
||||
}
|
||||
output << "]"
|
||||
<< ", \"stderr\": [";
|
||||
for (var_and_std_shocks_t::const_iterator it = std_shocks.begin(); it != std_shocks.end(); it++)
|
||||
{
|
||||
if (it != std_shocks.begin())
|
||||
output << ", ";
|
||||
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\", "
|
||||
<< "\"stderr\": \"";
|
||||
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
|
||||
output << "\"}";
|
||||
}
|
||||
output << "]"
|
||||
<< ", \"covariance\": [";
|
||||
for (covar_and_corr_shocks_t::const_iterator it = covar_shocks.begin(); it != covar_shocks.end(); it++)
|
||||
{
|
||||
if (it != covar_shocks.begin())
|
||||
output << ", ";
|
||||
output << "{"
|
||||
<< "\"name\": \"" << symbol_table.getName(it->first.first) << "\", "
|
||||
<< "\"name2\": \"" << symbol_table.getName(it->first.second) << "\", "
|
||||
<< "\"covariance\": \"";
|
||||
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
|
||||
output << "\"}";
|
||||
}
|
||||
output << "]"
|
||||
<< ", \"correlation\": [";
|
||||
for (covar_and_corr_shocks_t::const_iterator it = corr_shocks.begin(); it != corr_shocks.end(); it++)
|
||||
{
|
||||
if (it != corr_shocks.begin())
|
||||
output << ", ";
|
||||
output << "{"
|
||||
<< "\"name\": \"" << symbol_table.getName(it->first.first) << "\", "
|
||||
<< "\"name2\": \"" << symbol_table.getName(it->first.second) << "\", "
|
||||
<< "\"correlation\": \"";
|
||||
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
|
||||
output << "\"}";
|
||||
}
|
||||
output << "]"
|
||||
<< "}";
|
||||
}
|
||||
|
||||
void
|
||||
ShocksStatement::writeVarOrStdShock(ostream &output, var_and_std_shocks_t::const_iterator &it,
|
||||
bool stddev) const
|
||||
{
|
||||
SymbolType type = symbol_table.getType(it->first);
|
||||
assert(type == eExogenous || symbol_table.isObservedVariable(it->first));
|
||||
|
||||
int id;
|
||||
if (type == eExogenous)
|
||||
{
|
||||
output << "M_.Sigma_e(";
|
||||
id = symbol_table.getTypeSpecificID(it->first) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
output << "M_.H(";
|
||||
id = symbol_table.getObservedVariableIndex(it->first) + 1;
|
||||
}
|
||||
|
||||
output << id << ", " << id << ") = ";
|
||||
if (stddev)
|
||||
output << "(";
|
||||
it->second->writeOutput(output);
|
||||
if (stddev)
|
||||
output << ")^2";
|
||||
output << ";" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
ShocksStatement::writeVarAndStdShocks(ostream &output) const
|
||||
{
|
||||
var_and_std_shocks_t::const_iterator it;
|
||||
|
||||
for (it = var_shocks.begin(); it != var_shocks.end(); it++)
|
||||
writeVarOrStdShock(output, it, false);
|
||||
|
||||
for (it = std_shocks.begin(); it != std_shocks.end(); it++)
|
||||
writeVarOrStdShock(output, it, true);
|
||||
}
|
||||
|
||||
void
|
||||
ShocksStatement::writeCovarOrCorrShock(ostream &output, covar_and_corr_shocks_t::const_iterator &it,
|
||||
bool corr) const
|
||||
{
|
||||
SymbolType type1 = symbol_table.getType(it->first.first);
|
||||
SymbolType type2 = symbol_table.getType(it->first.second);
|
||||
assert((type1 == eExogenous && type2 == eExogenous)
|
||||
|| (symbol_table.isObservedVariable(it->first.first) && symbol_table.isObservedVariable(it->first.second)));
|
||||
string matrix, corr_matrix;
|
||||
int id1, id2;
|
||||
if (type1 == eExogenous)
|
||||
{
|
||||
matrix = "M_.Sigma_e";
|
||||
corr_matrix = "M_.Correlation_matrix";
|
||||
id1 = symbol_table.getTypeSpecificID(it->first.first) + 1;
|
||||
id2 = symbol_table.getTypeSpecificID(it->first.second) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix = "M_.H";
|
||||
corr_matrix = "M_.Correlation_matrix_ME";
|
||||
id1 = symbol_table.getObservedVariableIndex(it->first.first) + 1;
|
||||
id2 = symbol_table.getObservedVariableIndex(it->first.second) + 1;
|
||||
}
|
||||
|
||||
output << matrix << "(" << id1 << ", " << id2 << ") = ";
|
||||
it->second->writeOutput(output);
|
||||
if (corr)
|
||||
output << "*sqrt(" << matrix << "(" << id1 << ", " << id1 << ")*"
|
||||
<< matrix << "(" << id2 << ", " << id2 << "))";
|
||||
output << ";" << endl
|
||||
<< matrix << "(" << id2 << ", " << id1 << ") = "
|
||||
<< matrix << "(" << id1 << ", " << id2 << ");" << endl;
|
||||
|
||||
if (corr)
|
||||
{
|
||||
output << corr_matrix << "(" << id1 << ", " << id2 << ") = ";
|
||||
it->second->writeOutput(output);
|
||||
output << ";" << endl
|
||||
<< corr_matrix << "(" << id2 << ", " << id1 << ") = "
|
||||
<< corr_matrix << "(" << id1 << ", " << id2 << ");" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShocksStatement::writeCovarAndCorrShocks(ostream &output) const
|
||||
{
|
||||
covar_and_corr_shocks_t::const_iterator it;
|
||||
|
||||
for (it = covar_shocks.begin(); it != covar_shocks.end(); it++)
|
||||
writeCovarOrCorrShock(output, it, false);
|
||||
|
||||
for (it = corr_shocks.begin(); it != corr_shocks.end(); it++)
|
||||
writeCovarOrCorrShock(output, it, true);
|
||||
}
|
||||
|
||||
void
|
||||
ShocksStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
|
||||
{
|
||||
/* Error out if variables are not of the right type. This must be done here
|
||||
and not at parsing time (see #448).
|
||||
Also Determine if there is a calibrated measurement error */
|
||||
for (var_and_std_shocks_t::const_iterator it = var_shocks.begin();
|
||||
it != var_shocks.end(); it++)
|
||||
{
|
||||
if (symbol_table.getType(it->first) != eExogenous
|
||||
&& !symbol_table.isObservedVariable(it->first))
|
||||
{
|
||||
cerr << "shocks: setting a variance on '"
|
||||
<< symbol_table.getName(it->first) << "' is not allowed, because it is neither an exogenous variable nor an observed endogenous variable" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
for (var_and_std_shocks_t::const_iterator it = std_shocks.begin();
|
||||
it != std_shocks.end(); it++)
|
||||
{
|
||||
if (symbol_table.getType(it->first) != eExogenous
|
||||
&& !symbol_table.isObservedVariable(it->first))
|
||||
{
|
||||
cerr << "shocks: setting a standard error on '"
|
||||
<< symbol_table.getName(it->first) << "' is not allowed, because it is neither an exogenous variable nor an observed endogenous variable" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
for (covar_and_corr_shocks_t::const_iterator it = covar_shocks.begin();
|
||||
it != covar_shocks.end(); it++)
|
||||
{
|
||||
int symb_id1 = it->first.first;
|
||||
int symb_id2 = it->first.second;
|
||||
|
||||
if (!((symbol_table.getType(symb_id1) == eExogenous
|
||||
&& symbol_table.getType(symb_id2) == eExogenous)
|
||||
|| (symbol_table.isObservedVariable(symb_id1)
|
||||
&& symbol_table.isObservedVariable(symb_id2))))
|
||||
{
|
||||
cerr << "shocks: setting a covariance between '"
|
||||
<< symbol_table.getName(symb_id1) << "' and '"
|
||||
<< symbol_table.getName(symb_id2) << "'is not allowed; covariances can only be specified for exogenous or observed endogenous variables of same type" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
for (covar_and_corr_shocks_t::const_iterator it = corr_shocks.begin();
|
||||
it != corr_shocks.end(); it++)
|
||||
{
|
||||
int symb_id1 = it->first.first;
|
||||
int symb_id2 = it->first.second;
|
||||
|
||||
if (!((symbol_table.getType(symb_id1) == eExogenous
|
||||
&& symbol_table.getType(symb_id2) == eExogenous)
|
||||
|| (symbol_table.isObservedVariable(symb_id1)
|
||||
&& symbol_table.isObservedVariable(symb_id2))))
|
||||
{
|
||||
cerr << "shocks: setting a correlation between '"
|
||||
<< symbol_table.getName(symb_id1) << "' and '"
|
||||
<< symbol_table.getName(symb_id2) << "'is not allowed; correlations can only be specified for exogenous or observed endogenous variables of same type" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if there is a calibrated measurement error
|
||||
mod_file_struct.calibrated_measurement_errors |= has_calibrated_measurement_errors();
|
||||
|
||||
// Fill in mod_file_struct.parameters_with_shocks_values (related to #469)
|
||||
for (var_and_std_shocks_t::const_iterator it = var_shocks.begin();
|
||||
it != var_shocks.end(); ++it)
|
||||
it->second->collectVariables(eParameter, mod_file_struct.parameters_within_shocks_values);
|
||||
for (var_and_std_shocks_t::const_iterator it = std_shocks.begin();
|
||||
it != std_shocks.end(); ++it)
|
||||
it->second->collectVariables(eParameter, mod_file_struct.parameters_within_shocks_values);
|
||||
for (covar_and_corr_shocks_t::const_iterator it = covar_shocks.begin();
|
||||
it != covar_shocks.end(); ++it)
|
||||
it->second->collectVariables(eParameter, mod_file_struct.parameters_within_shocks_values);
|
||||
for (covar_and_corr_shocks_t::const_iterator it = corr_shocks.begin();
|
||||
it != corr_shocks.end(); ++it)
|
||||
it->second->collectVariables(eParameter, mod_file_struct.parameters_within_shocks_values);
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
ShocksStatement::has_calibrated_measurement_errors() const
|
||||
{
|
||||
for (var_and_std_shocks_t::const_iterator it = var_shocks.begin();
|
||||
it != var_shocks.end(); it++)
|
||||
if (symbol_table.isObservedVariable(it->first))
|
||||
return true;
|
||||
|
||||
for (var_and_std_shocks_t::const_iterator it = std_shocks.begin();
|
||||
it != std_shocks.end(); it++)
|
||||
if (symbol_table.isObservedVariable(it->first))
|
||||
return true;
|
||||
|
||||
for (covar_and_corr_shocks_t::const_iterator it = covar_shocks.begin();
|
||||
it != covar_shocks.end(); it++)
|
||||
if (symbol_table.isObservedVariable(it->first.first)
|
||||
|| symbol_table.isObservedVariable(it->first.second))
|
||||
return true;
|
||||
|
||||
for (covar_and_corr_shocks_t::const_iterator it = corr_shocks.begin();
|
||||
it != corr_shocks.end(); it++)
|
||||
if (symbol_table.isObservedVariable(it->first.first)
|
||||
|| symbol_table.isObservedVariable(it->first.second))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MShocksStatement::MShocksStatement(bool overwrite_arg,
|
||||
const det_shocks_t &det_shocks_arg,
|
||||
const SymbolTable &symbol_table_arg) :
|
||||
AbstractShocksStatement(true, overwrite_arg, det_shocks_arg, symbol_table_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
MShocksStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
output << "%" << endl
|
||||
<< "% MSHOCKS instructions" << endl
|
||||
<< "%" << endl;
|
||||
|
||||
if (overwrite)
|
||||
output << "M_.det_shocks = [];" << endl;
|
||||
|
||||
writeDetShocks(output);
|
||||
}
|
||||
|
||||
ConditionalForecastPathsStatement::ConditionalForecastPathsStatement(const AbstractShocksStatement::det_shocks_t &paths_arg,
|
||||
const SymbolTable &symbol_table_arg) :
|
||||
paths(paths_arg),
|
||||
symbol_table(symbol_table_arg),
|
||||
path_length(-1)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ConditionalForecastPathsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
|
||||
{
|
||||
for (AbstractShocksStatement::det_shocks_t::const_iterator it = paths.begin();
|
||||
it != paths.end(); it++)
|
||||
{
|
||||
int this_path_length = 0;
|
||||
const vector<AbstractShocksStatement::DetShockElement> &elems = it->second;
|
||||
for (int i = 0; i < (int) elems.size(); i++)
|
||||
// Period1 < Period2, as enforced in ParsingDriver::add_period()
|
||||
this_path_length = max(this_path_length, elems[i].period2);
|
||||
if (path_length == -1)
|
||||
path_length = this_path_length;
|
||||
else if (path_length != this_path_length)
|
||||
{
|
||||
cerr << "conditional_forecast_paths: all constrained paths must have the same length!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConditionalForecastPathsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
assert(path_length > 0);
|
||||
output << "constrained_vars_ = [];" << endl
|
||||
<< "constrained_paths_ = zeros(" << paths.size() << ", " << path_length << ");" << endl;
|
||||
|
||||
int k = 1;
|
||||
for (AbstractShocksStatement::det_shocks_t::const_iterator it = paths.begin();
|
||||
it != paths.end(); it++, k++)
|
||||
{
|
||||
if (it == paths.begin())
|
||||
output << "constrained_vars_ = " << symbol_table.getTypeSpecificID(it->first) + 1 << ";" << endl;
|
||||
else
|
||||
output << "constrained_vars_ = [constrained_vars_; " << symbol_table.getTypeSpecificID(it->first) + 1 << "];" << endl;
|
||||
|
||||
const vector<AbstractShocksStatement::DetShockElement> &elems = it->second;
|
||||
for (int i = 0; i < (int) elems.size(); i++)
|
||||
for (int j = elems[i].period1; j <= elems[i].period2; j++)
|
||||
{
|
||||
output << "constrained_paths_(" << k << "," << j << ")=";
|
||||
elems[i].value->writeOutput(output);
|
||||
output << ";" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MomentCalibration::MomentCalibration(const constraints_t &constraints_arg,
|
||||
const SymbolTable &symbol_table_arg)
|
||||
: constraints(constraints_arg), symbol_table(symbol_table_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
MomentCalibration::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
output << "options_.endogenous_prior_restrictions.moment = {" << endl;
|
||||
for (size_t i = 0; i < constraints.size(); i++)
|
||||
{
|
||||
const Constraint &c = constraints[i];
|
||||
output << "'" << symbol_table.getName(c.endo1) << "', "
|
||||
<< "'" << symbol_table.getName(c.endo2) << "', "
|
||||
<< c.lags << ", "
|
||||
<< "[ " << c.lower_bound << ", " << c.upper_bound << " ];"
|
||||
<< endl;
|
||||
}
|
||||
output << "};" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
MomentCalibration::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
output << "{\"statementName\": \"moment_calibration\""
|
||||
<< ", \"moment_calibration_criteria\": [";
|
||||
for (constraints_t::const_iterator it = constraints.begin(); it != constraints.end(); it++)
|
||||
{
|
||||
if (it != constraints.begin())
|
||||
output << ", ";
|
||||
output << "{\"endogenous1\": \"" << symbol_table.getName(it->endo1) << "\""
|
||||
<< ", \"endogenous2\": \"" << symbol_table.getName(it->endo2) << "\""
|
||||
<< ", \"lags\": \"" << it->lags << "\""
|
||||
<< ", \"lower_bound\": \"" << it->lower_bound << "\""
|
||||
<< ", \"upper_bound\": \"" << it->upper_bound << "\""
|
||||
<< "}";
|
||||
}
|
||||
output << "]"
|
||||
<< "}";
|
||||
}
|
||||
|
||||
IrfCalibration::IrfCalibration(const constraints_t &constraints_arg,
|
||||
const SymbolTable &symbol_table_arg,
|
||||
const OptionsList &options_list_arg)
|
||||
: constraints(constraints_arg), symbol_table(symbol_table_arg), options_list(options_list_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
IrfCalibration::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
options_list.writeOutput(output);
|
||||
|
||||
output << "options_.endogenous_prior_restrictions.irf = {" << endl;
|
||||
for (size_t i = 0; i < constraints.size(); i++)
|
||||
{
|
||||
const Constraint &c = constraints[i];
|
||||
output << "'" << symbol_table.getName(c.endo) << "', "
|
||||
<< "'" << symbol_table.getName(c.exo) << "', "
|
||||
<< c.periods << ", "
|
||||
<< "[ " << c.lower_bound << ", " << c.upper_bound << " ];"
|
||||
<< endl;
|
||||
}
|
||||
output << "};" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
IrfCalibration::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
output << "{\"statementName\": \"irf_calibration\"";
|
||||
if (options_list.getNumberOfOptions())
|
||||
{
|
||||
output << ", ";
|
||||
options_list.writeJsonOutput(output);
|
||||
}
|
||||
|
||||
output << ", \"irf_restrictions\": [";
|
||||
for (constraints_t::const_iterator it = constraints.begin(); it != constraints.end(); it++)
|
||||
{
|
||||
if (it != constraints.begin())
|
||||
output << ", ";
|
||||
output << "{\"endogenous\": \"" << symbol_table.getName(it->endo) << "\""
|
||||
<< ", \"exogenous\": \"" << symbol_table.getName(it->exo) << "\""
|
||||
<< ", \"periods\": \"" << it->periods << "\""
|
||||
<< ", \"lower_bound\": \"" << it->lower_bound << "\""
|
||||
<< ", \"upper_bound\": \"" << it->upper_bound << "\""
|
||||
<< "}";
|
||||
}
|
||||
output << "]"
|
||||
<< "}";
|
||||
}
|
||||
|
||||
ShockGroupsStatement::ShockGroupsStatement(const group_t &shock_groups_arg, const string &name_arg)
|
||||
: shock_groups(shock_groups_arg), name(name_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ShockGroupsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
int i = 1;
|
||||
bool unique_label = true;
|
||||
for (vector<Group>::const_iterator it = shock_groups.begin(); it != shock_groups.end(); it++, unique_label = true)
|
||||
{
|
||||
for (vector<Group>::const_iterator it1 = it+1; it1 != shock_groups.end(); it1++)
|
||||
if (it->name == it1->name)
|
||||
{
|
||||
unique_label = false;
|
||||
cerr << "Warning: shock group label '" << it->name << "' has been reused. "
|
||||
<< "Only using the last definition." << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
if (unique_label)
|
||||
{
|
||||
output << "M_.shock_groups." << name
|
||||
<< ".group" << i << ".label = '" << it->name << "';" << endl
|
||||
<< "M_.shock_groups." << name
|
||||
<< ".group" << i << ".shocks = {";
|
||||
for (vector<string>::const_iterator it1 = it->list.begin(); it1 != it->list.end(); it1++)
|
||||
output << " '" << *it1 << "'";
|
||||
output << "};" << endl;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SHOCKS_HH
|
||||
#define _SHOCKS_HH
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "Statement.hh"
|
||||
#include "SymbolTable.hh"
|
||||
#include "ExprNode.hh"
|
||||
|
||||
class AbstractShocksStatement : public Statement
|
||||
{
|
||||
public:
|
||||
struct DetShockElement
|
||||
{
|
||||
int period1;
|
||||
int period2;
|
||||
expr_t value;
|
||||
};
|
||||
//The boolean element indicates if the shock is a surprise (false) or a perfect foresight (true) shock.
|
||||
//This boolean is used only in case of conditional forecast with extended path method (simulation_type = deterministic).
|
||||
typedef map<int, vector<DetShockElement> > det_shocks_t;
|
||||
protected:
|
||||
//! Is this statement a "mshocks" statement ? (instead of a "shocks" statement)
|
||||
const bool mshocks;
|
||||
//! Does this "shocks" statement replace the previous ones?
|
||||
const bool overwrite;
|
||||
const det_shocks_t det_shocks;
|
||||
const SymbolTable &symbol_table;
|
||||
void writeDetShocks(ostream &output) const;
|
||||
void writeJsonDetShocks(ostream &output) const;
|
||||
|
||||
AbstractShocksStatement(bool mshocks_arg, bool overwrite_arg,
|
||||
const det_shocks_t &det_shocks_arg,
|
||||
const SymbolTable &symbol_table_arg);
|
||||
};
|
||||
|
||||
class ShocksStatement : public AbstractShocksStatement
|
||||
{
|
||||
public:
|
||||
typedef map<int, expr_t> var_and_std_shocks_t;
|
||||
typedef map<pair<int, int>, expr_t> covar_and_corr_shocks_t;
|
||||
private:
|
||||
const var_and_std_shocks_t var_shocks, std_shocks;
|
||||
const covar_and_corr_shocks_t covar_shocks, corr_shocks;
|
||||
void writeVarOrStdShock(ostream &output, var_and_std_shocks_t::const_iterator &it, bool stddev) const;
|
||||
void writeVarAndStdShocks(ostream &output) const;
|
||||
void writeCovarOrCorrShock(ostream &output, covar_and_corr_shocks_t::const_iterator &it, bool corr) const;
|
||||
void writeCovarAndCorrShocks(ostream &output) const;
|
||||
bool has_calibrated_measurement_errors() const;
|
||||
public:
|
||||
ShocksStatement(bool overwrite_arg,
|
||||
const det_shocks_t &det_shocks_arg,
|
||||
const var_and_std_shocks_t &var_shocks_arg,
|
||||
const var_and_std_shocks_t &std_shocks_arg,
|
||||
const covar_and_corr_shocks_t &covar_shocks_arg,
|
||||
const covar_and_corr_shocks_t &corr_shocks_arg,
|
||||
const SymbolTable &symbol_table_arg);
|
||||
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
class MShocksStatement : public AbstractShocksStatement
|
||||
{
|
||||
public:
|
||||
MShocksStatement(bool overwrite_arg,
|
||||
const det_shocks_t &det_shocks_arg,
|
||||
const SymbolTable &symbol_table_arg);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
};
|
||||
|
||||
class ConditionalForecastPathsStatement : public Statement
|
||||
{
|
||||
private:
|
||||
const AbstractShocksStatement::det_shocks_t paths;
|
||||
const SymbolTable &symbol_table;
|
||||
int path_length;
|
||||
public:
|
||||
ConditionalForecastPathsStatement(const AbstractShocksStatement::det_shocks_t &paths_arg,
|
||||
const SymbolTable &symbol_table_arg);
|
||||
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
};
|
||||
|
||||
class MomentCalibration : public Statement
|
||||
{
|
||||
public:
|
||||
struct Constraint
|
||||
{
|
||||
int endo1, endo2;
|
||||
string lags;
|
||||
string lower_bound, upper_bound;
|
||||
};
|
||||
typedef vector<Constraint> constraints_t;
|
||||
private:
|
||||
constraints_t constraints;
|
||||
const SymbolTable &symbol_table;
|
||||
public:
|
||||
MomentCalibration(const constraints_t &constraints_arg,
|
||||
const SymbolTable &symbol_table_arg);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
class IrfCalibration : public Statement
|
||||
{
|
||||
public:
|
||||
struct Constraint
|
||||
{
|
||||
int endo;
|
||||
int exo;
|
||||
string periods, lower_bound, upper_bound;
|
||||
};
|
||||
typedef vector<Constraint> constraints_t;
|
||||
private:
|
||||
constraints_t constraints;
|
||||
const SymbolTable &symbol_table;
|
||||
const OptionsList options_list;
|
||||
public:
|
||||
IrfCalibration(const constraints_t &constraints_arg,
|
||||
const SymbolTable &symbol_table_arg,
|
||||
const OptionsList &options_list_arg);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
class ShockGroupsStatement : public Statement
|
||||
{
|
||||
public:
|
||||
struct Group
|
||||
{
|
||||
string name;
|
||||
vector<string> list;
|
||||
};
|
||||
typedef vector<Group> group_t;
|
||||
private:
|
||||
group_t shock_groups;
|
||||
vector<string> group_names;
|
||||
string name;
|
||||
public:
|
||||
ShockGroupsStatement(const group_t &shock_groups_arg, const string &name_arg);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2015 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SigmaeInitialization.hh"
|
||||
|
||||
SigmaeStatement::SigmaeStatement(const matrix_t &matrix_arg) throw (MatrixFormException) :
|
||||
matrix(matrix_arg),
|
||||
matrix_form(determineMatrixForm(matrix))
|
||||
{
|
||||
}
|
||||
|
||||
SigmaeStatement::matrix_form_t
|
||||
SigmaeStatement::determineMatrixForm(const matrix_t &matrix) throw (MatrixFormException)
|
||||
{
|
||||
size_t nbe;
|
||||
int inc;
|
||||
matrix_form_t type;
|
||||
// Checking if first or last row has one element.
|
||||
if (matrix.front().size() == 1)
|
||||
{
|
||||
inc = 1;
|
||||
nbe = 2;
|
||||
type = eLower;
|
||||
}
|
||||
else if (matrix.back().size() == 1)
|
||||
{
|
||||
inc = -1;
|
||||
nbe = matrix.front().size()-1;
|
||||
type = eUpper;
|
||||
}
|
||||
else
|
||||
throw MatrixFormException();
|
||||
|
||||
// Checking if matrix is triangular (upper or lower):
|
||||
// each row has one element more or less than the previous one
|
||||
// and first or last one has one element.
|
||||
matrix_t::const_iterator ir;
|
||||
for (ir = matrix.begin(), ir++; ir != matrix.end(); ir++, nbe += inc)
|
||||
if (ir->size() != nbe)
|
||||
throw MatrixFormException();
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
void
|
||||
SigmaeStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
size_t ic, ic1, ir, ir1;
|
||||
|
||||
output << "M_.Sigma_e = [..." << endl;
|
||||
for (ir = 0; ir < matrix.size(); ir++)
|
||||
{
|
||||
for (ic = 0; ic < matrix.size(); ic++)
|
||||
{
|
||||
if (ic >= ir && matrix_form == eUpper)
|
||||
{
|
||||
ic1 = ic-ir;
|
||||
ir1 = ir;
|
||||
}
|
||||
else if (ic < ir && matrix_form == eUpper)
|
||||
{
|
||||
ic1 = ir-ic;
|
||||
ir1 = ic;
|
||||
}
|
||||
else if (ic > ir && matrix_form == eLower)
|
||||
{
|
||||
ic1 = ir;
|
||||
ir1 = ic;
|
||||
}
|
||||
else // ic <= ir && matrix_form == eLower
|
||||
{
|
||||
ic1 = ic;
|
||||
ir1 = ir;
|
||||
}
|
||||
|
||||
matrix[ir1][ic1]->writeOutput(output);
|
||||
output << " ";
|
||||
}
|
||||
output << ";..." << endl;
|
||||
}
|
||||
output << "];" << endl;
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2015 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SIGMAEINITIALIZATION_HH
|
||||
#define _SIGMAEINITIALIZATION_HH
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "ExprNode.hh"
|
||||
#include "Statement.hh"
|
||||
|
||||
//! Stores a Sigma_e statement
|
||||
class SigmaeStatement : public Statement
|
||||
{
|
||||
public:
|
||||
//! Matrix form (lower or upper triangular) enum
|
||||
enum matrix_form_t
|
||||
{
|
||||
eLower = 0, //!< Lower triangular matrix
|
||||
eUpper = 1 //!< Upper triangular matrix
|
||||
};
|
||||
//! Type of a matrix row
|
||||
typedef vector<expr_t> row_t;
|
||||
//! Type of a complete matrix
|
||||
typedef vector<row_t> matrix_t;
|
||||
|
||||
//! An exception indicating that a matrix is neither upper triangular nor lower triangular
|
||||
class MatrixFormException
|
||||
{
|
||||
};
|
||||
private:
|
||||
//! The matrix
|
||||
const matrix_t matrix;
|
||||
//! Matrix form (lower or upper)
|
||||
const matrix_form_t matrix_form;
|
||||
|
||||
//! Returns the type (upper or lower triangular) of a given matrix
|
||||
/*! Throws an exception if it is neither upper triangular nor lower triangular */
|
||||
static matrix_form_t determineMatrixForm(const matrix_t &matrix) throw (MatrixFormException);
|
||||
|
||||
public:
|
||||
SigmaeStatement(const matrix_t &matrix_arg) throw (MatrixFormException);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,407 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2018 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Statement.hh"
|
||||
#include <boost/xpressive/xpressive.hpp>
|
||||
|
||||
ModFileStructure::ModFileStructure() :
|
||||
check_present(false),
|
||||
steady_present(false),
|
||||
perfect_foresight_solver_present(false),
|
||||
stoch_simul_present(false),
|
||||
estimation_present(false),
|
||||
osr_present(false),
|
||||
osr_params_present(false),
|
||||
optim_weights_present(false),
|
||||
ramsey_model_present(false),
|
||||
ramsey_policy_present(false),
|
||||
discretionary_policy_present(false),
|
||||
planner_objective_present(false),
|
||||
extended_path_present(false),
|
||||
order_option(0),
|
||||
bvar_present(false),
|
||||
svar_identification_present(false),
|
||||
identification_present(false),
|
||||
estimation_analytic_derivation(false),
|
||||
partial_information(false),
|
||||
k_order_solver(false),
|
||||
calibrated_measurement_errors(false),
|
||||
dsge_prior_weight_in_estimated_params(false),
|
||||
dsge_var_calibrated(""),
|
||||
dsge_var_estimated(false),
|
||||
bayesian_irf_present(false),
|
||||
estimation_data_statement_present(false),
|
||||
last_markov_switching_chain(0),
|
||||
calib_smoother_present(false),
|
||||
estim_params_use_calib(false),
|
||||
prior_statement_present(false),
|
||||
std_prior_statement_present(false),
|
||||
corr_prior_statement_present(false),
|
||||
options_statement_present(false),
|
||||
std_options_statement_present(false),
|
||||
corr_options_statement_present(false),
|
||||
ms_dsge_present(false),
|
||||
occbin_option(false),
|
||||
orig_eq_nbr(0),
|
||||
ramsey_eq_nbr(0),
|
||||
steady_state_model_present(false),
|
||||
write_latex_steady_state_model_present(false)
|
||||
{
|
||||
}
|
||||
|
||||
Statement::~Statement()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Statement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Statement::writeCOutput(ostream &output, const string &basename)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Statement::writeJuliaOutput(ostream &output, const string &basename)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Statement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Statement::computingPass()
|
||||
{
|
||||
}
|
||||
|
||||
NativeStatement::NativeStatement(const string &native_statement_arg) :
|
||||
native_statement(native_statement_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NativeStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
using namespace boost::xpressive;
|
||||
string date_regex = "(-?\\d+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4]\\d|5[0-2])))";
|
||||
sregex regex_lookbehind = sregex::compile("(?<!\\$|\\d|[a-zA-Z_]|\\')" + date_regex);
|
||||
sregex regex_dollar = sregex::compile("(\\$)"+date_regex);
|
||||
|
||||
string ns = regex_replace(native_statement, regex_lookbehind, "dates('$&')");
|
||||
ns = regex_replace(ns, regex_dollar, "$2"); //replace $DATE with DATE
|
||||
output << ns << endl;
|
||||
}
|
||||
|
||||
void
|
||||
NativeStatement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
output << "{\"statementName\": \"native\""
|
||||
<< ", \"string\": \"" << native_statement << "\""
|
||||
<< "}";
|
||||
}
|
||||
|
||||
VerbatimStatement::VerbatimStatement(const string &verbatim_statement_arg) :
|
||||
verbatim_statement(verbatim_statement_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
VerbatimStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
output << verbatim_statement << endl;
|
||||
}
|
||||
|
||||
void
|
||||
VerbatimStatement::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
output << "{\"statementName\": \"verbatim\""
|
||||
<< ", \"string\": \"" << verbatim_statement << "\""
|
||||
<< "}";
|
||||
}
|
||||
|
||||
void
|
||||
OptionsList::writeOutput(ostream &output) const
|
||||
{
|
||||
for (num_options_t::const_iterator it = num_options.begin();
|
||||
it != num_options.end(); it++)
|
||||
output << "options_." << it->first << " = " << it->second << ";" << endl;
|
||||
|
||||
for (paired_num_options_t::const_iterator it = paired_num_options.begin();
|
||||
it != paired_num_options.end(); it++)
|
||||
output << "options_." << it->first << " = [" << it->second.first << "; "
|
||||
<< it->second.second << "];" << endl;
|
||||
|
||||
for (string_options_t::const_iterator it = string_options.begin();
|
||||
it != string_options.end(); it++)
|
||||
output << "options_." << it->first << " = '" << it->second << "';" << endl;
|
||||
|
||||
for (date_options_t::const_iterator it = date_options.begin();
|
||||
it != date_options.end(); it++)
|
||||
output << "options_." << it->first << " = " << it->second << ";" << endl;
|
||||
|
||||
for (symbol_list_options_t::const_iterator it = symbol_list_options.begin();
|
||||
it != symbol_list_options.end(); it++)
|
||||
it->second.writeOutput("options_." + it->first, output);
|
||||
|
||||
for (vec_int_options_t::const_iterator it = vector_int_options.begin();
|
||||
it != vector_int_options.end(); it++)
|
||||
{
|
||||
output << "options_." << it->first << " = ";
|
||||
if (it->second.size() > 1)
|
||||
{
|
||||
output << "[";
|
||||
for (vector<int>::const_iterator viit = it->second.begin();
|
||||
viit != it->second.end(); viit++)
|
||||
output << *viit << ";";
|
||||
output << "];" << endl;
|
||||
}
|
||||
else
|
||||
output << it->second.front() << ";" << endl;
|
||||
}
|
||||
|
||||
for (vec_str_options_t::const_iterator it = vector_str_options.begin();
|
||||
it != vector_str_options.end(); it++)
|
||||
{
|
||||
output << "options_." << it->first << " = ";
|
||||
if (it->second.size() > 1)
|
||||
{
|
||||
output << "{";
|
||||
for (vector<string>::const_iterator viit = it->second.begin();
|
||||
viit != it->second.end(); viit++)
|
||||
output << "'" << *viit << "';";
|
||||
output << "};" << endl;
|
||||
}
|
||||
else
|
||||
output << it->second.front() << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OptionsList::writeOutput(ostream &output, const string &option_group) const
|
||||
{
|
||||
// Initialize option_group as an empty struct iff the field does not exist!
|
||||
unsigned idx = option_group.find_last_of(".");
|
||||
if (idx < UINT_MAX)
|
||||
{
|
||||
output << "if ~isfield(" << option_group.substr(0, idx) << ",'" << option_group.substr(idx+1) << "')" << endl;
|
||||
output << " " << option_group << " = struct();" << endl;
|
||||
output << "end" << endl;
|
||||
}
|
||||
else
|
||||
output << option_group << " = struct();" << endl;
|
||||
|
||||
for (num_options_t::const_iterator it = num_options.begin();
|
||||
it != num_options.end(); it++)
|
||||
output << option_group << "." << it->first << " = " << it->second << ";" << endl;
|
||||
|
||||
for (paired_num_options_t::const_iterator it = paired_num_options.begin();
|
||||
it != paired_num_options.end(); it++)
|
||||
output << option_group << "." << it->first << " = [" << it->second.first << "; "
|
||||
<< it->second.second << "];" << endl;
|
||||
|
||||
for (string_options_t::const_iterator it = string_options.begin();
|
||||
it != string_options.end(); it++)
|
||||
output << option_group << "." << it->first << " = '" << it->second << "';" << endl;
|
||||
|
||||
for (date_options_t::const_iterator it = date_options.begin();
|
||||
it != date_options.end(); it++)
|
||||
output << option_group << "." << it->first << " = " << it->second << ";" << endl;
|
||||
|
||||
for (symbol_list_options_t::const_iterator it = symbol_list_options.begin();
|
||||
it != symbol_list_options.end(); it++)
|
||||
it->second.writeOutput(option_group + "." + it->first, output);
|
||||
|
||||
for (vec_int_options_t::const_iterator it = vector_int_options.begin();
|
||||
it != vector_int_options.end(); it++)
|
||||
{
|
||||
output << option_group << "." << it->first << " = ";
|
||||
if (it->second.size() > 1)
|
||||
{
|
||||
output << "[";
|
||||
for (vector<int>::const_iterator viit = it->second.begin();
|
||||
viit != it->second.end(); viit++)
|
||||
output << *viit << ";";
|
||||
output << "];" << endl;
|
||||
}
|
||||
else
|
||||
output << it->second.front() << ";" << endl;
|
||||
}
|
||||
|
||||
for (vec_str_options_t::const_iterator it = vector_str_options.begin();
|
||||
it != vector_str_options.end(); it++)
|
||||
{
|
||||
output << option_group << "." << it->first << " = ";
|
||||
if (it->second.size() > 1)
|
||||
{
|
||||
output << "{";
|
||||
for (vector<string>::const_iterator viit = it->second.begin();
|
||||
viit != it->second.end(); viit++)
|
||||
output << "'" << *viit << "';";
|
||||
output << "};" << endl;
|
||||
}
|
||||
else
|
||||
output << it->second.front() << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OptionsList::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
if (getNumberOfOptions() == 0)
|
||||
return;
|
||||
|
||||
output << "\"options\": {";
|
||||
for (num_options_t::const_iterator it = num_options.begin();
|
||||
it != num_options.end();)
|
||||
{
|
||||
output << "\""<< it->first << "\": " << it->second;
|
||||
it++;
|
||||
if (it != num_options.end()
|
||||
|| !(paired_num_options.empty()
|
||||
&& string_options.empty()
|
||||
&& date_options.empty()
|
||||
&& symbol_list_options.empty()
|
||||
&& vector_int_options.empty()))
|
||||
output << ", ";
|
||||
}
|
||||
|
||||
for (paired_num_options_t::const_iterator it = paired_num_options.begin();
|
||||
it != paired_num_options.end();)
|
||||
{
|
||||
output << "\""<< it->first << "\": [" << it->second.first << " " << it->second.second << "]";
|
||||
it++;
|
||||
if (it != paired_num_options.end()
|
||||
|| !(string_options.empty()
|
||||
&& date_options.empty()
|
||||
&& symbol_list_options.empty()
|
||||
&& vector_int_options.empty()))
|
||||
output << ", ";
|
||||
}
|
||||
|
||||
for (string_options_t::const_iterator it = string_options.begin();
|
||||
it != string_options.end();)
|
||||
{
|
||||
output << "\""<< it->first << "\": \"" << it->second << "\"";
|
||||
it++;
|
||||
if (it != string_options.end()
|
||||
|| !(date_options.empty()
|
||||
&& symbol_list_options.empty()
|
||||
&& vector_int_options.empty()))
|
||||
output << ", ";
|
||||
}
|
||||
|
||||
for (date_options_t::const_iterator it = date_options.begin();
|
||||
it != date_options.end();)
|
||||
{
|
||||
output << "\""<< it->first << "\": \"" << it->second << "\"";
|
||||
it++;
|
||||
if (it != date_options.end()
|
||||
|| !(symbol_list_options.empty()
|
||||
&& vector_int_options.empty()))
|
||||
output << ", ";
|
||||
}
|
||||
|
||||
for (symbol_list_options_t::const_iterator it = symbol_list_options.begin();
|
||||
it != symbol_list_options.end(); it++)
|
||||
{
|
||||
output << "\""<< it->first << "\":";
|
||||
it->second.writeJsonOutput(output);
|
||||
it++;
|
||||
if (it != symbol_list_options.end()
|
||||
|| !vector_int_options.empty())
|
||||
output << ", ";
|
||||
}
|
||||
|
||||
for (vec_int_options_t::const_iterator it = vector_int_options.begin();
|
||||
it != vector_int_options.end();)
|
||||
{
|
||||
output << "\""<< it->first << "\": [";
|
||||
if (it->second.size() > 1)
|
||||
{
|
||||
for (vector<int>::const_iterator viit = it->second.begin();
|
||||
viit != it->second.end();)
|
||||
{
|
||||
output << *viit;
|
||||
viit++;
|
||||
if (viit != it->second.end())
|
||||
output << ", ";
|
||||
}
|
||||
}
|
||||
else
|
||||
output << it->second.front() << endl;
|
||||
output << "]";
|
||||
it++;
|
||||
if (it != vector_int_options.end())
|
||||
output << ", ";
|
||||
}
|
||||
|
||||
|
||||
for (vec_str_options_t::const_iterator it = vector_str_options.begin();
|
||||
it != vector_str_options.end();)
|
||||
{
|
||||
output << "\""<< it->first << "\": [";
|
||||
if (it->second.size() > 1)
|
||||
{
|
||||
for (vector<string>::const_iterator viit = it->second.begin();
|
||||
viit != it->second.end();)
|
||||
{
|
||||
output << "\"" << *viit << "\"";
|
||||
viit++;
|
||||
if (viit != it->second.end())
|
||||
output << ", ";
|
||||
}
|
||||
}
|
||||
else
|
||||
output << it->second.front() << endl;
|
||||
output << "]";
|
||||
it++;
|
||||
if (it != vector_str_options.end())
|
||||
output << ", ";
|
||||
}
|
||||
|
||||
output << "}";
|
||||
}
|
||||
|
||||
void
|
||||
OptionsList::clear()
|
||||
{
|
||||
num_options.clear();
|
||||
paired_num_options.clear();
|
||||
string_options.clear();
|
||||
date_options.clear();
|
||||
symbol_list_options.clear();
|
||||
vector_int_options.clear();
|
||||
vector_str_options.clear();
|
||||
}
|
||||
|
||||
int
|
||||
OptionsList::getNumberOfOptions() const
|
||||
{
|
||||
return num_options.size()
|
||||
+ paired_num_options.size()
|
||||
+ string_options.size()
|
||||
+ date_options.size()
|
||||
+ symbol_list_options.size()
|
||||
+ vector_int_options.size()
|
||||
+ vector_str_options.size();
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _STATEMENT_HH
|
||||
#define _STATEMENT_HH
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "SymbolList.hh"
|
||||
#include "WarningConsolidation.hh"
|
||||
|
||||
class ModFileStructure
|
||||
{
|
||||
public:
|
||||
ModFileStructure();
|
||||
//! Whether check is present
|
||||
bool check_present;
|
||||
//! Whether steady is present
|
||||
bool steady_present;
|
||||
//! Whether a perfect_foresight_solver/simul statement is present
|
||||
bool perfect_foresight_solver_present;
|
||||
//! Whether a stoch_simul statement is present
|
||||
bool stoch_simul_present;
|
||||
//! Whether an estimation statement is present
|
||||
bool estimation_present;
|
||||
//! Whether an osr statement is present
|
||||
bool osr_present;
|
||||
//! Whether an osr params statement is present
|
||||
bool osr_params_present;
|
||||
//! Whether an optim weight statement is present
|
||||
bool optim_weights_present;
|
||||
//! Whether a ramsey_model statement is present
|
||||
bool ramsey_model_present;
|
||||
//! Whether a ramsey_policy statement is present
|
||||
bool ramsey_policy_present;
|
||||
//! Whether a discretionary_objective statement is present
|
||||
bool discretionary_policy_present;
|
||||
//! Whether a planner_objective statement is present
|
||||
bool planner_objective_present;
|
||||
//! Whether an extended_path statement is present
|
||||
bool extended_path_present;
|
||||
//! The value of the "order" option of stoch_simul, estimation, osr, ramsey_policy
|
||||
//! Derivation order
|
||||
/*! First initialized to zero. If user sets order option somewhere in the MOD file, it will be equal to the maximum of order options. Otherwise will default to 2 */
|
||||
int order_option;
|
||||
//! Whether a bvar_density, bvar_forecast, sbvar, ms_sbvar statement is present
|
||||
bool bvar_present;
|
||||
//! Whether an svar_identification statement is present
|
||||
bool svar_identification_present;
|
||||
//! Whether an identification statement is present or the identification option of dynare_sensitivity statement is equal to one
|
||||
bool identification_present;
|
||||
//! Whether the option analytic_derivation is given to estimation
|
||||
bool estimation_analytic_derivation;
|
||||
//! Whether the option partial_information is given to stoch_simul/estimation/osr/ramsey_policy
|
||||
bool partial_information;
|
||||
//! Whether the "k_order_solver" option is used (explictly, or implicitly if order >= 3)
|
||||
bool k_order_solver;
|
||||
//! Whether there is a calibrated measurement error
|
||||
bool calibrated_measurement_errors;
|
||||
//! Whether dsge_prior_weight was initialized as a parameter
|
||||
bool dsge_prior_weight_initialized;
|
||||
//! Whether dsge_prior_weight is in the estimated_params block
|
||||
bool dsge_prior_weight_in_estimated_params;
|
||||
//! Whether there is a dsge_var, with calibrated prior weight
|
||||
string dsge_var_calibrated;
|
||||
//! Whether there is a dsge_var, with prior weight that must be estimated
|
||||
bool dsge_var_estimated;
|
||||
//! Whether there is a bayesian_irf option passed to the estimation statement
|
||||
bool bayesian_irf_present;
|
||||
//! Whether there is a data statement present
|
||||
bool estimation_data_statement_present;
|
||||
//! Last chain number for Markov Switching statement2
|
||||
int last_markov_switching_chain;
|
||||
//! Whether a calib_smoother statement is present
|
||||
bool calib_smoother_present;
|
||||
//! Whether there is an estimated_params_init with use_calibration
|
||||
bool estim_params_use_calib;
|
||||
//! Set of parameters used within shocks blocks, inside the expressions
|
||||
//! defining the values of covariances (stored as symbol ids)
|
||||
set<int> parameters_within_shocks_values;
|
||||
//! Set of estimated parameters (stored as symbol ids)
|
||||
set<int> estimated_parameters;
|
||||
//! Whether there is a prior statement present
|
||||
bool prior_statement_present;
|
||||
//! Whether there is a std prior statement present
|
||||
bool std_prior_statement_present;
|
||||
//! Whether there is a corr prior statement present
|
||||
bool corr_prior_statement_present;
|
||||
//! Whether there is a options statement present
|
||||
bool options_statement_present;
|
||||
//! Whether there is a std options statement present
|
||||
bool std_options_statement_present;
|
||||
//! Whether there is a corr options statement present
|
||||
bool corr_options_statement_present;
|
||||
//! Whether a Markov Switching DSGE is present
|
||||
bool ms_dsge_present;
|
||||
//! Whether occbin is present
|
||||
bool occbin_option;
|
||||
//! Stores the original number of equations in the model_block
|
||||
int orig_eq_nbr;
|
||||
//! Stores the number of equations added to the Ramsey model
|
||||
int ramsey_eq_nbr;
|
||||
//! Whether there was a steady_state_model block
|
||||
bool steady_state_model_present;
|
||||
//! Whether there is a write_latex_steady_state_model statement present
|
||||
bool write_latex_steady_state_model_present;
|
||||
//! Histval values that do not have the appropriate lag
|
||||
map<int, int> hist_vals_wrong_lag;
|
||||
};
|
||||
|
||||
class Statement
|
||||
{
|
||||
public:
|
||||
virtual
|
||||
~Statement();
|
||||
//! Do some internal check, and fill the ModFileStructure class
|
||||
/*! Don't forget to update ComputingTasks.hh, Shocks.hh and
|
||||
NumericalInitialization.hh if you modify the signature of this
|
||||
method. Otherwise the default implementation (i.e. a no-op) will apply and
|
||||
some checks won't be run. */
|
||||
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
|
||||
virtual void computingPass();
|
||||
//! Write Matlab output code
|
||||
/*!
|
||||
\param output is the output stream of the main matlab file
|
||||
\param basename is the name of the modfile (without extension) which can be used to build auxiliary files
|
||||
*/
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const = 0;
|
||||
virtual void writeCOutput(ostream &output, const string &basename);
|
||||
virtual void writeJuliaOutput(ostream &output, const string &basename);
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
class NativeStatement : public Statement
|
||||
{
|
||||
private:
|
||||
const string native_statement;
|
||||
public:
|
||||
NativeStatement(const string &native_statement_arg);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
class VerbatimStatement : public Statement
|
||||
{
|
||||
private:
|
||||
const string verbatim_statement;
|
||||
public:
|
||||
VerbatimStatement(const string &verbatim_statement_arg);
|
||||
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
|
||||
virtual void writeJsonOutput(ostream &output) const;
|
||||
};
|
||||
|
||||
class OptionsList
|
||||
{
|
||||
public:
|
||||
typedef map<string, string> num_options_t;
|
||||
typedef map<string, pair<string, string> > paired_num_options_t;
|
||||
typedef map<string, string> string_options_t;
|
||||
typedef map<string, string> date_options_t;
|
||||
typedef map<string, SymbolList> symbol_list_options_t;
|
||||
typedef map<string, vector<int> > vec_int_options_t;
|
||||
typedef map<string, vector<string > > vec_str_options_t;
|
||||
num_options_t num_options;
|
||||
paired_num_options_t paired_num_options;
|
||||
string_options_t string_options;
|
||||
date_options_t date_options;
|
||||
symbol_list_options_t symbol_list_options;
|
||||
vec_int_options_t vector_int_options;
|
||||
vec_str_options_t vector_str_options;
|
||||
int getNumberOfOptions() const;
|
||||
void writeOutput(ostream &output) const;
|
||||
void writeOutput(ostream &output, const string &option_group) const;
|
||||
void writeJsonOutput(ostream &output) const;
|
||||
void clear();
|
||||
};
|
||||
|
||||
#endif // ! _STATEMENT_HH
|
File diff suppressed because it is too large
Load Diff
|
@ -1,332 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _STATIC_MODEL_HH
|
||||
#define _STATIC_MODEL_HH
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "ModelTree.hh"
|
||||
|
||||
//! Stores a static model, as derived from the "model" block when leads and lags have been removed
|
||||
class StaticModel : public ModelTree
|
||||
{
|
||||
private:
|
||||
//! global temporary terms for block decomposed models
|
||||
vector<vector<temporary_terms_t> > v_temporary_terms;
|
||||
|
||||
//! local temporary terms for block decomposed models
|
||||
vector<vector<temporary_terms_t> > v_temporary_terms_local;
|
||||
|
||||
vector<temporary_terms_inuse_t> v_temporary_terms_inuse;
|
||||
|
||||
typedef map< pair< int, pair< int, int> >, expr_t> first_chain_rule_derivatives_t;
|
||||
first_chain_rule_derivatives_t first_chain_rule_derivatives;
|
||||
|
||||
//! Writes static model file (standard Matlab version)
|
||||
void writeStaticMFile(const string &static_basename) const;
|
||||
|
||||
//! Writes static model file (C version)
|
||||
void writeStaticCFile(const string &func_name) const;
|
||||
|
||||
//! Writes static model file (Julia version)
|
||||
void writeStaticJuliaFile(const string &basename) const;
|
||||
|
||||
//! Writes the static model equations and its derivatives
|
||||
void writeStaticModel(ostream &StaticOutput, bool use_dll, bool julia) const;
|
||||
|
||||
//! Writes the static function calling the block to solve (Matlab version)
|
||||
void writeStaticBlockMFSFile(const string &basename) const;
|
||||
|
||||
//! Writes the Block reordred structure of the model in M output
|
||||
void writeModelEquationsOrdered_M(const string &dynamic_basename) const;
|
||||
|
||||
//! Writes the code of the Block reordred structure of the model in virtual machine bytecode
|
||||
void writeModelEquationsCode_Block(const string file_name, const string bin_basename, map_idx_t map_idx, vector<map_idx_t> map_idx2) const;
|
||||
|
||||
//! Writes the code of the model in virtual machine bytecode
|
||||
void writeModelEquationsCode(const string file_name, const string bin_basename, map_idx_t map_idx) const;
|
||||
|
||||
//! Computes jacobian and prepares for equation normalization
|
||||
/*! Using values from initval/endval blocks and parameter initializations:
|
||||
- computes the jacobian for the model w.r. to contemporaneous variables
|
||||
- removes edges of the incidence matrix when derivative w.r. to the corresponding variable is too close to zero (below the cutoff)
|
||||
*/
|
||||
void evaluateJacobian(const eval_context_t &eval_context, jacob_map_t *j_m, bool dynamic);
|
||||
|
||||
map_idx_t map_idx;
|
||||
|
||||
vector<map_idx_t> map_idx2;
|
||||
|
||||
//! sorts the temporary terms in the blocks order
|
||||
void computeTemporaryTermsOrdered();
|
||||
//! creates a mapping from the index of temporary terms to a natural index
|
||||
void computeTemporaryTermsMapping(temporary_terms_t &temporary_terms, map_idx_t &map_idx);
|
||||
|
||||
//! Write derivative code of an equation w.r. to a variable
|
||||
void compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, map_idx_t &map_idx, temporary_terms_t temporary_terms) const;
|
||||
//! Write chain rule derivative code of an equation w.r. to a variable
|
||||
void compileChainRuleDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int var, int lag, map_idx_t &map_idx, temporary_terms_t temporary_terms) const;
|
||||
|
||||
//! Get the type corresponding to a derivation ID
|
||||
virtual SymbolType getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException);
|
||||
//! Get the lag corresponding to a derivation ID
|
||||
virtual int getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException);
|
||||
//! Get the symbol ID corresponding to a derivation ID
|
||||
virtual int getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException);
|
||||
//! Compute the column indices of the static Jacobian
|
||||
void computeStatJacobianCols();
|
||||
//! return a map on the block jacobian
|
||||
map<pair<pair<int, pair<int, int> >, pair<int, int> >, int> get_Derivatives(int block);
|
||||
//! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables
|
||||
void computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives);
|
||||
//! Collect only the first derivatives
|
||||
map<pair<int, pair<int, int> >, expr_t> collect_first_order_derivatives_endogenous();
|
||||
|
||||
//! Write chain rule derivative of a recursive equation w.r. to a variable
|
||||
void writeChainRuleDerivative(ostream &output, int eq, int var, int lag, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const;
|
||||
|
||||
//! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous
|
||||
void collect_block_first_order_derivatives();
|
||||
|
||||
protected:
|
||||
//! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true
|
||||
bool global_temporary_terms;
|
||||
|
||||
//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation
|
||||
equation_type_and_normalized_equation_t equation_type_and_normalized_equation;
|
||||
|
||||
//! for each block contains pair< Simulation_Type, pair < Block_Size, Recursive_part_Size > >
|
||||
block_type_firstequation_size_mfs_t block_type_firstequation_size_mfs;
|
||||
|
||||
//! for all blocks derivatives description
|
||||
blocks_derivatives_t blocks_derivatives;
|
||||
|
||||
//! The jacobian without the elements below the cutoff
|
||||
dynamic_jacob_map_t dynamic_jacobian;
|
||||
|
||||
//! Vector indicating if the block is linear in endogenous variable (true) or not (false)
|
||||
vector<bool> blocks_linear;
|
||||
|
||||
//! Map the derivatives for a block pair<lag, make_pair(make_pair(eq, var)), expr_t>
|
||||
typedef map<pair< int, pair<int, int> >, expr_t> derivative_t;
|
||||
//! Vector of derivative for each blocks
|
||||
vector<derivative_t> derivative_endo, derivative_other_endo, derivative_exo, derivative_exo_det;
|
||||
|
||||
//!List for each block and for each lag-leag all the other endogenous variables and exogenous variables
|
||||
typedef set<int> var_t;
|
||||
typedef map<int, var_t> lag_var_t;
|
||||
vector<lag_var_t> other_endo_block, exo_block, exo_det_block;
|
||||
|
||||
//! for each block described the number of static, forward, backward and mixed variables in the block
|
||||
/*! pair< pair<static, forward>, pair<backward,mixed> > */
|
||||
vector<pair< pair<int, int>, pair<int, int> > > block_col_type;
|
||||
|
||||
//! List for each variable its block number and its maximum lag and lead inside the block
|
||||
vector<pair<int, pair<int, int> > > variable_block_lead_lag;
|
||||
//! List for each equation its block number
|
||||
vector<int> equation_block;
|
||||
|
||||
//!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous
|
||||
vector<pair<int, int> > endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
|
||||
|
||||
public:
|
||||
StaticModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants, ExternalFunctionsTable &external_functions_table_arg);
|
||||
|
||||
//! Writes information on block decomposition when relevant
|
||||
void writeOutput(ostream &output, bool block) const;
|
||||
|
||||
//! Execute computations (variable sorting + derivation)
|
||||
/*!
|
||||
\param eval_context evaluation context for normalization
|
||||
\param no_tmp_terms if true, no temporary terms will be computed in the static files
|
||||
\param hessian whether 2nd derivatives w.r. to exo, exo_det and endo should be computed
|
||||
\param paramsDerivsOrder order of derivatives w.r. to a pair (endo/exo/exo_det, parameter) to be computed
|
||||
*/
|
||||
void computingPass(const eval_context_t &eval_context, bool no_tmp_terms, bool hessian, bool thirdDerivatices, int paramsDerivsOrder, bool block, bool bytecode, const bool nopreprocessoroutput);
|
||||
|
||||
//! Adds informations for simulation in a binary file for a block decomposed model
|
||||
void Write_Inf_To_Bin_File_Block(const string &static_basename, const string &bin_basename, const int &num,
|
||||
int &u_count_int, bool &file_open) const;
|
||||
|
||||
//! Writes static model file
|
||||
void writeStaticFile(const string &basename, bool block, bool bytecode, bool use_dll, bool julia) const;
|
||||
|
||||
//! Write JSON Output (used by PlannerObjectiveStatement)
|
||||
void writeJsonOutput(ostream &output) const;
|
||||
|
||||
//! Write JSON representation of static model
|
||||
void writeJsonComputingPassOutput(ostream &output, bool writeDetails) const;
|
||||
|
||||
//! Writes file containing static parameters derivatives
|
||||
void writeJsonParamsDerivativesFile(ostream &output, bool writeDetails) const;
|
||||
|
||||
//! Writes file containing static parameters derivatives
|
||||
void writeParamsDerivativesFile(const string &basename, bool julia) const;
|
||||
|
||||
//! Writes LaTeX file with the equations of the static model
|
||||
void writeLatexFile(const string &basename, const bool write_equation_tags) const;
|
||||
|
||||
//! Writes initializations in oo_.steady_state or steady state file for the auxiliary variables
|
||||
void writeAuxVarInitval(ostream &output, ExprNodeOutputType output_type) const;
|
||||
|
||||
//! Writes definition of the auxiliary variables in a .m or .jl file
|
||||
void writeSetAuxiliaryVariables(const string &basename, const bool julia) const;
|
||||
void writeAuxVarRecursiveDefinitions(ostream &output, ExprNodeOutputType output_type) const;
|
||||
void writeLatexAuxVarRecursiveDefinitions(ostream &output) const;
|
||||
void writeJsonAuxVarRecursiveDefinitions(ostream &output) const;
|
||||
|
||||
//! To ensure that no exogenous is present in the planner objective
|
||||
//! See #1264
|
||||
bool exoPresentInEqs() const;
|
||||
|
||||
virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException);
|
||||
virtual void addAllParamDerivId(set<int> &deriv_id_set);
|
||||
|
||||
//! Return the number of blocks
|
||||
virtual unsigned int
|
||||
getNbBlocks() const
|
||||
{
|
||||
return (block_type_firstequation_size_mfs.size());
|
||||
};
|
||||
//! Determine the simulation type of each block
|
||||
virtual BlockSimulationType
|
||||
getBlockSimulationType(int block_number) const
|
||||
{
|
||||
return (block_type_firstequation_size_mfs[block_number].first.first);
|
||||
};
|
||||
//! Return the first equation number of a block
|
||||
virtual unsigned int
|
||||
getBlockFirstEquation(int block_number) const
|
||||
{
|
||||
return (block_type_firstequation_size_mfs[block_number].first.second);
|
||||
};
|
||||
//! Return the size of the block block_number
|
||||
virtual unsigned int
|
||||
getBlockSize(int block_number) const
|
||||
{
|
||||
return (block_type_firstequation_size_mfs[block_number].second.first);
|
||||
};
|
||||
//! Return the number of exogenous variable in the block block_number
|
||||
virtual unsigned int
|
||||
getBlockExoSize(int block_number) const
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
//! Return the number of colums in the jacobian matrix for exogenous variable in the block block_number
|
||||
virtual unsigned int
|
||||
getBlockExoColSize(int block_number) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
//! Return the number of feedback variable of the block block_number
|
||||
virtual unsigned int
|
||||
getBlockMfs(int block_number) const
|
||||
{
|
||||
return (block_type_firstequation_size_mfs[block_number].second.second);
|
||||
};
|
||||
//! Return the maximum lag in a block
|
||||
virtual unsigned int
|
||||
getBlockMaxLag(int block_number) const
|
||||
{
|
||||
return (block_lag_lead[block_number].first);
|
||||
};
|
||||
//! Return the maximum lead in a block
|
||||
virtual unsigned int
|
||||
getBlockMaxLead(int block_number) const
|
||||
{
|
||||
return (block_lag_lead[block_number].second);
|
||||
};
|
||||
//! Return the type of equation (equation_number) belonging to the block block_number
|
||||
virtual EquationType
|
||||
getBlockEquationType(int block_number, int equation_number) const
|
||||
{
|
||||
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first);
|
||||
};
|
||||
//! Return true if the equation has been normalized
|
||||
virtual bool
|
||||
isBlockEquationRenormalized(int block_number, int equation_number) const
|
||||
{
|
||||
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first == E_EVALUATE_S);
|
||||
};
|
||||
//! Return the expr_t of the equation equation_number belonging to the block block_number
|
||||
virtual expr_t
|
||||
getBlockEquationExpr(int block_number, int equation_number) const
|
||||
{
|
||||
return (equations[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]]);
|
||||
};
|
||||
//! Return the expr_t of the renormalized equation equation_number belonging to the block block_number
|
||||
virtual expr_t
|
||||
getBlockEquationRenormalizedExpr(int block_number, int equation_number) const
|
||||
{
|
||||
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].second);
|
||||
};
|
||||
//! Return the original number of equation equation_number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockEquationID(int block_number, int equation_number) const
|
||||
{
|
||||
return (equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]);
|
||||
};
|
||||
//! Return the original number of variable variable_number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockVariableID(int block_number, int variable_number) const
|
||||
{
|
||||
return (variable_reordered[block_type_firstequation_size_mfs[block_number].first.second+variable_number]);
|
||||
};
|
||||
//! Return the original number of the exogenous variable varexo_number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockVariableExoID(int block_number, int variable_number) const
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
//! Return the position of equation_number in the block number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockInitialEquationID(int block_number, int equation_number) const
|
||||
{
|
||||
return ((int) inv_equation_reordered[equation_number] - (int) block_type_firstequation_size_mfs[block_number].first.second);
|
||||
};
|
||||
//! Return the position of variable_number in the block number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockInitialVariableID(int block_number, int variable_number) const
|
||||
{
|
||||
return ((int) inv_variable_reordered[variable_number] - (int) block_type_firstequation_size_mfs[block_number].first.second);
|
||||
};
|
||||
//! Return the position of variable_number in the block number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockInitialExogenousID(int block_number, int variable_number) const
|
||||
{
|
||||
return -1;
|
||||
};
|
||||
//! Return the position of the deterministic exogenous variable_number in the block number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockInitialDetExogenousID(int block_number, int variable_number) const
|
||||
{
|
||||
return -1;
|
||||
};
|
||||
//! Return the position of the other endogenous variable_number in the block number belonging to the block block_number
|
||||
virtual int
|
||||
getBlockInitialOtherEndogenousID(int block_number, int variable_number) const
|
||||
{
|
||||
return -1;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,316 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
#include "SteadyStateModel.hh"
|
||||
|
||||
SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg, const StaticModel &static_model_arg) :
|
||||
DataTree(symbol_table_arg, num_constants_arg, external_functions_table_arg), static_model(static_model_arg)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SteadyStateModel::addDefinition(int symb_id, expr_t expr)
|
||||
{
|
||||
AddVariable(symb_id); // Create the variable node to be used in write method
|
||||
|
||||
assert(symbol_table.getType(symb_id) == eEndogenous
|
||||
|| symbol_table.getType(symb_id) == eModFileLocalVariable
|
||||
|| symbol_table.getType(symb_id) == eParameter);
|
||||
|
||||
// Add the variable
|
||||
vector<int> v;
|
||||
v.push_back(symb_id);
|
||||
def_table.push_back(make_pair(v, expr));
|
||||
}
|
||||
|
||||
void
|
||||
SteadyStateModel::addMultipleDefinitions(const vector<int> &symb_ids, expr_t expr)
|
||||
{
|
||||
for (size_t i = 0; i < symb_ids.size(); i++)
|
||||
{
|
||||
AddVariable(symb_ids[i]); // Create the variable nodes to be used in write method
|
||||
assert(symbol_table.getType(symb_ids[i]) == eEndogenous
|
||||
|| symbol_table.getType(symb_ids[i]) == eModFileLocalVariable
|
||||
|| symbol_table.getType(symb_ids[i]) == eParameter);
|
||||
}
|
||||
def_table.push_back(make_pair(symb_ids, expr));
|
||||
}
|
||||
|
||||
void
|
||||
SteadyStateModel::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) const
|
||||
{
|
||||
if (def_table.size() == 0)
|
||||
return;
|
||||
|
||||
mod_file_struct.steady_state_model_present = true;
|
||||
vector<int> so_far_defined;
|
||||
|
||||
for (size_t i = 0; i < def_table.size(); i++)
|
||||
{
|
||||
const vector<int> &symb_ids = def_table[i].first;
|
||||
|
||||
// Check that symbols are not already defined
|
||||
for (size_t j = 0; j < symb_ids.size(); j++)
|
||||
if (find(so_far_defined.begin(), so_far_defined.end(), symb_ids[j])
|
||||
!= so_far_defined.end())
|
||||
warnings << "WARNING: in the 'steady_state_model' block, variable '" << symbol_table.getName(symb_ids[j]) << "' is declared twice" << endl;
|
||||
|
||||
// Check that expression has no undefined symbol
|
||||
if (!mod_file_struct.ramsey_model_present)
|
||||
{
|
||||
set<int> used_symbols;
|
||||
const expr_t &expr = def_table[i].second;
|
||||
expr->collectVariables(eEndogenous, used_symbols);
|
||||
expr->collectVariables(eModFileLocalVariable, used_symbols);
|
||||
for (set<int>::const_iterator it = used_symbols.begin();
|
||||
it != used_symbols.end(); ++it)
|
||||
if (find(so_far_defined.begin(), so_far_defined.end(), *it)
|
||||
== so_far_defined.end())
|
||||
{
|
||||
cerr << "ERROR: in the 'steady_state_model' block, variable '" << symbol_table.getName(*it)
|
||||
<< "' is undefined in the declaration of variable '" << symbol_table.getName(symb_ids[0]) << "'" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
copy(symb_ids.begin(), symb_ids.end(), back_inserter(so_far_defined));
|
||||
}
|
||||
|
||||
set<int> orig_endogs = symbol_table.getOrigEndogenous();
|
||||
for (set<int>::const_iterator it = orig_endogs.begin();
|
||||
it != orig_endogs.end(); ++it)
|
||||
{
|
||||
if (find(so_far_defined.begin(), so_far_defined.end(), *it)
|
||||
== so_far_defined.end())
|
||||
warnings << "WARNING: in the 'steady_state_model' block, variable '" << symbol_table.getName(*it) << "' is not assigned a value" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SteadyStateModel::writeLatexSteadyStateFile(const string &basename) const
|
||||
{
|
||||
ofstream output, content_output;
|
||||
string filename = basename + "_steady_state.tex";
|
||||
string content_basename = basename + "_steady_state_content";
|
||||
string content_filename = content_basename + ".tex";
|
||||
|
||||
output.open(filename.c_str(), ios::out | ios::binary);
|
||||
if (!output.is_open())
|
||||
{
|
||||
cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
content_output.open(content_filename.c_str(), ios::out | ios::binary);
|
||||
if (!content_output.is_open())
|
||||
{
|
||||
cerr << "ERROR: Can't open file " << content_filename << " for writing" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
output << "\\documentclass[10pt,a4paper]{article}" << endl
|
||||
<< "\\usepackage[landscape]{geometry}" << endl
|
||||
<< "\\usepackage{fullpage}" << endl
|
||||
<< "\\usepackage{amsfonts}" << endl
|
||||
<< "\\usepackage{breqn}" << endl
|
||||
<< "\\begin{document}" << endl
|
||||
<< "\\footnotesize" << endl;
|
||||
|
||||
for (vector<pair<vector<int>, expr_t> >::const_iterator it = def_table.begin();
|
||||
it != def_table.end(); it++)
|
||||
for (vector<int>::const_iterator it1 = it->first.begin(); it1 != it->first.end(); it1++)
|
||||
{
|
||||
int id = *it1;
|
||||
expr_t value = it->second;
|
||||
content_output << "\\begin{dmath}" << endl
|
||||
<< symbol_table.getTeXName(id) << " = ";
|
||||
value->writeOutput(content_output, oLatexStaticModel);
|
||||
content_output << endl << "\\end{dmath}" << endl;
|
||||
}
|
||||
|
||||
static_model.writeLatexAuxVarRecursiveDefinitions(content_output);
|
||||
|
||||
output << "\\include{" << content_basename << "}" << endl
|
||||
<< "\\end{document}" << endl;
|
||||
|
||||
output.close();
|
||||
content_output.close();
|
||||
}
|
||||
|
||||
void
|
||||
SteadyStateModel::writeSteadyStateFile(const string &basename, bool ramsey_model, bool julia) const
|
||||
{
|
||||
if (def_table.size() == 0)
|
||||
return;
|
||||
|
||||
string filename = julia ? basename + "SteadyState2.jl" : basename + "_steadystate2.m";
|
||||
ofstream output;
|
||||
output.open(filename.c_str(), ios::out | ios::binary);
|
||||
if (!output.is_open())
|
||||
{
|
||||
cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ExprNodeOutputType output_type = (julia ? oJuliaSteadyStateFile : oSteadyStateFile);
|
||||
|
||||
if (!julia)
|
||||
output << "function [ys_, params, info] = " << basename << "_steadystate2("
|
||||
<< "ys_, exo_, params)" << endl
|
||||
<< "% Steady state generated by Dynare preprocessor" << endl
|
||||
<< " info = 0;" << endl;
|
||||
else
|
||||
output << "module " << basename << "SteadyState2" << endl
|
||||
<< "#" << endl
|
||||
<< "# NB: this file was automatically generated by Dynare" << endl
|
||||
<< "# from " << basename << ".mod" << endl
|
||||
<< "#" << endl
|
||||
<< "export steady_state!" << endl << endl
|
||||
<< "function steady_state!(ys_::Vector{Float64}, exo_::Vector{Float64}, "
|
||||
<< "params::Vector{Float64})" << endl;
|
||||
|
||||
for (size_t i = 0; i < def_table.size(); i++)
|
||||
{
|
||||
const vector<int> &symb_ids = def_table[i].first;
|
||||
output << " ";
|
||||
if (symb_ids.size() > 1)
|
||||
output << "[";
|
||||
for (size_t j = 0; j < symb_ids.size(); j++)
|
||||
{
|
||||
variable_node_map_t::const_iterator it = variable_node_map.find(make_pair(symb_ids[j], 0));
|
||||
assert(it != variable_node_map.end());
|
||||
dynamic_cast<ExprNode *>(it->second)->writeOutput(output, output_type);
|
||||
if (j < symb_ids.size()-1)
|
||||
output << ",";
|
||||
}
|
||||
if (symb_ids.size() > 1)
|
||||
output << "]";
|
||||
|
||||
output << "=";
|
||||
def_table[i].second->writeOutput(output, output_type);
|
||||
output << ";" << endl;
|
||||
}
|
||||
if (!julia)
|
||||
output << " % Auxiliary equations" << endl;
|
||||
else
|
||||
output << " # Auxiliary equations" << endl;
|
||||
static_model.writeAuxVarRecursiveDefinitions(output, output_type);
|
||||
|
||||
if (!julia)
|
||||
output << " check_=0;" << endl;
|
||||
|
||||
output << "end" << endl;
|
||||
if (julia)
|
||||
output << "end" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
SteadyStateModel::writeSteadyStateFileC(const string &basename, bool ramsey_model) const
|
||||
{
|
||||
string filename = basename + "_steadystate.c";
|
||||
|
||||
ofstream output;
|
||||
output.open(filename.c_str(), ios::out | ios::binary);
|
||||
if (!output.is_open())
|
||||
{
|
||||
cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
output << "#include <math.h>" << endl;
|
||||
|
||||
output << "void steadystate("
|
||||
<< "const double *exo_, const double *params, double *ys_, int *info)" << endl
|
||||
<< "// Steady state file generated by Dynare preprocessor" << endl
|
||||
<< "{" << endl
|
||||
<< " *info = 0;" << endl;
|
||||
|
||||
if (def_table.size() == 0)
|
||||
{
|
||||
output << " return;" << endl
|
||||
<< "}" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < def_table.size(); i++)
|
||||
{
|
||||
const vector<int> &symb_ids = def_table[i].first;
|
||||
output << " ";
|
||||
if (symb_ids.size() > 1)
|
||||
std::cout << "Error: in C, multiple returns are not permitted in steady_state_model" << std::endl;
|
||||
variable_node_map_t::const_iterator it = variable_node_map.find(make_pair(symb_ids[0], 0));
|
||||
assert(it != variable_node_map.end());
|
||||
if (it->second->get_type() == eModFileLocalVariable)
|
||||
output << "double ";
|
||||
dynamic_cast<ExprNode *>(it->second)->writeOutput(output, oCSteadyStateFile);
|
||||
output << "=";
|
||||
def_table[i].second->writeOutput(output, oCSteadyStateFile);
|
||||
output << ";" << endl;
|
||||
}
|
||||
output << " // Auxiliary equations" << endl;
|
||||
static_model.writeAuxVarInitval(output, oCSteadyStateFile);
|
||||
output << "}" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
SteadyStateModel::writeJsonSteadyStateFile(ostream &output, bool transformComputingPass) const
|
||||
{
|
||||
if (def_table.size() == 0)
|
||||
return;
|
||||
|
||||
deriv_node_temp_terms_t tef_terms;
|
||||
vector<pair<string, string> > eqtags;
|
||||
temporary_terms_t tt_empty;
|
||||
|
||||
output << "{\"steady_state_model\": [";
|
||||
|
||||
for (size_t i = 0; i < def_table.size(); i++)
|
||||
{
|
||||
const vector<int> &symb_ids = def_table[i].first;
|
||||
if (i != 0)
|
||||
output << ",";
|
||||
output << "{\"lhs\": ";
|
||||
if (symb_ids.size() > 1)
|
||||
output << "[";
|
||||
for (size_t j = 0; j < symb_ids.size(); j++)
|
||||
{
|
||||
if (j != 0)
|
||||
output << ",";
|
||||
variable_node_map_t::const_iterator it =
|
||||
variable_node_map.find(make_pair(symb_ids[j], 0));
|
||||
assert(it != variable_node_map.end());
|
||||
output << "\"";
|
||||
dynamic_cast<ExprNode *>(it->second)->writeJsonOutput(output, tt_empty, tef_terms, false);
|
||||
output << "\"";
|
||||
}
|
||||
if (symb_ids.size() > 1)
|
||||
output << "]";
|
||||
output << ", \"rhs\":\"";
|
||||
def_table[i].second->writeJsonOutput(output, tt_empty, tef_terms, false);
|
||||
output << "\"}" << endl;
|
||||
}
|
||||
|
||||
if (transformComputingPass)
|
||||
static_model.writeJsonAuxVarRecursiveDefinitions(output);
|
||||
|
||||
output << "]}";
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _STEADY_STATE_MODEL_HH
|
||||
#define _STEADY_STATE_MODEL_HH
|
||||
|
||||
#include "DataTree.hh"
|
||||
#include "Statement.hh"
|
||||
#include "StaticModel.hh"
|
||||
#include "WarningConsolidation.hh"
|
||||
|
||||
class SteadyStateModel : public DataTree
|
||||
{
|
||||
private:
|
||||
//! Associates a set of symbol IDs (the variable(s) assigned in a given statement) to an expression (their assigned value)
|
||||
vector<pair<vector<int>, expr_t> > def_table;
|
||||
|
||||
//! Reference to static model (for writing auxiliary equations)
|
||||
const StaticModel &static_model;
|
||||
|
||||
public:
|
||||
SteadyStateModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg, const StaticModel &static_model_arg);
|
||||
//! Add an expression of the form "var = expr;"
|
||||
void addDefinition(int symb_id, expr_t expr);
|
||||
//! Add an expression of the form "[ var1, var2, ... ] = expr;"
|
||||
void addMultipleDefinitions(const vector<int> &symb_ids, expr_t expr);
|
||||
//! Checks that definitions are in a recursive order, and that no variable is declared twice
|
||||
/*!
|
||||
\param[in] ramsey_model Is there a Ramsey model in the MOD file? If yes, then disable the check on the recursivity of the declarations
|
||||
*/
|
||||
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) const;
|
||||
//! Write the steady state file
|
||||
/*!
|
||||
\param[in] ramsey_model Is there a Ramsey model in the MOD file? If yes, then use the "ys" in argument of the steady state file as initial values
|
||||
*/
|
||||
void writeSteadyStateFile(const string &basename, bool ramsey_model, bool julia) const;
|
||||
void writeSteadyStateFileC(const string &basename, bool ramsey_model) const;
|
||||
//! Writes LaTeX file with the equations of the dynamic model (for the steady state model)
|
||||
void writeLatexSteadyStateFile(const string &basename) const;
|
||||
//! Writes JSON output
|
||||
void writeJsonSteadyStateFile(ostream &output, bool transformComputingPass) const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2018 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SymbolList.hh"
|
||||
|
||||
void
|
||||
SymbolList::addSymbol(const string &symbol)
|
||||
{
|
||||
symbols.push_back(symbol);
|
||||
}
|
||||
|
||||
void
|
||||
SymbolList::writeOutput(const string &varname, ostream &output) const
|
||||
{
|
||||
output << varname << " = {";
|
||||
for (vector<string>::const_iterator it = symbols.begin();
|
||||
it != symbols.end(); ++it)
|
||||
{
|
||||
if (it != symbols.begin())
|
||||
output << ";";
|
||||
output << "'" << *it << "'";
|
||||
}
|
||||
output << "};" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
SymbolList::writeJsonOutput(ostream &output) const
|
||||
{
|
||||
output << "\"symbol_list\": [";
|
||||
for (vector<string>::const_iterator it = symbols.begin();
|
||||
it != symbols.end(); ++it)
|
||||
{
|
||||
if (it != symbols.begin())
|
||||
output << ",";
|
||||
output << "\"" << *it << "\"";
|
||||
}
|
||||
output << "]";
|
||||
}
|
||||
|
||||
void
|
||||
SymbolList::clear()
|
||||
{
|
||||
symbols.clear();
|
||||
}
|
||||
|
||||
int
|
||||
SymbolList::getSize() const
|
||||
{
|
||||
return symbols.size();
|
||||
}
|
||||
|
||||
vector<string>
|
||||
SymbolList::getSymbols() const
|
||||
{
|
||||
return symbols;
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SYMBOL_LIST_HH
|
||||
#define _SYMBOL_LIST_HH
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//! Used to store a list of symbols
|
||||
/*! This class is no more than a vector<string>, with a pretty-printer for Matlab */
|
||||
class SymbolList
|
||||
{
|
||||
private:
|
||||
//! Internal container for symbol list
|
||||
vector<string> symbols;
|
||||
public:
|
||||
//! Adds a symbol to the list
|
||||
void addSymbol(const string &symbol);
|
||||
//! Output content in Matlab format
|
||||
/*! Creates a string array for Matlab, stored in variable "varname" */
|
||||
void writeOutput(const string &varname, ostream &output) const;
|
||||
//! Output content in Matlab format without preceding varname of writeOutput
|
||||
void write(ostream &output) const;
|
||||
//! Write JSON output
|
||||
void writeJsonOutput(ostream &output) const;
|
||||
//! Clears all content
|
||||
void clear();
|
||||
//! Get a copy of the string vector
|
||||
vector<string>
|
||||
get_symbols() const
|
||||
{
|
||||
return symbols;
|
||||
};
|
||||
//! Is Empty
|
||||
int
|
||||
empty() const
|
||||
{
|
||||
return symbols.empty();
|
||||
};
|
||||
//! Return the number of Symbols contained in the list
|
||||
int getSize() const;
|
||||
//! Return the list of symbols
|
||||
vector<string> getSymbols() const;
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,513 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2018 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SYMBOLTABLE_HH
|
||||
#define _SYMBOLTABLE_HH
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <ostream>
|
||||
|
||||
#include "CodeInterpreter.hh"
|
||||
#include "ExprNode.hh"
|
||||
|
||||
typedef class ExprNode *expr_t;
|
||||
|
||||
//! Types of auxiliary variables
|
||||
enum aux_var_t
|
||||
{
|
||||
avEndoLead = 0, //!< Substitute for endo leads >= 2
|
||||
avEndoLag = 1, //!< Substitute for endo lags >= 2
|
||||
avExoLead = 2, //!< Substitute for exo leads >= 2
|
||||
avExoLag = 3, //!< Substitute for exo lags >= 2
|
||||
avExpectation = 4, //!< Substitute for Expectation Operator
|
||||
avDiffForward = 5, //!< Substitute for the differentiate of a forward variable
|
||||
avMultiplier = 6, //!< Multipliers for FOC of Ramsey Problem
|
||||
avVarModel = 7, //!< Variable for var_model with order > abs(min_lag()) present in model
|
||||
avDiff = 8 //!< Variable for Diff operator
|
||||
};
|
||||
|
||||
//! Information on some auxiliary variables
|
||||
class AuxVarInfo
|
||||
{
|
||||
private:
|
||||
int symb_id; //!< Symbol ID of the auxiliary variable
|
||||
aux_var_t type; //!< Its type
|
||||
int orig_symb_id; //!< Symbol ID of the endo of the original model represented by this aux var. Only used for avEndoLag and avExoLag.
|
||||
int orig_lead_lag; //!< Lead/lag of the endo of the original model represented by this aux var. Only used for avEndoLag and avExoLag.
|
||||
int equation_number_for_multiplier; //!< Stores the original constraint equation number associated with this aux var. Only used for avMultiplier.
|
||||
int information_set; //! Argument of expectation operator. Only used for avExpectation.
|
||||
expr_t expr_node; //! Auxiliary variable definition
|
||||
public:
|
||||
AuxVarInfo(int symb_id_arg, aux_var_t type_arg, int orig_symb_id, int orig_lead_lag, int equation_number_for_multiplier_arg, int information_set_arg, expr_t expr_node_arg);
|
||||
int
|
||||
get_symb_id() const
|
||||
{
|
||||
return symb_id;
|
||||
};
|
||||
aux_var_t
|
||||
get_type() const
|
||||
{
|
||||
return type;
|
||||
};
|
||||
int
|
||||
get_orig_symb_id() const
|
||||
{
|
||||
return orig_symb_id;
|
||||
};
|
||||
int
|
||||
get_orig_lead_lag() const
|
||||
{
|
||||
return orig_lead_lag;
|
||||
};
|
||||
int
|
||||
get_equation_number_for_multiplier() const
|
||||
{
|
||||
return equation_number_for_multiplier;
|
||||
};
|
||||
int
|
||||
get_information_set() const
|
||||
{
|
||||
return information_set;
|
||||
};
|
||||
expr_t
|
||||
get_expr_node() const
|
||||
{
|
||||
return expr_node;
|
||||
};
|
||||
};
|
||||
|
||||
//! Stores the symbol table
|
||||
/*!
|
||||
A symbol is given by its name, and is internally represented by a unique integer.
|
||||
|
||||
When method freeze() is called, computes a distinct sequence of IDs for some types
|
||||
(endogenous, exogenous, parameters), which are used by the Matlab/Octave functions.
|
||||
We call these "type specific IDs".
|
||||
|
||||
Also manages a TeX name for each symbol, which by default is an empty string.
|
||||
*/
|
||||
class SymbolTable
|
||||
{
|
||||
private:
|
||||
//! Has method freeze() been called?
|
||||
bool frozen;
|
||||
|
||||
typedef map<string, int> symbol_table_type;
|
||||
//! Maps strings to symbol IDs
|
||||
symbol_table_type symbol_table;
|
||||
|
||||
//! Maps IDs to names
|
||||
vector<string> name_table;
|
||||
//! Maps IDs to TeX names
|
||||
vector<string> tex_name_table;
|
||||
//! Maps IDs to string names of variables
|
||||
vector<string> long_name_table;
|
||||
//! Maps IDs to a pair containing the partition and the partition value
|
||||
map<int, map<string, string> > partition_value_map;
|
||||
//! Maps IDs to types
|
||||
vector<SymbolType> type_table;
|
||||
|
||||
//! Maps symbol IDs to type specific IDs
|
||||
vector<int> type_specific_ids;
|
||||
|
||||
//! Maps type specific IDs of endogenous to symbol IDs
|
||||
vector<int> endo_ids;
|
||||
//! Maps type specific IDs of exogenous to symbol IDs
|
||||
vector<int> exo_ids;
|
||||
//! Maps type specific IDs of exogenous deterministic to symbol IDs
|
||||
vector<int> exo_det_ids;
|
||||
//! Maps type specific IDs of parameters to symbol IDs
|
||||
vector<int> param_ids;
|
||||
//! Information about auxiliary variables
|
||||
vector<AuxVarInfo> aux_vars;
|
||||
|
||||
//! Stores the predetermined variables (by symbol IDs)
|
||||
set<int> predetermined_variables;
|
||||
|
||||
//! Stores the list of observed variables
|
||||
vector<int> varobs;
|
||||
|
||||
//! Stores the list of observed exogenous variables
|
||||
vector<int> varexobs;
|
||||
|
||||
public:
|
||||
SymbolTable();
|
||||
//! Thrown when trying to access an unknown symbol (by name)
|
||||
class UnknownSymbolNameException
|
||||
{
|
||||
public:
|
||||
//! Symbol name
|
||||
string name;
|
||||
UnknownSymbolNameException(const string &name_arg) : name(name_arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
//! Thrown when trying to access an unknown symbol (by id)
|
||||
class UnknownSymbolIDException
|
||||
{
|
||||
public:
|
||||
//! Symbol ID
|
||||
int id;
|
||||
UnknownSymbolIDException(int id_arg) : id(id_arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
//! Thrown when trying to access an unknown type specific ID
|
||||
class UnknownTypeSpecificIDException
|
||||
{
|
||||
public:
|
||||
int tsid;
|
||||
SymbolType type;
|
||||
UnknownTypeSpecificIDException(int tsid_arg, SymbolType type_arg) : tsid(tsid_arg), type(type_arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
//! Thrown when trying to declare a symbol twice
|
||||
class AlreadyDeclaredException
|
||||
{
|
||||
public:
|
||||
//! Symbol name
|
||||
string name;
|
||||
//! Was the previous declaration done with the same symbol type ?
|
||||
bool same_type;
|
||||
AlreadyDeclaredException(const string &name_arg, bool same_type_arg) : name(name_arg), same_type(same_type_arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
//! Thrown when table is frozen and trying to modify it
|
||||
class FrozenException
|
||||
{
|
||||
};
|
||||
//! Thrown when trying to use the result of freeze() while this method has not yet been called
|
||||
class NotYetFrozenException
|
||||
{
|
||||
};
|
||||
//! Thrown when searchAuxiliaryVars() failed
|
||||
class SearchFailedException
|
||||
{
|
||||
public:
|
||||
int orig_symb_id, orig_lead_lag, symb_id;
|
||||
SearchFailedException(int orig_symb_id_arg, int orig_lead_lag_arg) : orig_symb_id(orig_symb_id_arg),
|
||||
orig_lead_lag(orig_lead_lag_arg)
|
||||
{
|
||||
}
|
||||
SearchFailedException(int symb_id_arg) : symb_id(symb_id_arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
//! Factorized code for adding aux lag variables
|
||||
int addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag, expr_t arg) throw (FrozenException);
|
||||
//! Factorized code for adding aux lead variables
|
||||
int addLeadAuxiliaryVarInternal(bool endo, int index, expr_t arg) throw (FrozenException);
|
||||
//! Factorized code for Json writing
|
||||
void writeJsonVarVector(ostream &output, const vector<int> &varvec) const;
|
||||
//! Factorized code for asserting that 0 <= symb_id <= symbol_table.size()
|
||||
inline void validateSymbID(int symb_id) const throw (UnknownSymbolIDException);
|
||||
public:
|
||||
//! Add a symbol
|
||||
/*! Returns the symbol ID */
|
||||
int addSymbol(const string &name, SymbolType type, const string &tex_name, const vector<pair<string *, string *> *> *partition_value) throw (AlreadyDeclaredException, FrozenException);
|
||||
//! Add a symbol without its TeX name (will be equal to its name)
|
||||
/*! Returns the symbol ID */
|
||||
int addSymbol(const string &name, SymbolType type) throw (AlreadyDeclaredException, FrozenException);
|
||||
//! Adds an auxiliary variable for endogenous with lead >= 2
|
||||
/*!
|
||||
\param[in] index Used to construct the variable name
|
||||
\return the symbol ID of the new symbol */
|
||||
int addEndoLeadAuxiliaryVar(int index, expr_t arg) throw (FrozenException);
|
||||
//! Adds an auxiliary variable for endogenous with lag >= 2
|
||||
/*!
|
||||
\param[in] orig_symb_id symbol ID of the endogenous declared by the user that this new variable will represent
|
||||
\param[in] orig_lead_lag lag value such that this new variable will be equivalent to orig_symb_id(orig_lead_lag)
|
||||
\return the symbol ID of the new symbol */
|
||||
int addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t arg) throw (FrozenException);
|
||||
//! Adds an auxiliary variable for endogenous with lead >= 1
|
||||
/*!
|
||||
\param[in] index Used to construct the variable name
|
||||
\return the symbol ID of the new symbol */
|
||||
int addExoLeadAuxiliaryVar(int index, expr_t arg) throw (FrozenException);
|
||||
//! Adds an auxiliary variable for exogenous with lag >= 1
|
||||
/*!
|
||||
\param[in] orig_symb_id symbol ID of the exogenous declared by the user that this new variable will represent
|
||||
\param[in] orig_lead_lag lag value such that this new variable will be equivalent to orig_symb_id(orig_lead_lag)
|
||||
\return the symbol ID of the new symbol */
|
||||
int addExoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t arg) throw (FrozenException);
|
||||
//! Adds an auxiliary variable for the expectation operator
|
||||
/*!
|
||||
\param[in] information_set information set (possibly negative) of the expectation operator
|
||||
\param[in] index Used to construct the variable name
|
||||
\return the symbol ID of the new symbol
|
||||
*/
|
||||
int addExpectationAuxiliaryVar(int information_set, int index, expr_t arg) throw (FrozenException);
|
||||
//! Adds an auxiliary variable for the multiplier for the FOCs of the Ramsey Problem
|
||||
/*!
|
||||
\param[in] index Used to construct the variable name
|
||||
\return the symbol ID of the new symbol
|
||||
*/
|
||||
int addMultiplierAuxiliaryVar(int index) throw (FrozenException);
|
||||
//! Adds an auxiliary variable for the (time) differentiate of a forward var
|
||||
/*!
|
||||
\param[in] orig_symb_id The symb_id of the forward variable
|
||||
\return the symbol ID of the new symbol
|
||||
*/
|
||||
int addDiffForwardAuxiliaryVar(int orig_symb_id, expr_t arg) throw (FrozenException);
|
||||
//! Searches auxiliary variables which are substitutes for a given symbol_id and lead/lag
|
||||
/*!
|
||||
The search is only performed among auxiliary variables of endo/exo lag.
|
||||
\return the symbol ID of the auxiliary variable
|
||||
Throws an exception if match not found.
|
||||
*/
|
||||
int searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const throw (SearchFailedException);
|
||||
//! Serches aux_vars for the aux var represented by aux_var_symb_id and returns its associated orig_symb_id
|
||||
int getOrigSymbIdForAuxVar(int aux_var_symb_id) const throw (UnknownSymbolIDException);
|
||||
//! Adds an auxiliary variable when var_model is used with an order that is greater in absolute value
|
||||
//! than the largest lag present in the model.
|
||||
int addVarModelEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) throw (AlreadyDeclaredException, FrozenException);
|
||||
//! Adds an auxiliary variable when the diff operator is encountered
|
||||
int addDiffAuxiliaryVar(int index, expr_t expr_arg) throw (FrozenException);
|
||||
int addDiffAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, int orig_lag) throw (FrozenException);
|
||||
//! Returns the number of auxiliary variables
|
||||
int
|
||||
AuxVarsSize() const
|
||||
{
|
||||
return aux_vars.size();
|
||||
};
|
||||
//! Retruns expr_node for an auxiliary variable
|
||||
expr_t getAuxiliaryVarsExprNode(int symb_id) const throw (SearchFailedException);
|
||||
//! Tests if symbol already exists
|
||||
inline bool exists(const string &name) const;
|
||||
//! Get symbol name (by ID)
|
||||
inline string getName(int id) const throw (UnknownSymbolIDException);
|
||||
//! Get TeX name
|
||||
inline string getTeXName(int id) const throw (UnknownSymbolIDException);
|
||||
//! Get long name
|
||||
inline string getLongName(int id) const throw (UnknownSymbolIDException);
|
||||
//! Returns true if the partition name is the first encountered for the type of variable represented by id
|
||||
bool isFirstOfPartitionForType(int id) const throw (UnknownSymbolIDException);
|
||||
//! Returns a list of partitions and symbols that belong to that partition
|
||||
map<string, map<int, string> > getPartitionsForType(enum SymbolType st) const throw (UnknownSymbolIDException);
|
||||
//! Get type (by ID)
|
||||
inline SymbolType getType(int id) const throw (UnknownSymbolIDException);
|
||||
//! Get type (by name)
|
||||
inline SymbolType getType(const string &name) const throw (UnknownSymbolNameException);
|
||||
//! Get ID (by name)
|
||||
inline int getID(const string &name) const throw (UnknownSymbolNameException);
|
||||
//! Get ID (by type specific ID)
|
||||
int getID(SymbolType type, int tsid) const throw (UnknownTypeSpecificIDException, NotYetFrozenException);
|
||||
//! Freeze symbol table
|
||||
void freeze() throw (FrozenException);
|
||||
//! unreeze symbol table
|
||||
//! Used after having written JSON files
|
||||
void unfreeze();
|
||||
//! Change the type of a symbol
|
||||
void changeType(int id, SymbolType newtype) throw (UnknownSymbolIDException, FrozenException);
|
||||
//! Get type specific ID (by symbol ID)
|
||||
inline int getTypeSpecificID(int id) const throw (UnknownSymbolIDException, NotYetFrozenException);
|
||||
//! Get type specific ID (by symbol name)
|
||||
inline int getTypeSpecificID(const string &name) const throw (UnknownSymbolNameException, NotYetFrozenException);
|
||||
//! Get number of endogenous variables
|
||||
inline int endo_nbr() const throw (NotYetFrozenException);
|
||||
//! Get number of exogenous variables
|
||||
inline int exo_nbr() const throw (NotYetFrozenException);
|
||||
//! Get number of exogenous deterministic variables
|
||||
inline int exo_det_nbr() const throw (NotYetFrozenException);
|
||||
//! Get number of parameters
|
||||
inline int param_nbr() const throw (NotYetFrozenException);
|
||||
//! Returns the greatest symbol ID (the smallest is zero)
|
||||
inline int maxID();
|
||||
//! Get number of user-declared endogenous variables (without the auxiliary variables)
|
||||
inline int orig_endo_nbr() const throw (NotYetFrozenException);
|
||||
//! Write output of this class
|
||||
void writeOutput(ostream &output) const throw (NotYetFrozenException);
|
||||
//! Write JSON Output
|
||||
void writeJsonOutput(ostream &output) const;
|
||||
//! Write Julia output of this class
|
||||
void writeJuliaOutput(ostream &output) const throw (NotYetFrozenException);
|
||||
//! Write C output of this class
|
||||
void writeCOutput(ostream &output) const throw (NotYetFrozenException);
|
||||
//! Write CC output of this class
|
||||
void writeCCOutput(ostream &output) const throw (NotYetFrozenException);
|
||||
//! Mark a symbol as predetermined variable
|
||||
void markPredetermined(int symb_id) throw (UnknownSymbolIDException, FrozenException);
|
||||
//! Test if a given symbol is a predetermined variable
|
||||
bool isPredetermined(int symb_id) const throw (UnknownSymbolIDException);
|
||||
//! Return the number of predetermined variables
|
||||
int predeterminedNbr() const;
|
||||
//! Add an observed variable
|
||||
void addObservedVariable(int symb_id) throw (UnknownSymbolIDException);
|
||||
//! Return the number of observed variables
|
||||
int observedVariablesNbr() const;
|
||||
//! Is a given symbol in the set of observed variables
|
||||
bool isObservedVariable(int symb_id) const;
|
||||
//! Return the index of a given observed variable in the vector of all observed variables
|
||||
int getObservedVariableIndex(int symb_id) const;
|
||||
//! Add an observed exogenous variable
|
||||
void addObservedExogenousVariable(int symb_id) throw (UnknownSymbolIDException);
|
||||
//! Return the number of observed exogenous variables
|
||||
int observedExogenousVariablesNbr() const;
|
||||
//! Is a given symbol in the set of observed exogenous variables
|
||||
bool isObservedExogenousVariable(int symb_id) const;
|
||||
//! Return the index of a given observed exogenous variable in the vector of all observed variables
|
||||
int getObservedExogenousVariableIndex(int symb_id) const;
|
||||
vector <int> getTrendVarIds() const;
|
||||
//! Get list of exogenous variables
|
||||
set <int> getExogenous() const;
|
||||
//! Get list of exogenous variables
|
||||
set <int> getObservedExogenous() const;
|
||||
//! Get list of endogenous variables
|
||||
set <int> getEndogenous() const;
|
||||
//! Is a given symbol an auxiliary variable
|
||||
bool isAuxiliaryVariable(int symb_id) const;
|
||||
//! Is a given symbol an auxiliary variable but not a Lagrange multiplier
|
||||
bool isAuxiliaryVariableButNotMultiplier(int symb_id) const;
|
||||
//! Get list of endogenous variables without aux vars
|
||||
set <int> getOrigEndogenous() const;
|
||||
};
|
||||
|
||||
inline void
|
||||
SymbolTable::validateSymbID(int symb_id) const throw (UnknownSymbolIDException)
|
||||
{
|
||||
if (symb_id < 0 || symb_id > (int) symbol_table.size())
|
||||
throw UnknownSymbolIDException(symb_id);
|
||||
}
|
||||
|
||||
inline bool
|
||||
SymbolTable::exists(const string &name) const
|
||||
{
|
||||
symbol_table_type::const_iterator iter = symbol_table.find(name);
|
||||
return (iter != symbol_table.end());
|
||||
}
|
||||
|
||||
inline string
|
||||
SymbolTable::getName(int id) const throw (UnknownSymbolIDException)
|
||||
{
|
||||
validateSymbID(id);
|
||||
return name_table[id];
|
||||
}
|
||||
|
||||
inline string
|
||||
SymbolTable::getTeXName(int id) const throw (UnknownSymbolIDException)
|
||||
{
|
||||
validateSymbID(id);
|
||||
return tex_name_table[id];
|
||||
}
|
||||
|
||||
inline string
|
||||
SymbolTable::getLongName(int id) const throw (UnknownSymbolIDException)
|
||||
{
|
||||
validateSymbID(id);
|
||||
return long_name_table[id];
|
||||
}
|
||||
|
||||
inline SymbolType
|
||||
SymbolTable::getType(int id) const throw (UnknownSymbolIDException)
|
||||
{
|
||||
validateSymbID(id);
|
||||
return type_table[id];
|
||||
}
|
||||
|
||||
inline SymbolType
|
||||
SymbolTable::getType(const string &name) const throw (UnknownSymbolNameException)
|
||||
{
|
||||
return getType(getID(name));
|
||||
}
|
||||
|
||||
inline int
|
||||
SymbolTable::getID(const string &name) const throw (UnknownSymbolNameException)
|
||||
{
|
||||
symbol_table_type::const_iterator iter = symbol_table.find(name);
|
||||
if (iter != symbol_table.end())
|
||||
return iter->second;
|
||||
else
|
||||
throw UnknownSymbolNameException(name);
|
||||
}
|
||||
|
||||
inline int
|
||||
SymbolTable::getTypeSpecificID(int id) const throw (UnknownSymbolIDException, NotYetFrozenException)
|
||||
{
|
||||
if (!frozen)
|
||||
throw NotYetFrozenException();
|
||||
|
||||
validateSymbID(id);
|
||||
|
||||
return type_specific_ids[id];
|
||||
}
|
||||
|
||||
inline int
|
||||
SymbolTable::getTypeSpecificID(const string &name) const throw (UnknownSymbolNameException, NotYetFrozenException)
|
||||
{
|
||||
return getTypeSpecificID(getID(name));
|
||||
}
|
||||
|
||||
inline int
|
||||
SymbolTable::endo_nbr() const throw (NotYetFrozenException)
|
||||
{
|
||||
if (!frozen)
|
||||
throw NotYetFrozenException();
|
||||
|
||||
return endo_ids.size();
|
||||
}
|
||||
|
||||
inline int
|
||||
SymbolTable::exo_nbr() const throw (NotYetFrozenException)
|
||||
{
|
||||
if (!frozen)
|
||||
throw NotYetFrozenException();
|
||||
|
||||
return exo_ids.size();
|
||||
}
|
||||
|
||||
inline int
|
||||
SymbolTable::exo_det_nbr() const throw (NotYetFrozenException)
|
||||
{
|
||||
if (!frozen)
|
||||
throw NotYetFrozenException();
|
||||
|
||||
return exo_det_ids.size();
|
||||
}
|
||||
|
||||
inline int
|
||||
SymbolTable::param_nbr() const throw (NotYetFrozenException)
|
||||
{
|
||||
if (!frozen)
|
||||
throw NotYetFrozenException();
|
||||
|
||||
return param_ids.size();
|
||||
}
|
||||
|
||||
inline int
|
||||
SymbolTable::maxID()
|
||||
{
|
||||
return symbol_table.size() - 1;
|
||||
}
|
||||
|
||||
inline int
|
||||
SymbolTable::orig_endo_nbr() const throw (NotYetFrozenException)
|
||||
{
|
||||
return (endo_nbr() - aux_vars.size());
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2012-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "WarningConsolidation.hh"
|
||||
#include <ostream>
|
||||
|
||||
WarningConsolidation
|
||||
&
|
||||
operator<<(WarningConsolidation &wcc, const string &warning)
|
||||
{
|
||||
if (wcc.no_warn)
|
||||
return wcc;
|
||||
|
||||
cerr << warning;
|
||||
wcc.addWarning(warning);
|
||||
return wcc;
|
||||
};
|
||||
|
||||
WarningConsolidation &
|
||||
operator<<(WarningConsolidation &wcc, const Dynare::location &loc)
|
||||
{
|
||||
if (wcc.no_warn)
|
||||
return wcc;
|
||||
|
||||
stringstream ostr;
|
||||
Dynare::position last = loc.end - 1;
|
||||
ostr << loc.begin;
|
||||
if (last.filename
|
||||
&& (!loc.begin.filename
|
||||
|| *loc.begin.filename != *last.filename))
|
||||
ostr << '-' << last;
|
||||
else if (loc.begin.line != last.line)
|
||||
ostr << '-' << last.line << '.' << last.column;
|
||||
else if (loc.begin.column != last.column)
|
||||
ostr << '-' << last.column;
|
||||
|
||||
cerr << ostr.str();
|
||||
wcc.addWarning(ostr.str());
|
||||
return wcc;
|
||||
};
|
||||
|
||||
WarningConsolidation &
|
||||
operator<<(WarningConsolidation &wcc, ostream & (*pf)(ostream &))
|
||||
{
|
||||
if (wcc.no_warn)
|
||||
return wcc;
|
||||
|
||||
cerr << pf;
|
||||
wcc.addWarning(pf);
|
||||
return wcc;
|
||||
}
|
||||
|
||||
void
|
||||
WarningConsolidation::writeOutput(ostream &output) const
|
||||
{
|
||||
if (warnings.str().empty())
|
||||
return;
|
||||
|
||||
output << "disp([char(10) 'Dynare Preprocessor Warning(s) Encountered:']);" << endl;
|
||||
|
||||
bool writedisp = true;
|
||||
string warningsstr = warnings.str();
|
||||
for (size_t i = 0; i < warningsstr.length(); i++)
|
||||
{
|
||||
if (writedisp)
|
||||
{
|
||||
output << "disp(' ";
|
||||
writedisp = false;
|
||||
}
|
||||
|
||||
if (warningsstr[i] != '\n')
|
||||
output << warningsstr[i];
|
||||
else
|
||||
{
|
||||
output << "');" << endl;
|
||||
if (i+1 < warningsstr.length())
|
||||
writedisp = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
WarningConsolidation::countWarnings() const
|
||||
{
|
||||
size_t p = 0;
|
||||
int n = 0;
|
||||
while ((p = warnings.str().find('\n', p)) != string::npos)
|
||||
{
|
||||
p++;
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2012-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _WARNINGCONSOLIDATION_HH
|
||||
#define _WARNINGCONSOLIDATION_HH
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include "location.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
//! Stores Warnings issued by the Preprocessor
|
||||
class WarningConsolidation
|
||||
{
|
||||
private:
|
||||
stringstream warnings;
|
||||
bool no_warn;
|
||||
|
||||
public:
|
||||
WarningConsolidation(bool no_warn_arg) : no_warn(no_warn_arg)
|
||||
{
|
||||
};
|
||||
~WarningConsolidation()
|
||||
{
|
||||
};
|
||||
|
||||
//! Add A Warning to the StringStream
|
||||
friend WarningConsolidation &operator<<(WarningConsolidation &wcc, const string &warning);
|
||||
friend WarningConsolidation &operator<<(WarningConsolidation &wcc, const Dynare::location &loc);
|
||||
friend WarningConsolidation &operator<<(WarningConsolidation &wcc, ostream & (*pf)(ostream &));
|
||||
|
||||
inline void
|
||||
addWarning(const string &w)
|
||||
{
|
||||
warnings << w;
|
||||
};
|
||||
inline void
|
||||
addWarning(ostream & (*pf)(ostream &))
|
||||
{
|
||||
warnings << pf;
|
||||
};
|
||||
|
||||
//! Write Warnings to m file
|
||||
void writeOutput(ostream &output) const;
|
||||
//! Count warnings
|
||||
/*! This is done in a very lousy way, by counting newlines in the
|
||||
stringstream... */
|
||||
int countWarnings() const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,214 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
%skeleton "lalr1.cc"
|
||||
%require "2.5"
|
||||
%defines
|
||||
|
||||
%code top {
|
||||
class MacroDriver;
|
||||
}
|
||||
|
||||
%name-prefix "Macro"
|
||||
|
||||
%parse-param { MacroDriver &driver }
|
||||
%parse-param { ostream &out }
|
||||
%lex-param { MacroDriver &driver }
|
||||
|
||||
%locations
|
||||
%initial-action
|
||||
{
|
||||
// Initialize the location filenames
|
||||
@$.begin.filename = @$.end.filename = &driver.file;
|
||||
};
|
||||
|
||||
%debug
|
||||
%error-verbose
|
||||
|
||||
%code requires {
|
||||
#include "MacroValue.hh"
|
||||
}
|
||||
|
||||
%union
|
||||
{
|
||||
string *string_val;
|
||||
int int_val;
|
||||
const MacroValue *mv;
|
||||
};
|
||||
|
||||
%code {
|
||||
#include <cstdlib> // Pour atoi()
|
||||
#include "MacroDriver.hh"
|
||||
|
||||
/* this "connects" the bison parser in the driver to the flex scanner class
|
||||
* object. it defines the yylex() function call to pull the next token from the
|
||||
* current lexer object of the driver context. */
|
||||
#undef yylex
|
||||
#define yylex driver.lexer->lex
|
||||
|
||||
#define TYPERR_CATCH(statement, loc) try \
|
||||
{ \
|
||||
statement; \
|
||||
} \
|
||||
catch(MacroValue::TypeError &e) \
|
||||
{ \
|
||||
driver.error(loc, e.message); \
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
%token DEFINE LINE FOR IN IF ELSE ENDIF ECHO_DIR ERROR IFDEF IFNDEF
|
||||
%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL LENGTH ECHOMACROVARS SAVE
|
||||
|
||||
%token <int_val> INTEGER
|
||||
%token <string_val> NAME STRING
|
||||
|
||||
%left COMMA
|
||||
%left LOGICAL_OR
|
||||
%left LOGICAL_AND
|
||||
%left LESS GREATER LESS_EQUAL GREATER_EQUAL EQUAL_EQUAL EXCLAMATION_EQUAL
|
||||
%nonassoc IN
|
||||
%nonassoc COLON
|
||||
%left PLUS MINUS
|
||||
%left TIMES DIVIDE
|
||||
%left UMINUS UPLUS EXCLAMATION
|
||||
%left LBRACKET
|
||||
|
||||
%type <mv> expr array_expr
|
||||
%%
|
||||
|
||||
%start statement_list_or_nothing;
|
||||
|
||||
statement_list_or_nothing : /* empty */
|
||||
| statement_list
|
||||
;
|
||||
|
||||
statement_list : statement EOL
|
||||
| statement_list statement EOL
|
||||
;
|
||||
|
||||
statement : expr
|
||||
{ out << $1->toString(); }
|
||||
| DEFINE NAME EQUAL expr
|
||||
{ driver.set_variable(*$2, $4); delete $2; }
|
||||
| FOR NAME IN expr
|
||||
{ TYPERR_CATCH(driver.init_loop(*$2, $4), @$); delete $2; }
|
||||
| IF expr
|
||||
{ TYPERR_CATCH(driver.begin_if($2), @$); }
|
||||
| IFDEF NAME
|
||||
{ TYPERR_CATCH(driver.begin_ifdef(*$2), @$); delete $2; }
|
||||
| IFNDEF NAME
|
||||
{ TYPERR_CATCH(driver.begin_ifndef(*$2), @$); delete $2; }
|
||||
| ECHO_DIR expr
|
||||
{ TYPERR_CATCH(driver.echo(@$, $2), @$); }
|
||||
| ERROR expr
|
||||
{ TYPERR_CATCH(driver.error(@$, $2), @$); }
|
||||
| LINE STRING INTEGER
|
||||
/* Ignore @#line declarations */
|
||||
| ECHOMACROVARS
|
||||
{ driver.printvars(@$, true); }
|
||||
| ECHOMACROVARS LPAREN SAVE RPAREN
|
||||
{ out << driver.printvars(@$, false); }
|
||||
;
|
||||
|
||||
expr : INTEGER
|
||||
{ $$ = new IntMV(driver, $1); }
|
||||
| STRING
|
||||
{ $$ = new StringMV(driver, *$1); delete $1; }
|
||||
| NAME
|
||||
{
|
||||
try
|
||||
{
|
||||
$$ = driver.get_variable(*$1);
|
||||
}
|
||||
catch(MacroDriver::UnknownVariable(&e))
|
||||
{
|
||||
error(@$, "Unknown variable: " + e.name);
|
||||
}
|
||||
delete $1;
|
||||
}
|
||||
| LENGTH LPAREN array_expr RPAREN
|
||||
{ TYPERR_CATCH($$ = $3->length(), @$); }
|
||||
| LPAREN expr RPAREN
|
||||
{ $$ = $2; }
|
||||
| expr PLUS expr
|
||||
{ TYPERR_CATCH($$ = *$1 + *$3, @$); }
|
||||
| expr MINUS expr
|
||||
{ TYPERR_CATCH($$ = *$1 - *$3, @$); }
|
||||
| expr TIMES expr
|
||||
{ TYPERR_CATCH($$ = *$1 * *$3, @$); }
|
||||
| expr DIVIDE expr
|
||||
{
|
||||
if (dynamic_cast<const IntMV *>($3) != NULL
|
||||
&& ((IntMV *)$3)->get_int_value() == 0)
|
||||
driver.error(@$, "Division by zero");
|
||||
TYPERR_CATCH($$ = *$1 / *$3, @$);
|
||||
}
|
||||
| expr LESS expr
|
||||
{ TYPERR_CATCH($$ = *$1 < *$3, @$); }
|
||||
| expr GREATER expr
|
||||
{ TYPERR_CATCH($$ = *$1 > *$3, @$); }
|
||||
| expr LESS_EQUAL expr
|
||||
{ TYPERR_CATCH($$ = *$1 <= *$3, @$); }
|
||||
| expr GREATER_EQUAL expr
|
||||
{ TYPERR_CATCH($$ = *$1 >= *$3, @$); }
|
||||
| expr EQUAL_EQUAL expr
|
||||
{ TYPERR_CATCH($$ = *$1 == *$3, @$); }
|
||||
| expr EXCLAMATION_EQUAL expr
|
||||
{ TYPERR_CATCH($$ = *$1 != *$3, @$); }
|
||||
| expr LOGICAL_OR expr
|
||||
{ TYPERR_CATCH($$ = *$1 || *$3, @$); }
|
||||
| expr LOGICAL_AND expr
|
||||
{ TYPERR_CATCH($$ = *$1 && *$3, @$); }
|
||||
| MINUS expr %prec UMINUS
|
||||
{ TYPERR_CATCH($$ = -*$2, @$); }
|
||||
| PLUS expr %prec UPLUS
|
||||
{ TYPERR_CATCH($$ = +(*$2), @$); }
|
||||
| EXCLAMATION expr
|
||||
{ TYPERR_CATCH($$ = !*$2, @$); }
|
||||
| expr LBRACKET array_expr RBRACKET
|
||||
{
|
||||
TYPERR_CATCH($$ = (*$1)[*$3], @$)
|
||||
catch(MacroValue::OutOfBoundsError)
|
||||
{
|
||||
error(@$, "Index out of bounds");
|
||||
}
|
||||
}
|
||||
| LBRACKET array_expr RBRACKET
|
||||
{ $$ = $2; }
|
||||
| expr COLON expr
|
||||
{ TYPERR_CATCH($$ = IntMV::new_range(driver, $1, $3), @$); }
|
||||
| expr IN expr
|
||||
{ TYPERR_CATCH($$ = $1->in($3), @$); }
|
||||
;
|
||||
|
||||
array_expr : expr
|
||||
{ $$ = $1->toArray(); }
|
||||
| array_expr COMMA expr
|
||||
{ TYPERR_CATCH($$ = $3->append($1), @$); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
void
|
||||
Macro::parser::error(const Macro::parser::location_type &l,
|
||||
const string &m)
|
||||
{
|
||||
driver.error(l, m);
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2018 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "MacroDriver.hh"
|
||||
|
||||
MacroDriver::MacroDriver()
|
||||
{
|
||||
}
|
||||
|
||||
MacroDriver::~MacroDriver()
|
||||
{
|
||||
for (set<const MacroValue *>::iterator it = values.begin();
|
||||
it != values.end(); it++)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
void
|
||||
MacroDriver::parse(const string &f, const string &fb, const string &modfiletxt,
|
||||
ostream &out, bool debug, bool no_line_macro_arg, map<string, string> defines,
|
||||
vector<string> path)
|
||||
{
|
||||
file = f;
|
||||
basename = fb;
|
||||
no_line_macro = no_line_macro_arg;
|
||||
|
||||
/*
|
||||
Copy the file into a stringstream, and add an extra end-of-line. This is a
|
||||
workaround for trac ticket #73: with this workaround, MOD files ending with
|
||||
an @#endif or an @#endfor - but no newline - no longer trigger an error.
|
||||
*/
|
||||
stringstream file_with_endl;
|
||||
for (map<string, string>::iterator it = defines.begin();
|
||||
it != defines.end(); it++)
|
||||
try
|
||||
{
|
||||
boost::lexical_cast<int>(it->second);
|
||||
file_with_endl << "@#define " << it->first << " = " << it->second << endl;
|
||||
}
|
||||
catch (boost::bad_lexical_cast &)
|
||||
{
|
||||
if (!it->second.empty() && it->second.at(0) == '[' && it->second.at(it->second.length()-1) == ']')
|
||||
// If the input is an array. Issue #1578
|
||||
file_with_endl << "@#define " << it->first << " = " << it->second << endl;
|
||||
else
|
||||
file_with_endl << "@#define " << it->first << " = \"" << it->second << "\"" << endl;
|
||||
}
|
||||
file_with_endl << modfiletxt << endl;
|
||||
|
||||
lexer = new MacroFlex(&file_with_endl, &out, no_line_macro, path);
|
||||
lexer->set_debug(debug);
|
||||
|
||||
Macro::parser parser(*this, out);
|
||||
parser.set_debug_level(debug);
|
||||
|
||||
// Output first @#line statement
|
||||
if (!no_line_macro)
|
||||
out << "@#line \"" << file << "\" 1" << endl;
|
||||
|
||||
// Launch macro-processing
|
||||
parser.parse();
|
||||
|
||||
delete lexer;
|
||||
}
|
||||
|
||||
void
|
||||
MacroDriver::error(const Macro::parser::location_type &l, const string &m) const
|
||||
{
|
||||
cerr << "ERROR in macro-processor: " << l << ": " << m << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void
|
||||
MacroDriver::set_variable(const string &name, const MacroValue *value)
|
||||
{
|
||||
env[name] = value;
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroDriver::get_variable(const string &name) const throw (UnknownVariable)
|
||||
{
|
||||
map<string, const MacroValue *>::const_iterator it = env.find(name);
|
||||
if (it == env.end())
|
||||
throw UnknownVariable(name);
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void
|
||||
MacroDriver::init_loop(const string &name, const MacroValue *value) throw (MacroValue::TypeError)
|
||||
{
|
||||
const ArrayMV<int> *mv1 = dynamic_cast<const ArrayMV<int> *>(value);
|
||||
const ArrayMV<string> *mv2 = dynamic_cast<const ArrayMV<string> *>(value);
|
||||
if (!mv1 && !mv2)
|
||||
throw MacroValue::TypeError("Argument of @#for loop must be an array expression");
|
||||
loop_stack.push(make_pair(name, make_pair(value, 0)));
|
||||
}
|
||||
|
||||
bool
|
||||
MacroDriver::iter_loop()
|
||||
{
|
||||
if (loop_stack.empty())
|
||||
throw "No loop on which to iterate!";
|
||||
|
||||
int &i = loop_stack.top().second.second;
|
||||
const MacroValue *mv = loop_stack.top().second.first;
|
||||
string name = loop_stack.top().first;
|
||||
|
||||
const ArrayMV<int> *mv1 = dynamic_cast<const ArrayMV<int> *>(mv);
|
||||
if (mv1)
|
||||
{
|
||||
if (i >= (int) mv1->values.size())
|
||||
{
|
||||
loop_stack.pop();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
env[name] = new IntMV(*this, mv1->values[i++]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const ArrayMV<string> *mv2 = dynamic_cast<const ArrayMV<string> *>(mv);
|
||||
if (i >= (int) mv2->values.size())
|
||||
{
|
||||
loop_stack.pop();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
env[name] = new StringMV(*this, mv2->values[i++]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroDriver::begin_if(const MacroValue *value) throw (MacroValue::TypeError)
|
||||
{
|
||||
const IntMV *ival = dynamic_cast<const IntMV *>(value);
|
||||
if (!ival)
|
||||
throw MacroValue::TypeError("Argument of @#if must be an integer");
|
||||
last_if = (bool) ival->value;
|
||||
}
|
||||
|
||||
void
|
||||
MacroDriver::begin_ifdef(const string &name)
|
||||
{
|
||||
try
|
||||
{
|
||||
get_variable(name);
|
||||
begin_if(new IntMV(*this, 1));
|
||||
}
|
||||
catch (UnknownVariable &)
|
||||
{
|
||||
begin_if(new IntMV(*this, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroDriver::begin_ifndef(const string &name)
|
||||
{
|
||||
try
|
||||
{
|
||||
get_variable(name);
|
||||
begin_if(new IntMV(*this, 0));
|
||||
}
|
||||
catch (UnknownVariable &)
|
||||
{
|
||||
begin_if(new IntMV(*this, 1));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroDriver::echo(const Macro::parser::location_type &l, const MacroValue *value) const throw (MacroValue::TypeError)
|
||||
{
|
||||
const StringMV *sval = dynamic_cast<const StringMV *>(value);
|
||||
if (!sval)
|
||||
throw MacroValue::TypeError("Argument of @#echo must be a string");
|
||||
|
||||
cerr << "ECHO in macro-processor: " << l << ": " << sval->value << endl;
|
||||
}
|
||||
|
||||
void
|
||||
MacroDriver::error(const Macro::parser::location_type &l, const MacroValue *value) const throw (MacroValue::TypeError)
|
||||
{
|
||||
const StringMV *sval = dynamic_cast<const StringMV *>(value);
|
||||
if (!sval)
|
||||
throw MacroValue::TypeError("Argument of @#error must be a string");
|
||||
|
||||
error(l, sval->value);
|
||||
}
|
||||
|
||||
string
|
||||
MacroDriver::printvars(const Macro::parser::location_type &l, const bool tostdout) const
|
||||
{
|
||||
if (tostdout)
|
||||
{
|
||||
cout << "Macroprocessor: Printing macro variable values from " << file
|
||||
<< " at line " << l.begin.line << endl;
|
||||
for (map<string, const MacroValue *>::const_iterator it = env.begin();
|
||||
it != env.end(); it++)
|
||||
cout << " " << it->first << " = " << it->second->print() << endl;
|
||||
cout << endl;
|
||||
return "";
|
||||
}
|
||||
|
||||
stringstream intomfile;
|
||||
if (!no_line_macro)
|
||||
intomfile << "@#line \"" << file << "\" " << l.begin.line << endl;
|
||||
|
||||
for (map<string, const MacroValue *>::const_iterator it = env.begin();
|
||||
it != env.end(); it++)
|
||||
intomfile<< "options_.macrovars_line_" << l.begin.line << "." << it->first << " = " << it->second->print() << ";" << endl;
|
||||
return intomfile.str();
|
||||
}
|
|
@ -1,240 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _MACRO_DRIVER_HH
|
||||
#define _MACRO_DRIVER_HH
|
||||
|
||||
#ifdef _PARSING_DRIVER_HH
|
||||
# error Impossible to include both ParsingDriver.hh and MacroDriver.hh
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "MacroValue.hh"
|
||||
#include "MacroBison.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Declare MacroFlexLexer class
|
||||
#ifndef __FLEX_LEXER_H
|
||||
# define yyFlexLexer MacroFlexLexer
|
||||
# include <FlexLexer.h>
|
||||
# undef yyFlexLexer
|
||||
#endif
|
||||
|
||||
//! The lexer class
|
||||
/*! Actually it was necessary to subclass the MacroFlexLexer class generated by Flex,
|
||||
since the prototype for MacroFlexLexer::yylex() was not convenient.
|
||||
*/
|
||||
class MacroFlex : public MacroFlexLexer
|
||||
{
|
||||
private:
|
||||
//! Used to backup all the information related to a given scanning context
|
||||
class ScanContext
|
||||
{
|
||||
public:
|
||||
istream *input;
|
||||
struct yy_buffer_state *buffer;
|
||||
const Macro::parser::location_type yylloc;
|
||||
const bool is_for_context;
|
||||
const string for_body;
|
||||
const Macro::parser::location_type for_body_loc;
|
||||
ScanContext(istream *input_arg, struct yy_buffer_state *buffer_arg,
|
||||
Macro::parser::location_type &yylloc_arg, bool is_for_context_arg,
|
||||
const string &for_body_arg,
|
||||
Macro::parser::location_type &for_body_loc_arg) :
|
||||
input(input_arg), buffer(buffer_arg), yylloc(yylloc_arg), is_for_context(is_for_context_arg),
|
||||
for_body(for_body_arg), for_body_loc(for_body_loc_arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//! The stack used to keep track of nested scanning contexts
|
||||
stack<ScanContext> context_stack;
|
||||
|
||||
//! Input stream used for initialization of current scanning context
|
||||
/*! Kept for deletion at end of current scanning buffer */
|
||||
istream *input;
|
||||
|
||||
//! Should we omit the @#line statements ?
|
||||
const bool no_line_macro;
|
||||
//! The paths to search when looking for .mod files
|
||||
vector<string> path;
|
||||
//! True iff current context is the body of a loop
|
||||
bool is_for_context;
|
||||
//! If current context is the body of a loop, contains the string of the loop body
|
||||
string for_body;
|
||||
//! If current context is the body of a loop, contains the location of the beginning of the body
|
||||
Macro::parser::location_type for_body_loc;
|
||||
|
||||
//! Temporary variable used in FOR_BODY mode
|
||||
string for_body_tmp;
|
||||
//! Temporary variable used in FOR_BODY mode
|
||||
Macro::parser::location_type for_body_loc_tmp;
|
||||
//! Temporary variable used in FOR_BODY mode. Keeps track of the location of the @#for statement, for reporting messages
|
||||
Macro::parser::location_type for_stmt_loc_tmp;
|
||||
//! Temporary variable used in FOR_BODY mode. Keeps track of number of nested @#for/@#endfor
|
||||
int nested_for_nb;
|
||||
//! Set to true while parsing a FOR statement (only the statement, not the loop body)
|
||||
bool reading_for_statement;
|
||||
|
||||
//! Temporary variable used in THEN_BODY and ELSE_BODY modes. Keeps track of number of nested @#if
|
||||
int nested_if_nb;
|
||||
//! Temporary variable used in THEN_BODY mode
|
||||
string then_body_tmp;
|
||||
//! Temporary variable used in THEN_BODY mode
|
||||
Macro::parser::location_type then_body_loc_tmp;
|
||||
//! Temporary variable used in THEN_BODY mode. Keeps track of the location of the @#if statement, for reporting messages
|
||||
Macro::parser::location_type if_stmt_loc_tmp;
|
||||
//! Temporary variable used in ELSE_BODY mode
|
||||
string else_body_tmp;
|
||||
//! Temporary variable used in ELSE_BODY mode
|
||||
Macro::parser::location_type else_body_loc_tmp;
|
||||
//! Set to true while parsing an IF statement (only the statement, not the body)
|
||||
bool reading_if_statement;
|
||||
|
||||
//! Output the @#line declaration
|
||||
void output_line(Macro::parser::location_type *yylloc) const;
|
||||
|
||||
//! Save current scanning context
|
||||
void save_context(Macro::parser::location_type *yylloc);
|
||||
|
||||
//! Restore last scanning context
|
||||
void restore_context(Macro::parser::location_type *yylloc);
|
||||
|
||||
//! pushes the colon-separated paths passed to @#includepath onto the path vector
|
||||
void push_path(string *includepath, Macro::parser::location_type *yylloc,
|
||||
MacroDriver &driver);
|
||||
|
||||
//! Saves current scanning context and create a new context with content of filename
|
||||
/*! Filename must be a newly allocated string which will be deleted by the lexer */
|
||||
void create_include_context(string *filename, Macro::parser::location_type *yylloc,
|
||||
MacroDriver &driver);
|
||||
|
||||
//! Saves current scanning context and create a new context based on the "then" body
|
||||
void create_then_context(Macro::parser::location_type *yylloc);
|
||||
|
||||
//! Saves current scanning context and create a new context based on the "else" body
|
||||
void create_else_context(Macro::parser::location_type *yylloc);
|
||||
|
||||
//! Initialise a new flex buffer with the loop body
|
||||
void new_loop_body_buffer(Macro::parser::location_type *yylloc);
|
||||
|
||||
public:
|
||||
MacroFlex(istream *in, ostream *out, bool no_line_macro_arg, vector<string> path_arg);
|
||||
|
||||
//! The main lexing function
|
||||
Macro::parser::token_type lex(Macro::parser::semantic_type *yylval,
|
||||
Macro::parser::location_type *yylloc,
|
||||
MacroDriver &driver);
|
||||
};
|
||||
|
||||
//! Implements the macro expansion using a Flex scanner and a Bison parser
|
||||
class MacroDriver
|
||||
{
|
||||
friend class MacroValue;
|
||||
private:
|
||||
//! Stores all created macro values
|
||||
set<const MacroValue *> values;
|
||||
|
||||
//! Environment: maps macro variables to their values
|
||||
map<string, const MacroValue *> env;
|
||||
|
||||
//! Stack used to keep track of (possibly nested) loops
|
||||
//! First element is loop variable name, second is the array over which iteration is done, and third is subscript to be used by next call of iter_loop() (beginning with 0) */
|
||||
stack<pair<string, pair<const MacroValue *, int> > > loop_stack;
|
||||
public:
|
||||
//! Exception thrown when value of an unknown variable is requested
|
||||
class UnknownVariable
|
||||
{
|
||||
public:
|
||||
const string name;
|
||||
UnknownVariable(const string &name_arg) : name(name_arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//! Constructor
|
||||
MacroDriver();
|
||||
//! Destructor
|
||||
virtual
|
||||
~MacroDriver();
|
||||
|
||||
//! Starts parsing a file, returns output in out
|
||||
/*! \param no_line_macro should we omit the @#line statements ? */
|
||||
void parse(const string &f, const string &fb, const string &modfiletxt, ostream &out, bool debug, bool no_line_macro_arg,
|
||||
map<string, string> defines, vector<string> path);
|
||||
|
||||
//! Name of main file being parsed
|
||||
string file;
|
||||
|
||||
//! Basename of main file being parsed
|
||||
string basename;
|
||||
|
||||
//! Whether or not to print @#line
|
||||
bool no_line_macro;
|
||||
|
||||
//! Reference to the lexer
|
||||
class MacroFlex *lexer;
|
||||
|
||||
//! Used to store the value of the last @#if condition
|
||||
bool last_if;
|
||||
|
||||
//! Error handler
|
||||
void error(const Macro::parser::location_type &l, const string &m) const;
|
||||
|
||||
//! Print variables
|
||||
string printvars(const Macro::parser::location_type &l, const bool save) const;
|
||||
|
||||
//! Set a variable
|
||||
void set_variable(const string &name, const MacroValue *value);
|
||||
|
||||
//! Get a variable
|
||||
/*! Returns a newly allocated value (clone of the value stored in environment). */
|
||||
const MacroValue *get_variable(const string &name) const throw (UnknownVariable);
|
||||
|
||||
//! Initiate a for loop
|
||||
/*! Does not set name = value[1]. You must call iter_loop() for that. */
|
||||
void init_loop(const string &name, const MacroValue *value) throw (MacroValue::TypeError);
|
||||
|
||||
//! Iterate innermost loop
|
||||
/*! Returns false if iteration is no more possible (end of loop); in that case it destroys the pointer given to init_loop() */
|
||||
bool iter_loop();
|
||||
|
||||
//! Begins an @#if statement
|
||||
void begin_if(const MacroValue *value) throw (MacroValue::TypeError);
|
||||
|
||||
//! Begins an @#ifdef statement
|
||||
void begin_ifdef(const string &name);
|
||||
|
||||
//! Begins an @#ifndef statement
|
||||
void begin_ifndef(const string &name);
|
||||
|
||||
//! Executes @#echo directive
|
||||
void echo(const Macro::parser::location_type &l, const MacroValue *value) const throw (MacroValue::TypeError);
|
||||
|
||||
//! Executes @#error directive
|
||||
void error(const Macro::parser::location_type &l, const MacroValue *value) const throw (MacroValue::TypeError);
|
||||
};
|
||||
|
||||
#endif // ! MACRO_DRIVER_HH
|
|
@ -1,567 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2018 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
%{
|
||||
using namespace std;
|
||||
|
||||
#include <fstream>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
#include "MacroDriver.hh"
|
||||
|
||||
// Announce to Flex the prototype we want for lexing function
|
||||
#define YY_DECL \
|
||||
Macro::parser::token_type \
|
||||
MacroFlex::lex(Macro::parser::semantic_type *yylval, \
|
||||
Macro::parser::location_type *yylloc, \
|
||||
MacroDriver &driver)
|
||||
|
||||
// Shortcut to access tokens defined by Bison
|
||||
typedef Macro::parser::token token;
|
||||
|
||||
/* By default yylex returns int, we use token_type.
|
||||
Unfortunately yyterminate by default returns 0, which is
|
||||
not of token_type. */
|
||||
#define yyterminate() return Macro::parser::token_type (0);
|
||||
%}
|
||||
|
||||
%option c++
|
||||
|
||||
%option prefix="Macro"
|
||||
|
||||
%option case-insensitive noyywrap nounput batch debug never-interactive
|
||||
|
||||
%x STMT
|
||||
%x EXPR
|
||||
%x FOR_BODY
|
||||
%x THEN_BODY
|
||||
%x ELSE_BODY
|
||||
|
||||
%{
|
||||
// Increments location counter for every token read
|
||||
#define YY_USER_ACTION yylloc->columns(yyleng);
|
||||
%}
|
||||
|
||||
SPC [ \t]+
|
||||
EOL (\r)?\n
|
||||
CONT \\\\
|
||||
|
||||
%%
|
||||
/* Code put at the beginning of yylex() */
|
||||
%{
|
||||
// Reset location before reading token
|
||||
yylloc->step();
|
||||
%}
|
||||
|
||||
<STMT,EXPR,FOR_BODY,THEN_BODY,ELSE_BODY>["/"]["/"].*
|
||||
|
||||
<INITIAL>^{SPC}*@#{SPC}*includepath{SPC}+\"([^\"\r\n:;|<>]*){1}(:[^\"\r\n:;|<>]*)*\"{SPC}*{EOL} {
|
||||
yylloc->lines(1);
|
||||
yylloc->step();
|
||||
|
||||
// Get path
|
||||
string *includepath = new string(yytext);
|
||||
int dblq_idx1 = includepath->find('"');
|
||||
int dblq_idx2 = includepath->find('"', dblq_idx1 + 1);
|
||||
includepath->erase(dblq_idx2);
|
||||
includepath->erase(0, dblq_idx1 + 1);
|
||||
|
||||
push_path(includepath, yylloc, driver);
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
<INITIAL>^{SPC}*@#{SPC}*includepath{SPC}+[^\"\r\n]*{SPC}*{EOL} {
|
||||
yylloc->lines(1);
|
||||
yylloc->step();
|
||||
|
||||
// Get variable name
|
||||
string pathvar = string(yytext);
|
||||
int dblq_idx1 = pathvar.find("includepath");
|
||||
pathvar.erase(0, dblq_idx1 + 11);
|
||||
pathvar.erase(0, pathvar.find_first_not_of(" \t"));
|
||||
size_t p = pathvar.find_last_not_of(" \t\n\r");
|
||||
if (string::npos != p)
|
||||
pathvar.erase(p+1);
|
||||
|
||||
string *includepath = NULL;
|
||||
try
|
||||
{
|
||||
includepath = new string(driver.get_variable(pathvar)->toString());
|
||||
}
|
||||
catch(MacroDriver::UnknownVariable(&e))
|
||||
{
|
||||
driver.error(*yylloc, "Unknown variable: " + pathvar);
|
||||
}
|
||||
push_path(includepath, yylloc, driver);
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
<INITIAL>^{SPC}*@#{SPC}*include{SPC}+\"[^\"\r\n]*\"{SPC}*{EOL} {
|
||||
yylloc->lines(1);
|
||||
yylloc->step();
|
||||
|
||||
// Get filename
|
||||
string *filename = new string(yytext);
|
||||
int dblq_idx1 = filename->find('"');
|
||||
int dblq_idx2 = filename->find('"', dblq_idx1 + 1);
|
||||
filename->erase(dblq_idx2);
|
||||
filename->erase(0, dblq_idx1 + 1);
|
||||
|
||||
create_include_context(filename, yylloc, driver);
|
||||
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
<INITIAL>^{SPC}*@#{SPC}*include{SPC}+[^\"\r\n]*{SPC}*{EOL} {
|
||||
yylloc->lines(1);
|
||||
yylloc->step();
|
||||
|
||||
// Get variable name
|
||||
string modvarname = string(yytext);
|
||||
int dblq_idx1 = modvarname.find("include");
|
||||
modvarname.erase(0, dblq_idx1 + 7);
|
||||
modvarname.erase(0, modvarname.find_first_not_of(" \t"));
|
||||
size_t p = modvarname.find_last_not_of(" \t\n\r");
|
||||
if (string::npos != p)
|
||||
modvarname.erase(p+1);
|
||||
|
||||
string *filename = NULL;
|
||||
try
|
||||
{
|
||||
filename = new string(driver.get_variable(modvarname)->toString());
|
||||
}
|
||||
catch(MacroDriver::UnknownVariable(&e))
|
||||
{
|
||||
driver.error(*yylloc, "Unknown variable: " + modvarname);
|
||||
}
|
||||
create_include_context(filename, yylloc, driver);
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
<INITIAL>^{SPC}*@# { yylloc->step(); BEGIN(STMT); }
|
||||
<INITIAL>@\{ { yylloc->step(); BEGIN(EXPR); }
|
||||
|
||||
<EXPR>\} { BEGIN(INITIAL); return token::EOL; }
|
||||
|
||||
<STMT>{CONT}{SPC}*{EOL} { yylloc->lines(1); yylloc->step(); }
|
||||
<STMT>{EOL} {
|
||||
/* If parsing a @#for or an @#if, keep the location
|
||||
for reporting message in case of error */
|
||||
if (reading_for_statement)
|
||||
for_stmt_loc_tmp = *yylloc;
|
||||
else if (reading_if_statement)
|
||||
if_stmt_loc_tmp = *yylloc;
|
||||
|
||||
yylloc->lines(1);
|
||||
yylloc->step();
|
||||
if (reading_for_statement)
|
||||
{
|
||||
reading_for_statement = false;
|
||||
for_body_tmp.erase();
|
||||
for_body_loc_tmp = *yylloc;
|
||||
nested_for_nb = 0;
|
||||
BEGIN(FOR_BODY);
|
||||
}
|
||||
else if (reading_if_statement)
|
||||
{
|
||||
reading_if_statement = false;
|
||||
then_body_tmp.erase();
|
||||
then_body_loc_tmp = *yylloc;
|
||||
nested_if_nb = 0;
|
||||
BEGIN(THEN_BODY);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (YY_FLEX_MAJOR_VERSION > 2) || (YY_FLEX_MAJOR_VERSION == 2 && YY_FLEX_MINOR_VERSION >= 6)
|
||||
yyout << endl;
|
||||
#else
|
||||
*yyout << endl;
|
||||
#endif
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
return token::EOL;
|
||||
}
|
||||
|
||||
<STMT,EXPR>{SPC}+ { yylloc->step(); }
|
||||
|
||||
<STMT,EXPR>[0-9]+ {
|
||||
yylval->int_val = atoi(yytext);
|
||||
return token::INTEGER;
|
||||
}
|
||||
<STMT,EXPR>\( { return token::LPAREN; }
|
||||
<STMT,EXPR>\) { return token::RPAREN; }
|
||||
<STMT,EXPR>\[ { return token::LBRACKET; }
|
||||
<STMT,EXPR>\] { return token::RBRACKET; }
|
||||
<STMT,EXPR>: { return token::COLON; }
|
||||
<STMT,EXPR>, { return token::COMMA; }
|
||||
<STMT,EXPR>= { return token::EQUAL; }
|
||||
<STMT,EXPR>[!] { return token::EXCLAMATION; }
|
||||
<STMT,EXPR>"||" { return token::LOGICAL_OR; }
|
||||
<STMT,EXPR>&& { return token::LOGICAL_AND; }
|
||||
<STMT,EXPR>"<=" { return token::LESS_EQUAL; }
|
||||
<STMT,EXPR>">=" { return token::GREATER_EQUAL; }
|
||||
<STMT,EXPR>"<" { return token::LESS; }
|
||||
<STMT,EXPR>">" { return token::GREATER; }
|
||||
<STMT,EXPR>"==" { return token::EQUAL_EQUAL; }
|
||||
<STMT,EXPR>"!=" { return token::EXCLAMATION_EQUAL; }
|
||||
<STMT,EXPR>[+] { return token::PLUS; }
|
||||
<STMT,EXPR>[-] { return token::MINUS; }
|
||||
<STMT,EXPR>[*] { return token::TIMES; }
|
||||
<STMT,EXPR>[/] { return token::DIVIDE; }
|
||||
<STMT,EXPR>in { return token::IN; }
|
||||
<STMT,EXPR>length { return token::LENGTH; }
|
||||
|
||||
<STMT,EXPR>\"[^\"]*\" {
|
||||
yylval->string_val = new string(yytext + 1);
|
||||
yylval->string_val->resize(yylval->string_val->length() - 1);
|
||||
return token::STRING;
|
||||
}
|
||||
|
||||
<STMT>line { return token::LINE; }
|
||||
<STMT>define { return token::DEFINE; }
|
||||
|
||||
<STMT>echomacrovars { return token::ECHOMACROVARS; }
|
||||
<STMT>save { return token::SAVE; }
|
||||
|
||||
<STMT>for { reading_for_statement = true; return token::FOR; }
|
||||
<STMT>endfor { driver.error(*yylloc, "@#endfor is not matched by a @#for statement"); }
|
||||
|
||||
<STMT>ifdef { reading_if_statement = true; return token::IFDEF; }
|
||||
<STMT>ifndef { reading_if_statement = true; return token::IFNDEF; }
|
||||
|
||||
<STMT>if { reading_if_statement = true; return token::IF; }
|
||||
<STMT>else { driver.error(*yylloc, "@#else is not matched by an @#if/@#ifdef/@#ifndef statement"); }
|
||||
<STMT>endif { driver.error(*yylloc, "@#endif is not matched by an @#if/@#ifdef/@#ifndef statement"); }
|
||||
|
||||
<STMT>echo { return token::ECHO_DIR; }
|
||||
<STMT>error { return token::ERROR; }
|
||||
|
||||
<STMT,EXPR>[A-Za-z_][A-Za-z0-9_]* {
|
||||
yylval->string_val = new string(yytext);
|
||||
return token::NAME;
|
||||
}
|
||||
|
||||
<EXPR><<EOF>> { driver.error(*yylloc, "Unexpected end of file while parsing a macro expression"); }
|
||||
<STMT><<EOF>> { driver.error(*yylloc, "Unexpected end of file while parsing a macro statement"); }
|
||||
|
||||
<FOR_BODY>{EOL} { yylloc->lines(1); yylloc->step(); for_body_tmp.append(yytext); }
|
||||
<FOR_BODY>^{SPC}*@#{SPC}*for({SPC}|{CONT}) {
|
||||
nested_for_nb++;
|
||||
for_body_tmp.append(yytext);
|
||||
yylloc->step();
|
||||
}
|
||||
<FOR_BODY>. { for_body_tmp.append(yytext); yylloc->step(); }
|
||||
<FOR_BODY><<EOF>> { driver.error(for_stmt_loc_tmp, "@#for loop not matched by an @#endfor or file does not end with a new line (unexpected end of file)"); }
|
||||
<FOR_BODY>^{SPC}*@#{SPC}*endfor{SPC}*(\/\/.*)?{EOL} {
|
||||
yylloc->lines(1);
|
||||
yylloc->step();
|
||||
if (nested_for_nb)
|
||||
{
|
||||
/* This @#endfor is not the end of the loop body,
|
||||
but only that of a nested @#for loop */
|
||||
nested_for_nb--;
|
||||
for_body_tmp.append(yytext);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Switch to loop body context, except if iterating over an empty array
|
||||
if (driver.iter_loop())
|
||||
{
|
||||
// Save old buffer state and location
|
||||
save_context(yylloc);
|
||||
|
||||
is_for_context = true;
|
||||
for_body = for_body_tmp;
|
||||
for_body_loc = for_body_loc_tmp;
|
||||
|
||||
new_loop_body_buffer(yylloc);
|
||||
}
|
||||
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
}
|
||||
|
||||
<THEN_BODY>{EOL} { yylloc->lines(1); yylloc->step(); then_body_tmp.append(yytext); }
|
||||
<THEN_BODY>^{SPC}*@#{SPC}*if({SPC}|{CONT}) {
|
||||
nested_if_nb++;
|
||||
then_body_tmp.append(yytext);
|
||||
yylloc->step();
|
||||
}
|
||||
<THEN_BODY>^{SPC}*@#{SPC}*ifdef({SPC}|{CONT}) {
|
||||
nested_if_nb++;
|
||||
then_body_tmp.append(yytext);
|
||||
yylloc->step();
|
||||
}
|
||||
<THEN_BODY>^{SPC}*@#{SPC}*ifndef({SPC}|{CONT}) {
|
||||
nested_if_nb++;
|
||||
then_body_tmp.append(yytext);
|
||||
yylloc->step();
|
||||
}
|
||||
<THEN_BODY>. { then_body_tmp.append(yytext); yylloc->step(); }
|
||||
<THEN_BODY><<EOF>> { driver.error(if_stmt_loc_tmp, "@#if/@#ifdef/@#ifndef not matched by an @#endif or file does not end with a new line (unexpected end of file)"); }
|
||||
<THEN_BODY>^{SPC}*@#{SPC}*else{SPC}*(\/\/.*)?{EOL} {
|
||||
yylloc->lines(1);
|
||||
yylloc->step();
|
||||
if (nested_if_nb)
|
||||
then_body_tmp.append(yytext);
|
||||
else
|
||||
{
|
||||
else_body_tmp.erase();
|
||||
else_body_loc_tmp = *yylloc;
|
||||
BEGIN(ELSE_BODY);
|
||||
}
|
||||
}
|
||||
|
||||
<THEN_BODY>^{SPC}*@#{SPC}*endif{SPC}*(\/\/.*)?{EOL} {
|
||||
yylloc->lines(1);
|
||||
yylloc->step();
|
||||
if (nested_if_nb)
|
||||
{
|
||||
/* This @#endif is not the end of the @#if we're parsing,
|
||||
but only that of a nested @#if */
|
||||
nested_if_nb--;
|
||||
then_body_tmp.append(yytext);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (driver.last_if)
|
||||
create_then_context(yylloc);
|
||||
else
|
||||
output_line(yylloc);
|
||||
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
}
|
||||
|
||||
<ELSE_BODY>{EOL} { yylloc->lines(1); yylloc->step(); else_body_tmp.append(yytext); }
|
||||
<ELSE_BODY>^{SPC}*@#{SPC}*if({SPC}|{CONT}) {
|
||||
nested_if_nb++;
|
||||
else_body_tmp.append(yytext);
|
||||
yylloc->step();
|
||||
}
|
||||
<ELSE_BODY>. { else_body_tmp.append(yytext); yylloc->step(); }
|
||||
<ELSE_BODY><<EOF>> { driver.error(if_stmt_loc_tmp, "@#if/@#ifdef/@#ifndef not matched by an @#endif or file does not end with a new line (unexpected end of file)"); }
|
||||
|
||||
<ELSE_BODY>^{SPC}*@#{SPC}*endif{SPC}*(\/\/.*)?{EOL} {
|
||||
yylloc->lines(1);
|
||||
yylloc->step();
|
||||
if (nested_if_nb)
|
||||
{
|
||||
/* This @#endif is not the end of the @#if we're parsing,
|
||||
but only that of a nested @#if */
|
||||
nested_if_nb--;
|
||||
else_body_tmp.append(yytext);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (driver.last_if)
|
||||
create_then_context(yylloc);
|
||||
else
|
||||
create_else_context(yylloc);
|
||||
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
}
|
||||
|
||||
<INITIAL><<EOF>> {
|
||||
// Quit lexer if end of main file
|
||||
if (context_stack.empty())
|
||||
{
|
||||
yyterminate();
|
||||
}
|
||||
|
||||
// Else clean current scanning context
|
||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||
delete input;
|
||||
delete yylloc->begin.filename;
|
||||
|
||||
/* If we are not in a loop body, or if the loop has terminated,
|
||||
pop a context */
|
||||
if (is_for_context && driver.iter_loop())
|
||||
new_loop_body_buffer(yylloc);
|
||||
else
|
||||
restore_context(yylloc);
|
||||
}
|
||||
|
||||
/* We don't use echo, because under Cygwin it will add an extra \r */
|
||||
<INITIAL>{EOL} { yylloc->lines(1); yylloc->step();
|
||||
#if (YY_FLEX_MAJOR_VERSION > 2) || (YY_FLEX_MAJOR_VERSION == 2 && YY_FLEX_MINOR_VERSION >= 6)
|
||||
yyout << endl;
|
||||
#else
|
||||
*yyout << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Copy everything else to output */
|
||||
<INITIAL>. { yylloc->step(); ECHO; }
|
||||
|
||||
<*>. { driver.error(*yylloc, "Macro lexer error: '" + string(yytext) + "'"); }
|
||||
%%
|
||||
|
||||
MacroFlex::MacroFlex(istream* in, ostream* out, bool no_line_macro_arg, vector<string> path_arg)
|
||||
: MacroFlexLexer(in, out), input(in), no_line_macro(no_line_macro_arg), path(path_arg),
|
||||
reading_for_statement(false), reading_if_statement(false)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
MacroFlex::output_line(Macro::parser::location_type *yylloc) const
|
||||
{
|
||||
if (!no_line_macro)
|
||||
#if (YY_FLEX_MAJOR_VERSION > 2) || (YY_FLEX_MAJOR_VERSION == 2 && YY_FLEX_MINOR_VERSION >= 6)
|
||||
const_cast<ostream&>(yyout)
|
||||
#else
|
||||
*yyout
|
||||
#endif
|
||||
<< endl << "@#line \"" << *yylloc->begin.filename << "\" "
|
||||
<< yylloc->begin.line << endl;
|
||||
}
|
||||
|
||||
void
|
||||
MacroFlex::save_context(Macro::parser::location_type *yylloc)
|
||||
{
|
||||
context_stack.push(ScanContext(input, YY_CURRENT_BUFFER, *yylloc, is_for_context,
|
||||
for_body, for_body_loc));
|
||||
}
|
||||
|
||||
void
|
||||
MacroFlex::restore_context(Macro::parser::location_type *yylloc)
|
||||
{
|
||||
input = context_stack.top().input;
|
||||
yy_switch_to_buffer(context_stack.top().buffer);
|
||||
*yylloc = context_stack.top().yylloc;
|
||||
is_for_context = context_stack.top().is_for_context;
|
||||
for_body = context_stack.top().for_body;
|
||||
for_body_loc = context_stack.top().for_body_loc;
|
||||
// Remove top of stack
|
||||
context_stack.pop();
|
||||
// Dump @#line instruction
|
||||
output_line(yylloc);
|
||||
}
|
||||
|
||||
void
|
||||
MacroFlex::push_path(string *includepath, Macro::parser::location_type *yylloc,
|
||||
MacroDriver &driver)
|
||||
{
|
||||
using namespace boost;
|
||||
vector<string> tokenizedPath;
|
||||
split(tokenizedPath, *includepath, is_any_of(":"), token_compress_on);
|
||||
for (vector<string>::iterator it = tokenizedPath.begin();
|
||||
it != tokenizedPath.end(); it++ )
|
||||
if (!it->empty())
|
||||
{
|
||||
trim(*it);
|
||||
path.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroFlex::create_include_context(string *filename, Macro::parser::location_type *yylloc,
|
||||
MacroDriver &driver)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
string FILESEP = "\\";
|
||||
#else
|
||||
string FILESEP = "/";
|
||||
#endif
|
||||
save_context(yylloc);
|
||||
// Open new file
|
||||
input = new ifstream(filename->c_str(), ios::binary);
|
||||
if (input->fail())
|
||||
{
|
||||
ostringstream dirs;
|
||||
dirs << "." << FILESEP << endl;
|
||||
for (vector<string>::const_iterator it = path.begin(); it != path.end(); it++)
|
||||
{
|
||||
string testfile = *it + FILESEP + *filename;
|
||||
input = new ifstream(testfile.c_str(), ios::binary);
|
||||
if (input->good())
|
||||
break;
|
||||
dirs << *it << endl;
|
||||
}
|
||||
if (input->fail())
|
||||
driver.error(*yylloc, "Could not open " + *filename +
|
||||
". The following directories were searched:\n" + dirs.str());
|
||||
}
|
||||
|
||||
// Reset location
|
||||
yylloc->begin.filename = yylloc->end.filename = filename;
|
||||
yylloc->begin.line = yylloc->end.line = 1;
|
||||
yylloc->begin.column = yylloc->end.column = 0;
|
||||
// We are not in a loop body
|
||||
is_for_context = false;
|
||||
for_body.clear();
|
||||
// Output @#line information
|
||||
output_line(yylloc);
|
||||
// Switch to new buffer
|
||||
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
|
||||
}
|
||||
|
||||
void
|
||||
MacroFlex::create_then_context(Macro::parser::location_type *yylloc)
|
||||
{
|
||||
save_context(yylloc);
|
||||
input = new stringstream(then_body_tmp);
|
||||
*yylloc = then_body_loc_tmp;
|
||||
yylloc->begin.filename = yylloc->end.filename = new string(*then_body_loc_tmp.begin.filename);
|
||||
is_for_context = false;
|
||||
for_body.clear();
|
||||
output_line(yylloc);
|
||||
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
|
||||
}
|
||||
|
||||
void
|
||||
MacroFlex::create_else_context(Macro::parser::location_type *yylloc)
|
||||
{
|
||||
save_context(yylloc);
|
||||
input = new stringstream(else_body_tmp);
|
||||
*yylloc = else_body_loc_tmp;
|
||||
yylloc->begin.filename = yylloc->end.filename = new string(*else_body_loc_tmp.begin.filename);
|
||||
is_for_context = false;
|
||||
for_body.clear();
|
||||
output_line(yylloc);
|
||||
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
|
||||
}
|
||||
|
||||
void
|
||||
MacroFlex::new_loop_body_buffer(Macro::parser::location_type *yylloc)
|
||||
{
|
||||
input = new stringstream(for_body);
|
||||
*yylloc = for_body_loc;
|
||||
yylloc->begin.filename = yylloc->end.filename = new string(*for_body_loc.begin.filename);
|
||||
output_line(yylloc);
|
||||
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
|
||||
}
|
||||
|
||||
/* This implementation of MacroFlexLexer::yylex() is required to fill the
|
||||
* vtable of the class MacroFlexLexer. We define the scanner's main yylex
|
||||
* function via YY_DECL to reside in the MacroFlex class instead. */
|
||||
|
||||
#ifdef yylex
|
||||
# undef yylex
|
||||
#endif
|
||||
|
||||
int
|
||||
MacroFlexLexer::yylex()
|
||||
{
|
||||
cerr << "MacroFlexLexer::yylex() has been called, that should never happen!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
|
@ -1,450 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "MacroDriver.hh"
|
||||
|
||||
MacroValue::MacroValue(MacroDriver &driver_arg) : driver(driver_arg)
|
||||
{
|
||||
driver.values.insert(this);
|
||||
}
|
||||
|
||||
MacroValue::~MacroValue()
|
||||
{
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator+() const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Unary operator + does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator-(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Operator - does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator-() const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Unary operator - does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator*(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Operator * does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator/(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Operator / does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator<(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Operator < does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator>(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Operator > does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator<=(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Operator <= does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator>=(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Operator >= does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator&&(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Operator && does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator||(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Operator || does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator!() const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Operator ! does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError)
|
||||
{
|
||||
throw TypeError("Operator [] does not exist for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::length() const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Length not supported for this type");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::append(const MacroValue *mv) const throw (TypeError)
|
||||
{
|
||||
throw TypeError("Cannot append an array at the end of another one. Should use concatenation.");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::in(const MacroValue *array) const throw (TypeError)
|
||||
{
|
||||
throw TypeError("First argument of 'in' operator cannot be an array");
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::new_base_value(MacroDriver &driver, int i)
|
||||
{
|
||||
return new IntMV(driver, i);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
MacroValue::new_base_value(MacroDriver &driver, const string &s)
|
||||
{
|
||||
return new StringMV(driver, s);
|
||||
}
|
||||
|
||||
IntMV::IntMV(MacroDriver &driver, int value_arg) : MacroValue(driver), value(value_arg)
|
||||
{
|
||||
}
|
||||
|
||||
IntMV::~IntMV()
|
||||
{
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator+(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of + operator");
|
||||
return new IntMV(driver, value + mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator+() const throw (TypeError)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator-(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of - operator");
|
||||
return new IntMV(driver, value - mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator-() const throw (TypeError)
|
||||
{
|
||||
return new IntMV(driver, -value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator*(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of * operator");
|
||||
return new IntMV(driver, value * mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator/(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of / operator");
|
||||
return new IntMV(driver, value / mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator<(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of < operator");
|
||||
return new IntMV(driver, value < mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator>(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of > operator");
|
||||
return new IntMV(driver, value > mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator<=(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of <= operator");
|
||||
return new IntMV(driver, value <= mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator>=(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of >= operator");
|
||||
return new IntMV(driver, value >= mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator==(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
return new IntMV(driver, 0);
|
||||
else
|
||||
return new IntMV(driver, value == mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator!=(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
return new IntMV(driver, 1);
|
||||
else
|
||||
return new IntMV(driver, value != mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator&&(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of && operator");
|
||||
return new IntMV(driver, value && mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator||(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of || operator");
|
||||
return new IntMV(driver, value || mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::operator!() const throw (TypeError)
|
||||
{
|
||||
return new IntMV(driver, !value);
|
||||
}
|
||||
|
||||
string
|
||||
IntMV::toString() const
|
||||
{
|
||||
ostringstream ss;
|
||||
ss << value;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
string
|
||||
IntMV::print() const
|
||||
{
|
||||
return toString();
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::toArray() const
|
||||
{
|
||||
vector<int> v;
|
||||
v.push_back(value);
|
||||
return new ArrayMV<int>(driver, v);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::append(const MacroValue *array) const throw (TypeError)
|
||||
{
|
||||
const ArrayMV<int> *array2 = dynamic_cast<const ArrayMV<int> *>(array);
|
||||
if (array2 == NULL)
|
||||
throw TypeError("Type mismatch for append operation");
|
||||
|
||||
vector<int> v(array2->values);
|
||||
v.push_back(value);
|
||||
return new ArrayMV<int>(driver, v);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::in(const MacroValue *array) const throw (TypeError)
|
||||
{
|
||||
const ArrayMV<int> *array2 = dynamic_cast<const ArrayMV<int> *>(array);
|
||||
if (array2 == NULL)
|
||||
throw TypeError("Type mismatch for 'in' operator");
|
||||
|
||||
int result = 0;
|
||||
for (vector<int>::const_iterator it = array2->values.begin();
|
||||
it != array2->values.end(); it++)
|
||||
if (*it == value)
|
||||
{
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return new IntMV(driver, result);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
IntMV::new_range(MacroDriver &driver, const MacroValue *mv1, const MacroValue *mv2) throw (TypeError)
|
||||
{
|
||||
const IntMV *mv1i = dynamic_cast<const IntMV *>(mv1);
|
||||
const IntMV *mv2i = dynamic_cast<const IntMV *>(mv2);
|
||||
if (mv1i == NULL || mv2i == NULL)
|
||||
throw TypeError("Arguments of range operator (:) must be integers");
|
||||
|
||||
int v1 = mv1i->value;
|
||||
int v2 = mv2i->value;
|
||||
|
||||
vector<int> result;
|
||||
for (; v1 <= v2; v1++)
|
||||
result.push_back(v1);
|
||||
return new ArrayMV<int>(driver, result);
|
||||
}
|
||||
|
||||
StringMV::StringMV(MacroDriver &driver, const string &value_arg) :
|
||||
MacroValue(driver), value(value_arg)
|
||||
{
|
||||
}
|
||||
|
||||
StringMV::~StringMV()
|
||||
{
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
StringMV::operator+(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of + operator");
|
||||
return new StringMV(driver, value + mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
StringMV::operator==(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
return new IntMV(driver, 0);
|
||||
else
|
||||
return new IntMV(driver, value == mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
StringMV::operator!=(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
return new IntMV(driver, 1);
|
||||
else
|
||||
return new IntMV(driver, value != mv2->value);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
StringMV::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError)
|
||||
{
|
||||
const ArrayMV<int> *mv2 = dynamic_cast<const ArrayMV<int> *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Expression inside [] must be an integer array");
|
||||
string result;
|
||||
for (vector<int>::const_iterator it = mv2->values.begin();
|
||||
it != mv2->values.end(); it++)
|
||||
{
|
||||
if (*it < 1 || *it > (int) value.length())
|
||||
throw OutOfBoundsError();
|
||||
char c = value.at(*it - 1);
|
||||
result.append(1, c);
|
||||
}
|
||||
return new StringMV(driver, result);
|
||||
}
|
||||
|
||||
string
|
||||
StringMV::toString() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
string
|
||||
StringMV::print() const
|
||||
{
|
||||
return "'" + value + "'";
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
StringMV::toArray() const
|
||||
{
|
||||
vector<string> v;
|
||||
v.push_back(value);
|
||||
return new ArrayMV<string>(driver, v);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
StringMV::append(const MacroValue *array) const throw (TypeError)
|
||||
{
|
||||
const ArrayMV<string> *array2 = dynamic_cast<const ArrayMV<string> *>(array);
|
||||
if (array2 == NULL)
|
||||
throw TypeError("Type mismatch for append operation");
|
||||
|
||||
vector<string> v(array2->values);
|
||||
v.push_back(value);
|
||||
return new ArrayMV<string>(driver, v);
|
||||
}
|
||||
|
||||
const MacroValue *
|
||||
StringMV::in(const MacroValue *array) const throw (TypeError)
|
||||
{
|
||||
const ArrayMV<string> *array2 = dynamic_cast<const ArrayMV<string> *>(array);
|
||||
if (array2 == NULL)
|
||||
throw TypeError("Type mismatch for 'in' operator");
|
||||
|
||||
int result = 0;
|
||||
for (vector<string>::const_iterator it = array2->values.begin();
|
||||
it != array2->values.end(); it++)
|
||||
if (*it == value)
|
||||
{
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return new IntMV(driver, result);
|
||||
}
|
|
@ -1,395 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2017 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _MACRO_VALUE_HH
|
||||
#define _MACRO_VALUE_HH
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class MacroDriver;
|
||||
|
||||
//! Base class for representing values in macro language
|
||||
class MacroValue
|
||||
{
|
||||
protected:
|
||||
//! Reference to enclosing MacroDriver
|
||||
MacroDriver &driver;
|
||||
public:
|
||||
//! Exception thrown when type error occurs in macro language
|
||||
class TypeError
|
||||
{
|
||||
public:
|
||||
const string message;
|
||||
TypeError(const string &message_arg) : message(message_arg)
|
||||
{
|
||||
};
|
||||
};
|
||||
//! Exception thrown when doing an out-of-bounds access through [] operator
|
||||
class OutOfBoundsError
|
||||
{
|
||||
};
|
||||
MacroValue(MacroDriver &driver_arg);
|
||||
virtual
|
||||
~MacroValue();
|
||||
//! Applies + operator
|
||||
virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError) = 0;
|
||||
//! Applies unary + operator
|
||||
virtual const MacroValue *operator+() const throw (TypeError);
|
||||
//! Applies - operator
|
||||
virtual const MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
|
||||
//! Applies unary - operator
|
||||
virtual const MacroValue *operator-() const throw (TypeError);
|
||||
//! Applies * operator
|
||||
virtual const MacroValue *operator*(const MacroValue &mv) const throw (TypeError);
|
||||
//! Applies / operator
|
||||
virtual const MacroValue *operator/(const MacroValue &mv) const throw (TypeError);
|
||||
//! Less comparison
|
||||
/*! Returns an IntMV, equal to 0 or 1 */
|
||||
virtual const MacroValue *operator<(const MacroValue &mv) const throw (TypeError);
|
||||
//! Greater comparision
|
||||
/*! Returns an IntMV, equal to 0 or 1 */
|
||||
virtual const MacroValue *operator>(const MacroValue &mv) const throw (TypeError);
|
||||
//! Less or equal comparison
|
||||
/*! Returns an IntMV, equal to 0 or 1 */
|
||||
virtual const MacroValue *operator<=(const MacroValue &mv) const throw (TypeError);
|
||||
//! Greater or equal comparison
|
||||
/*! Returns an IntMV, equal to 0 or 1 */
|
||||
virtual const MacroValue *operator>=(const MacroValue &mv) const throw (TypeError);
|
||||
//! Equal comparison
|
||||
/*! Returns an IntMV, equal to 0 or 1 */
|
||||
virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError) = 0;
|
||||
//! Not equal comparison
|
||||
/*! Returns an IntMV, equal to 0 or 1 */
|
||||
virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError) = 0;
|
||||
//! Applies && operator
|
||||
virtual const MacroValue *operator&&(const MacroValue &mv) const throw (TypeError);
|
||||
//! Applies || operator
|
||||
virtual const MacroValue *operator||(const MacroValue &mv) const throw (TypeError);
|
||||
//! Applies unary ! operator
|
||||
virtual const MacroValue *operator!() const throw (TypeError);
|
||||
//! Applies [] operator
|
||||
virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
|
||||
//! Converts value to string
|
||||
virtual string toString() const = 0;
|
||||
//! Converts value to be printed
|
||||
virtual string print() const = 0;
|
||||
//! Converts value to array form
|
||||
virtual const MacroValue *toArray() const = 0;
|
||||
//! Gets length
|
||||
virtual const MacroValue *length() const throw (TypeError);
|
||||
//! Appends value at the end of an array
|
||||
/*! The argument must be an array. */
|
||||
virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
|
||||
//! Applies "in" operator
|
||||
/*! The argument must be an array. Returns an IntMV, equal to 0 or 1 */
|
||||
virtual const MacroValue *in(const MacroValue *array) const throw (TypeError);
|
||||
//! Returns a new IntMV
|
||||
/*! Necessary for ArrayMV::operator[] (template issue) */
|
||||
static const MacroValue *new_base_value(MacroDriver &driver, int i);
|
||||
//! Returns a new StringMV
|
||||
/*! Necessary for ArrayMV::operator[] (template issue) */
|
||||
static const MacroValue *new_base_value(MacroDriver &driver, const string &s);
|
||||
};
|
||||
|
||||
//! Represents an integer value in macro language
|
||||
class IntMV : public MacroValue
|
||||
{
|
||||
friend class StringMV;
|
||||
friend class MacroDriver;
|
||||
private:
|
||||
//! Underlying integer value
|
||||
const int value;
|
||||
public:
|
||||
IntMV(MacroDriver &driver, int value_arg);
|
||||
virtual
|
||||
~IntMV();
|
||||
//! Computes arithmetic addition
|
||||
virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
|
||||
//! Unary plus
|
||||
/*! Returns itself */
|
||||
virtual const MacroValue *operator+() const throw (TypeError);
|
||||
//! Computes arithmetic substraction
|
||||
virtual const MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
|
||||
//! Computes opposite
|
||||
virtual const MacroValue *operator-() const throw (TypeError);
|
||||
//! Computes arithmetic multiplication
|
||||
virtual const MacroValue *operator*(const MacroValue &mv) const throw (TypeError);
|
||||
//! Computes arithmetic division
|
||||
virtual const MacroValue *operator/(const MacroValue &mv) const throw (TypeError);
|
||||
virtual const MacroValue *operator<(const MacroValue &mv) const throw (TypeError);
|
||||
virtual const MacroValue *operator>(const MacroValue &mv) const throw (TypeError);
|
||||
virtual const MacroValue *operator<=(const MacroValue &mv) const throw (TypeError);
|
||||
virtual const MacroValue *operator>=(const MacroValue &mv) const throw (TypeError);
|
||||
virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
|
||||
virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
|
||||
//! Computes logical and
|
||||
virtual const MacroValue *operator&&(const MacroValue &mv) const throw (TypeError);
|
||||
//! Computes logical or
|
||||
virtual const MacroValue *operator||(const MacroValue &mv) const throw (TypeError);
|
||||
//! Computes logical negation
|
||||
virtual const MacroValue *operator!() const throw (TypeError);
|
||||
virtual string toString() const;
|
||||
virtual string print() const;
|
||||
//! Converts value to array form
|
||||
/*! Returns an integer array containing a single value */
|
||||
virtual const MacroValue *toArray() const;
|
||||
//! Appends value at the end of an array
|
||||
/*! The first argument must be an integer array. */
|
||||
virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
|
||||
virtual const MacroValue *in(const MacroValue *array) const throw (TypeError);
|
||||
//! Creates a integer range
|
||||
/*! Arguments must be of type IntMV.
|
||||
Returns an integer array containing all integers between mv1 and mv2.
|
||||
If mv2 < mv1, returns an empty range (for consistency with MATLAB).
|
||||
*/
|
||||
static const MacroValue *new_range(MacroDriver &driver, const MacroValue *mv1, const MacroValue *mv2) throw (TypeError);
|
||||
inline int
|
||||
get_int_value() const
|
||||
{
|
||||
return value;
|
||||
};
|
||||
};
|
||||
|
||||
//! Represents a string value in macro language
|
||||
class StringMV : public MacroValue
|
||||
{
|
||||
friend class MacroDriver;
|
||||
private:
|
||||
//! Underlying string value
|
||||
const string value;
|
||||
public:
|
||||
StringMV(MacroDriver &driver, const string &value_arg);
|
||||
virtual
|
||||
~StringMV();
|
||||
//! Computes string concatenation
|
||||
virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
|
||||
virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
|
||||
virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
|
||||
//! Subscripting operator
|
||||
/*! Argument must be an ArrayMV<int>. Indexes begin at 1. Returns a StringMV. */
|
||||
virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
|
||||
//! Returns underlying string value
|
||||
virtual string toString() const;
|
||||
virtual string print() const;
|
||||
//! Converts value to array form
|
||||
/*! Returns a string array containing a single value */
|
||||
virtual const MacroValue *toArray() const;
|
||||
//! Appends value at the end of an array
|
||||
/*! The first argument must be a string array. Returns a string array. */
|
||||
virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
|
||||
virtual const MacroValue *in(const MacroValue *array) const throw (TypeError);
|
||||
};
|
||||
|
||||
//! Represents an array in macro language
|
||||
template<typename T>
|
||||
class ArrayMV : public MacroValue
|
||||
{
|
||||
friend class IntMV;
|
||||
friend class StringMV;
|
||||
friend class ArrayMV<string>; // Necessary for operator[] to access values of integer array when subscripting a string array
|
||||
friend class MacroDriver;
|
||||
private:
|
||||
//! Underlying vector
|
||||
const vector<T> values;
|
||||
public:
|
||||
ArrayMV(MacroDriver &driver, const vector<T> &values_arg);
|
||||
virtual
|
||||
~ArrayMV();
|
||||
//! Computes array concatenation
|
||||
/*! Both array must be of same type */
|
||||
virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
|
||||
//! Returns an array in which the elements of the second array have been removed from the first
|
||||
/*! It is close to a set difference operation, except that if an element appears two times in the first array, it will also be in the returned value (provided it is not in the second array) */
|
||||
virtual const MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
|
||||
virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
|
||||
virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
|
||||
//! Subscripting operator
|
||||
/*! Argument must be an ArrayMV<int>. Indexes begin at 1.
|
||||
If argument is a one-element array, returns an IntMV or StringMV.
|
||||
Otherwise returns an array. */
|
||||
virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
|
||||
//! Returns a string containing the concatenation of string representations of elements
|
||||
virtual string toString() const;
|
||||
virtual string print() const;
|
||||
//! Returns itself
|
||||
virtual const MacroValue *toArray() const;
|
||||
//! Gets length
|
||||
virtual const MacroValue *length() const throw (TypeError);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
ArrayMV<T>::ArrayMV(MacroDriver &driver, const vector<T> &values_arg) : MacroValue(driver), values(values_arg)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ArrayMV<T>::~ArrayMV()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const MacroValue *
|
||||
ArrayMV<T>::operator+(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of + operator");
|
||||
|
||||
vector<T> values_copy(values);
|
||||
values_copy.insert(values_copy.end(), mv2->values.begin(), mv2->values.end());
|
||||
return new ArrayMV<T>(driver, values_copy);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const MacroValue *
|
||||
ArrayMV<T>::operator-(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Type mismatch for operands of - operator");
|
||||
|
||||
/* Highly inefficient algorithm for computing set difference
|
||||
(but vector<T> is not suited for that...) */
|
||||
vector<T> new_values;
|
||||
for (typename vector<T>::const_iterator it = values.begin();
|
||||
it != values.end(); it++)
|
||||
{
|
||||
typename vector<T>::const_iterator it2;
|
||||
for (it2 = mv2->values.begin(); it2 != mv2->values.end(); it2++)
|
||||
if (*it == *it2)
|
||||
break;
|
||||
if (it2 == mv2->values.end())
|
||||
new_values.push_back(*it);
|
||||
}
|
||||
|
||||
return new ArrayMV<T>(driver, new_values);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const MacroValue *
|
||||
ArrayMV<T>::operator==(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
return new IntMV(driver, 0);
|
||||
else
|
||||
return new IntMV(driver, values == mv2->values);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const MacroValue *
|
||||
ArrayMV<T>::operator!=(const MacroValue &mv) const throw (TypeError)
|
||||
{
|
||||
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
return new IntMV(driver, 1);
|
||||
else
|
||||
return new IntMV(driver, values != mv2->values);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const MacroValue *
|
||||
ArrayMV<T>::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError)
|
||||
{
|
||||
const ArrayMV<int> *mv2 = dynamic_cast<const ArrayMV<int> *>(&mv);
|
||||
if (mv2 == NULL)
|
||||
throw TypeError("Expression inside [] must be an integer array");
|
||||
vector<T> result;
|
||||
for (vector<int>::const_iterator it = mv2->values.begin();
|
||||
it != mv2->values.end(); it++)
|
||||
{
|
||||
if (*it < 1 || *it > (int) values.size())
|
||||
throw OutOfBoundsError();
|
||||
result.push_back(values[*it - 1]);
|
||||
}
|
||||
|
||||
if (result.size() > 1 || result.size() == 0)
|
||||
return new ArrayMV<T>(driver, result);
|
||||
else
|
||||
return MacroValue::new_base_value(driver, result[0]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
string
|
||||
ArrayMV<T>::toString() const
|
||||
{
|
||||
ostringstream ss;
|
||||
for (typename vector<T>::const_iterator it = values.begin();
|
||||
it != values.end(); it++)
|
||||
ss << *it;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
string
|
||||
ArrayMV<T>::print() const
|
||||
{
|
||||
bool printStrArr = false;
|
||||
try
|
||||
{
|
||||
typename vector<T>::const_iterator it = values.begin();
|
||||
boost::lexical_cast<int>(*it);
|
||||
}
|
||||
catch (boost::bad_lexical_cast &)
|
||||
{
|
||||
printStrArr= true;
|
||||
}
|
||||
ostringstream ss;
|
||||
if (printStrArr)
|
||||
ss << "{";
|
||||
else
|
||||
ss << "[";
|
||||
for (typename vector<T>::const_iterator it = values.begin();
|
||||
it != values.end(); it++)
|
||||
{
|
||||
if (it != values.begin())
|
||||
ss << ", ";
|
||||
|
||||
if (printStrArr)
|
||||
ss << "'" << *it << "'";
|
||||
else
|
||||
ss << *it;
|
||||
}
|
||||
if (printStrArr)
|
||||
ss << "}";
|
||||
else
|
||||
ss << "]";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const MacroValue *
|
||||
ArrayMV<T>::toArray() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const MacroValue *
|
||||
ArrayMV<T>::length() const throw (TypeError)
|
||||
{
|
||||
return new IntMV(driver, values.size());
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,23 +0,0 @@
|
|||
noinst_LIBRARIES = libmacro.a
|
||||
|
||||
BUILT_SOURCES = MacroBison.hh stack.hh position.hh location.hh MacroBison.cc MacroFlex.cc
|
||||
|
||||
# We don't put BUILT_SOURCES in libmacro_a_SOURCES, otherwise MacroBison.o and MacroFlex.o will be linked two times (Automake translates MacroFlex.ll and MacroBison.yy into their respective .o); so BUILT_SOURCES is in EXTRA_DIST
|
||||
libmacro_a_SOURCES = \
|
||||
MacroFlex.ll \
|
||||
MacroBison.yy \
|
||||
MacroDriver.cc \
|
||||
MacroDriver.hh \
|
||||
MacroValue.cc \
|
||||
MacroValue.hh
|
||||
|
||||
EXTRA_DIST = $(BUILT_SOURCES)
|
||||
|
||||
# The -I.. is for <FlexLexer.h>
|
||||
libmacro_a_CPPFLAGS = $(BOOST_CPPFLAGS) -I..
|
||||
|
||||
MacroFlex.cc: MacroFlex.ll
|
||||
$(LEX) -o MacroFlex.cc MacroFlex.ll
|
||||
|
||||
MacroBison.cc MacroBison.hh location.hh stack.hh position.hh: MacroBison.yy
|
||||
$(YACC) -o MacroBison.cc MacroBison.yy
|
|
@ -1,5 +1,5 @@
|
|||
function runDynareReport(dc_a, dc_q, db_a, db_q)
|
||||
% Copyright (C) 2013-2015 Dynare Team
|
||||
% Copyright (C) 2013-2018 Dynare Team
|
||||
%
|
||||
% This file is part of Dynare.
|
||||
%
|
||||
|
@ -258,9 +258,9 @@ rep = rep.addSeries('graphHline', 460, ...
|
|||
'graphLineWidth', 1.5);
|
||||
|
||||
a=dseries([1:200]', '1984q1');
|
||||
b=a;
|
||||
c=a;
|
||||
d=a;
|
||||
b=copy(a);
|
||||
c=copy(a);
|
||||
d=copy(a);
|
||||
b(dates('2012q2'):dates('2015q2'))=b(dates('2012q2'):dates('2015q2'))+2;
|
||||
c(dates('2012q2'):dates('2015q2'))=c(dates('2012q2'):dates('2015q2'))+4;
|
||||
d(dates('2012q2'):dates('2015q2'))=d(dates('2012q2'):dates('2015q2'))+6;
|
||||
|
|
Loading…
Reference in New Issue