Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 4.6
  • 5.x
  • 6.x
  • aux_vars_fix
  • julia
  • llvm-15
  • master
  • python-codegen
  • rework_pac
  • uop
  • julia-6.2.0
  • julia-6.3.0
  • julia-6.4.0
  • julia-7.0.0
14 results

Target

Select target project
  • normann/preprocessor
  • Dynare/preprocessor
  • FerhatMihoubi/preprocessor
  • MichelJuillard/preprocessor
  • sebastien/preprocessor
  • lnsongxf/preprocessor
  • albop/preprocessor
  • DoraK/preprocessor
  • amg/preprocessor
  • wmutschl/preprocessor
  • JohannesPfeifer/preprocessor
11 results
Select Git revision
  • 4.6
  • 5.x
  • aux_vars_fix
  • dynare_lite
  • julia
  • master
  • pylib
  • rework_pac
  • uop
  • wasm
  • created_preprocessor_repo
  • julia-6.2.0
12 results
Show changes

Commits on Source 209

109 additional commits have been omitted to prevent performance issues.
Showing
with 6136 additions and 4339 deletions
...@@ -11,8 +11,12 @@ BreakInheritanceList: AfterColon ...@@ -11,8 +11,12 @@ BreakInheritanceList: AfterColon
Cpp11BracedListStyle: true Cpp11BracedListStyle: true
DeriveLineEnding: false DeriveLineEnding: false
IndentPPDirectives: AfterHash IndentPPDirectives: AfterHash
InsertNewlineAtEOF: true
PackConstructorInitializers: NextLine
PPIndentWidth: 1 PPIndentWidth: 1
PointerAlignment: Left PointerAlignment: Left
# RemoveParentheses: ReturnStatement
# RemoveSemicolon: true
SpaceAfterTemplateKeyword: false SpaceAfterTemplateKeyword: false
SpaceBeforeParens: ControlStatements SpaceBeforeParens: ControlStatements
SpaceBeforeCpp11BracedList: true SpaceBeforeCpp11BracedList: true
# TODO: add the following check families:
# - bugprone-*
# - cppcoreguidelines-
# NB: as of clang-tidy 16, we get several false positives inside boost, notably this one:
# https://github.com/llvm/llvm-project/issues/40486
Checks: 'performance-*,modernize-*,-modernize-use-trailing-return-type,-clang-diagnostic-unqualified-std-cast-call'
variables: variables:
TERM: linux TERM: linux
MINGW32_BOOST_VERSION: 1.81.0-7 MINGW64_BOOST_VERSION: 1.88.0-2
MINGW64_BOOST_VERSION: 1.81.0-7
WGET_OPTIONS: '--no-verbose --no-use-server-timestamps --retry-connrefused --retry-on-host-error' WGET_OPTIONS: '--no-verbose --no-use-server-timestamps --retry-connrefused --retry-on-host-error'
# To ensure that "false && true" fails, see https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394#note_412609647 # To ensure that "false && true" fails, see https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394#note_412609647
FF_ENABLE_BASH_EXIT_CODE_CHECK: 'true' FF_ENABLE_BASH_EXIT_CODE_CHECK: 'true'
...@@ -9,7 +8,7 @@ variables: ...@@ -9,7 +8,7 @@ variables:
build_linux_x86_64: build_linux_x86_64:
stage: build stage: build
script: script:
- meson setup -D buildtype=release build - meson setup --buildtype=release -Db_lto=true build
- meson compile -C build -v - meson compile -C build -v
artifacts: artifacts:
paths: paths:
...@@ -18,7 +17,7 @@ build_linux_x86_64: ...@@ -18,7 +17,7 @@ build_linux_x86_64:
build_linux_arm64: build_linux_arm64:
stage: build stage: build
script: script:
- meson setup -D buildtype=release --cross-file scripts/linux-arm64-cross.ini build - meson setup --buildtype=release -Db_lto=true --cross-file scripts/linux-arm64-cross.ini build
- meson compile -C build -v - meson compile -C build -v
artifacts: artifacts:
paths: paths:
...@@ -32,7 +31,7 @@ build_windows_x86_64: ...@@ -32,7 +31,7 @@ build_windows_x86_64:
- mkdir -p deps - mkdir -p deps
- tar xf tarballs/mingw-w64-x86_64-boost-$MINGW64_BOOST_VERSION-any.pkg.tar.zst --directory deps - tar xf tarballs/mingw-w64-x86_64-boost-$MINGW64_BOOST_VERSION-any.pkg.tar.zst --directory deps
- echo -e "[properties]\nboost_root = '$(pwd)/deps/mingw64/'" > boost.ini - echo -e "[properties]\nboost_root = '$(pwd)/deps/mingw64/'" > boost.ini
- meson setup -D buildtype=release --cross-file scripts/windows-cross.ini --cross-file boost.ini build - meson setup --buildtype=release -Db_lto=true --cross-file scripts/windows-cross.ini --cross-file boost.ini build
- meson compile -C build -v - meson compile -C build -v
cache: cache:
# This cache is shared between all branches, to save space # This cache is shared between all branches, to save space
...@@ -48,7 +47,7 @@ build_macos_x86_64: ...@@ -48,7 +47,7 @@ build_macos_x86_64:
tags: tags:
- macOS - macOS
script: script:
- arch -x86_64 meson setup -D buildtype=release --native-file scripts/homebrew-native-x86_64.ini build - arch -x86_64 meson setup --buildtype=release -Db_lto=true --native-file scripts/homebrew-native-x86_64.ini build
- arch -x86_64 meson compile -C build -v - arch -x86_64 meson compile -C build -v
artifacts: artifacts:
paths: paths:
...@@ -60,8 +59,28 @@ build_macos_arm64: ...@@ -60,8 +59,28 @@ build_macos_arm64:
- macOS - macOS
script: script:
- export PATH="/opt/homebrew/bin:$PATH" - export PATH="/opt/homebrew/bin:$PATH"
- arch -arm64 meson setup -D buildtype=release --native-file scripts/homebrew-native-arm64.ini build - arch -arm64 meson setup --buildtype=release -Db_lto=true --native-file scripts/homebrew-native-arm64.ini build
- arch -arm64 meson compile -C build -v - arch -arm64 meson compile -C build -v
artifacts: artifacts:
paths: paths:
- build/src/dynare-preprocessor - build/src/dynare-preprocessor
test_clang_format:
stage: test
script:
- meson setup build-clang-format
- ninja -C build-clang-format clang-format-check
needs: []
test_clang_tidy:
stage: test
script:
# Hack needed for meson < 1.6.0 which only looks for unversioned clang-tidy
- mkdir -p ~/.local/bin && ln -s /usr/bin/clang-tidy-19 ~/.local/bin/clang-tidy
- export PATH="$HOME/.local/bin:$PATH"
- meson setup build-clang-tidy
# Generate Flex and Bison files
- meson compile -C build-clang-tidy
- ninja -C build-clang-tidy clang-tidy
needs: []
when: manual
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
\pgfdeclareimage[height=0.8cm]{logo}{dlogo} \pgfdeclareimage[height=0.8cm]{logo}{dlogo}
\institute[Dynare Team]{\pgfuseimage{logo}} \institute[Dynare Team]{\pgfuseimage{logo}}
\date{23 May 2023} \date{31 May 2024}
\AtBeginSection[] \AtBeginSection[]
{ {
...@@ -156,9 +156,9 @@ ...@@ -156,9 +156,9 @@
\item comparison operators: \texttt{< > <= >= == !=} \item comparison operators: \texttt{< > <= >= == !=}
\item logical operators: \verb+&& || !+ \item logical operators: \verb+&& || !+
\item range with unit increment: \texttt{1:4} is equivalent to \item range with unit increment: \texttt{1:4} is equivalent to
real array \texttt{[1, 2, 3, 4]}. (NB: \texttt{[1:4]} is equivalent to an real array \texttt{[1, 2, 3, 4]} \\ (NB: \texttt{[1:4]} is equivalent to an
array containing an array of reals, \textit{i.e.} \texttt{[[1, 2, 3, 4]]}) array containing an array of reals, \textit{i.e.} \texttt{[[1, 2, 3, 4]]})
\item range with user-defined increment: \texttt{4:-1.1:-1} is equivalent to real array \texttt{[4, 2.9, 1.8, 0.7, -0.4]}. \item range with user-defined increment: \\ \texttt{4:-1.1:-1} is equivalent to real array \texttt{[4, 2.9, 1.8, 0.7, -0.4]}
\end{itemize} \end{itemize}
\end{block} \end{block}
...@@ -314,7 +314,7 @@ Then \texttt{distance(3, 4)} will be equivalent to \texttt{5}. ...@@ -314,7 +314,7 @@ Then \texttt{distance(3, 4)} will be equivalent to \texttt{5}.
\end{frame} \end{frame}
\begin{frame}[fragile=singleslide] \begin{frame}[fragile=singleslide]
\frametitle{Defining macro-variables} \frametitle{Defining macro-variables (1/2)}
The value of a macro-variable can be defined with the \verb+@#define+ The value of a macro-variable can be defined with the \verb+@#define+
directive. directive.
...@@ -335,9 +335,31 @@ Then \texttt{distance(3, 4)} will be equivalent to \texttt{5}. ...@@ -335,9 +335,31 @@ Then \texttt{distance(3, 4)} will be equivalent to \texttt{5}.
@#define t = ("US" in w) // Equals true @#define t = ("US" in w) // Equals true
\end{verbatim} \end{verbatim}
\end{block} \end{block}
NB: You can define macro variables on the Dynare command line by using the \texttt{-D} option
\end{frame} \end{frame}
\begin{frame}[fragile=singleslide]
\frametitle{Defining macro-variables (2/2)}
Macro variables can also be defined on the Dynare command line by using the
\texttt{-D} option, for easily switching between different flavours of a model.
\begin{block}{Example 1}
\begin{verbatim}
dynare myfile.mod -Dx=5
\end{verbatim}
The macro-variable \texttt{x} will be equal to \texttt{5} when running \texttt{myfile.mod}.
\end{block}
\begin{block}{Example 2}
Use single quotes around the \texttt{-D} option when there are spaces or
special characters in the variable definition.
\begin{verbatim}
dynare myfile.mod '-DA=[ i in [1,2,3] when i > 1 ]'
\end{verbatim}
The macro-variable \texttt{A} will be equal to \texttt{[2,3]} when running \texttt{myfile.mod}.
\end{block}
\end{frame}
\begin{frame}[fragile=singleslide] \begin{frame}[fragile=singleslide]
\frametitle{Expression substitution} \frametitle{Expression substitution}
\framesubtitle{Dummy example} \framesubtitle{Dummy example}
...@@ -611,7 +633,7 @@ end; ...@@ -611,7 +633,7 @@ end;
\begin{frame} \begin{frame}
\frametitle{Macro-related command line options} \frametitle{Macro-related command line options}
\begin{itemize} \begin{itemize}
\item \texttt{savemacro}: Useful for debugging or learning purposes, saves the output of the macro processor. If your \texttt{.mod} file is called \texttt{file.mod}, the output is saved to \texttt{file-macroexp.mod}. \item \texttt{savemacro}: Useful for debugging or learning purposes, saves the output of the macro processor. If your \texttt{.mod} file is called \texttt{file.mod}, the output is saved to \texttt{file\_macroexp.mod}.
\item NB: \texttt{savemacro=filename} allows a user-defined file name \item NB: \texttt{savemacro=filename} allows a user-defined file name
\item \texttt{linemacro}: In the output of \texttt{savemacro}, print line numbers where the macro directives were placed. \item \texttt{linemacro}: In the output of \texttt{savemacro}, print line numbers where the macro directives were placed.
\item \texttt{onlymacro}: Stops processing after the macro processing step. \item \texttt{onlymacro}: Stops processing after the macro processing step.
...@@ -866,7 +888,7 @@ rhos = [ 0.8, 0.9, 1]; ...@@ -866,7 +888,7 @@ rhos = [ 0.8, 0.9, 1];
\ccbysa \ccbysa
\column{0.71\textwidth} \column{0.71\textwidth}
\tiny \tiny
Copyright © 2008-2023 Dynare Team \\ Copyright © 2008-2024 Dynare Team \\
License: \href{http://creativecommons.org/licenses/by-sa/4.0/}{Creative License: \href{http://creativecommons.org/licenses/by-sa/4.0/}{Creative
Commons Attribution-ShareAlike 4.0} Commons Attribution-ShareAlike 4.0}
\end{columns} \end{columns}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# It is not used when building Dynare as a whole. # It is not used when building Dynare as a whole.
project('dynare-preprocessor', 'cpp', project('dynare-preprocessor', 'cpp',
version : '6-unstable', version : '7-unstable',
# NB: update C++ standard in .clang-format whenever the following is modified # NB: update C++ standard in .clang-format whenever the following is modified
default_options : [ 'cpp_std=gnu++20', 'warning_level=2' ], default_options : [ 'cpp_std=gnu++20', 'warning_level=2' ],
meson_version : '>=0.64.0') meson_version : '>=0.64.0')
......
# Meson native file for compiling under Homebrew / arm64 # Meson native file for compiling under Homebrew / arm64
[binaries] [binaries]
cpp = '/opt/homebrew/bin/g++-13' cpp = '/opt/homebrew/bin/g++-15'
flex = '/opt/homebrew/opt/flex/bin/flex' flex = '/opt/homebrew/opt/flex/bin/flex'
bison = '/opt/homebrew/opt/bison/bin/bison' bison = '/opt/homebrew/opt/bison/bin/bison'
......
# Meson native file for compiling under Homebrew / x86-64 # Meson native file for compiling under Homebrew / x86-64
[binaries] [binaries]
cpp = '/usr/local/bin/g++-13' cpp = '/usr/local/bin/g++-15'
flex = '/usr/local/opt/flex/bin/flex' flex = '/usr/local/opt/flex/bin/flex'
bison = '/usr/local/opt/bison/bin/bison' bison = '/usr/local/opt/bison/bin/bison'
......
# Meson cross file for creating a WebAssembly version of the preprocessor.
#
# Requires emscripten to be installed.
# Was successfully tested with emscripten 3.1.69 installed through emsdk
# tool, as described on: https://emscripten.org/docs/getting_started/downloads.html
# Don’t forget to source script snippet in current shell before running meson.
#
# Compilation creates a .wasm and .js wrapper under <builddir>/src/
#
# Can be run locally with node.js using:
# node dynare-preprocessor.js file.mod
# NB: a version of node.js is shipped with emscripten (under the node/
# subdirectory), but another version should also work.
[binaries]
cpp = 'em++'
[host_machine]
system = 'emscripten'
# Could be changed to wasm64 if 4GB memory constraint is hit
# Some background: https://v8.dev/blog/4gb-wasm-memory
cpu_family = 'wasm32'
cpu = 'wasm32'
endian = 'little'
[built-in options]
# Never do a debug build, because otherwise the lack of optimisations can
# overflow the memory capacities.
buildtype = 'release'
# The -fexceptions flag (for both compilation and linking) is needed for an
# unknown reason (C++ compilers are supposed to always add exception support).
# The -Wno-unqualified-std-cast-call flag removes many warnings about “move”
# not being qualified with “std::” namespace.
# The -fexperimental-library flag is needed to get std::jthread support (it was
# supposed to no longer be necessary for LLVM 20, but for some reason we still
# need it).
cpp_args = [ '-fexceptions', '-Wno-unqualified-std-cast-call', '-fexperimental-library' ]
# NODERAWFS=1 is needed for accessing the local filesystem
cpp_link_args = [ '-s', 'NODERAWFS=1', '-fexceptions' ]
[properties]
# It’s necessary to use a different copy of Boost than the one under
# /usr/include, because otherwise GCC headers confuse Clang
boost_root = '/tmp/boost_1_86_0'
/* /*
* Copyright © 2022-2023 Dynare Team * Copyright © 2022-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -17,14 +17,17 @@ ...@@ -17,14 +17,17 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <iostream>
#include <ios>
#include <cstdlib>
#include <algorithm> #include <algorithm>
#include <cstdlib>
#include <ios>
#include <iostream>
#include "Bytecode.hh" #include "Bytecode.hh"
BytecodeWriter::BytecodeWriter(const filesystem::path &filename) namespace Bytecode
{
Writer::Writer(const filesystem::path& filename)
{ {
open(filename, ios::out | ios::binary); open(filename, ios::out | ios::binary);
if (!is_open()) if (!is_open())
...@@ -35,17 +38,16 @@ BytecodeWriter::BytecodeWriter(const filesystem::path &filename) ...@@ -35,17 +38,16 @@ BytecodeWriter::BytecodeWriter(const filesystem::path &filename)
} }
template<> template<>
BytecodeWriter & Writer&
operator<<(BytecodeWriter &code_file, const FCALL_ &instr) operator<<(Writer& code_file, const FCALL& instr)
{ {
code_file.instructions_positions.push_back(code_file.tellp()); code_file.instructions_positions.push_back(code_file.tellp());
auto write_member = [&code_file](const auto &member) auto write_member = [&code_file](const auto& member) {
{
code_file.write(reinterpret_cast<const char*>(&member), sizeof member); code_file.write(reinterpret_cast<const char*>(&member), sizeof member);
}; };
write_member(instr.op_code); write_member(instr.tag);
write_member(instr.nb_output_arguments); write_member(instr.nb_output_arguments);
write_member(instr.nb_input_arguments); write_member(instr.nb_input_arguments);
write_member(instr.indx); write_member(instr.indx);
...@@ -66,23 +68,22 @@ operator<<(BytecodeWriter &code_file, const FCALL_ &instr) ...@@ -66,23 +68,22 @@ operator<<(BytecodeWriter &code_file, const FCALL_ &instr)
} }
template<> template<>
BytecodeWriter & Writer&
operator<<(BytecodeWriter &code_file, const FBEGINBLOCK_ &instr) operator<<(Writer& code_file, const FBEGINBLOCK& instr)
{ {
code_file.instructions_positions.push_back(code_file.tellp()); code_file.instructions_positions.push_back(code_file.tellp());
auto write_member = [&code_file](const auto &member) auto write_member = [&code_file](const auto& member) {
{
code_file.write(reinterpret_cast<const char*>(&member), sizeof member); code_file.write(reinterpret_cast<const char*>(&member), sizeof member);
}; };
write_member(instr.op_code); write_member(instr.tag);
write_member(instr.size); write_member(instr.size);
write_member(instr.type); write_member(instr.type);
for (int i = 0; i < instr.size; i++) for (int i = 0; i < instr.size; i++)
{ {
write_member(instr.variable[i]); write_member(instr.variables[i]);
write_member(instr.equation[i]); write_member(instr.equations[i]);
} }
if (instr.type == BlockSimulationType::solveTwoBoundariesSimple if (instr.type == BlockSimulationType::solveTwoBoundariesSimple
|| instr.type == BlockSimulationType::solveTwoBoundariesComplete || instr.type == BlockSimulationType::solveTwoBoundariesComplete
...@@ -96,8 +97,10 @@ operator<<(BytecodeWriter &code_file, const FBEGINBLOCK_ &instr) ...@@ -96,8 +97,10 @@ operator<<(BytecodeWriter &code_file, const FBEGINBLOCK_ &instr)
write_member(instr.det_exo_size); write_member(instr.det_exo_size);
write_member(instr.exo_size); write_member(instr.exo_size);
for_each_n(instr.det_exogenous.begin(), instr.det_exo_size, write_member); ranges::for_each_n(instr.det_exogenous.begin(), instr.det_exo_size, write_member);
for_each_n(instr.exogenous.begin(), instr.exo_size, write_member); ranges::for_each_n(instr.exogenous.begin(), instr.exo_size, write_member);
return code_file; return code_file;
} }
}
/* /*
* Copyright © 2007-2023 Dynare Team * Copyright © 2007-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -17,50 +17,66 @@ ...@@ -17,50 +17,66 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef _BYTECODE_HH #ifndef BYTECODE_HH
#define _BYTECODE_HH #define BYTECODE_HH
#include <concepts>
#include <filesystem>
#include <fstream> #include <fstream>
#include <vector>
#include <utility>
#include <ios> #include <ios>
#include <filesystem>
#include <type_traits> #include <type_traits>
#include <utility>
#include <vector>
#include "CommonEnums.hh" #include "CommonEnums.hh"
using namespace std; using namespace std;
// The different opcodes of bytecode namespace Bytecode
enum class Tags {
// The different tags encoding a bytecode instruction
enum class Tag
{ {
FLDZ, // Loads a zero onto the stack FLDZ, // Loads a zero onto the stack
FLDC, // Loads a constant term onto the stack FLDC, // Loads a constant term onto the stack
FDIMT, // Defines the number of temporary terms - dynamic context (the period has to be indicated) FDIMT, // Defines the number of temporary terms - dynamic context (the period has to be indicated)
FDIMST, // Defines the number of temporary terms - static context (the period hasn’t to be indicated) FDIMST, // Defines the number of temporary terms - static context (the period hasn’t to be
// indicated)
FLDT, // Loads a temporary term onto the stack - dynamic context (the period has to be indicated) FLDT, // Loads a temporary term onto the stack - dynamic context (the period has to be indicated)
FLDST, // Loads a temporary term onto the stack - static context (the period hasn’t to be indicated) FLDST, // Loads a temporary term onto the stack - static context (the period hasn’t to be
FSTPT, // Stores a temporary term from the stack - dynamic context (the period has to be indicated) // indicated)
FSTPST, // Stores a temporary term from the stack - static context (the period hasn’t to be indicated) FSTPT, // Stores a temporary term from the stack - dynamic context (the period has to be
// indicated)
FLDU, // Loads an element of the vector U onto the stack - dynamic context (the period has to be indicated) FSTPST, // Stores a temporary term from the stack - static context (the period hasn’t to be
FLDSU, // Loads an element of the vector U onto the stack - static context (the period hasn’t to be indicated) // indicated)
FSTPU, // Stores an element of the vector U from the stack - dynamic context (the period has to be indicated)
FSTPSU, // Stores an element of the vector U from the stack - static context (the period hasn’t to be indicated) FLDU, // Loads an element of the vector U onto the stack - dynamic context (the period has to be
// indicated)
FLDV, // Loads a variable (described in SymbolType) onto the stack - dynamic context (the period has to be indicated) FLDSU, // Loads an element of the vector U onto the stack - static context (the period hasn’t to
FLDSV, // Loads a variable (described in SymbolType) onto the stack - static context (the period hasn’t to be indicated) // be indicated)
FLDVS, // Loads a variable (described in SymbolType) onto the stack - dynamic context but inside the STEADY_STATE operator (the period hasn’t to be indicated) FSTPU, // Stores an element of the vector U from the stack - dynamic context (the period has to be
FSTPV, // Stores a variable (described in SymbolType) from the stack - dynamic context (the period has to be indicated) // indicated)
FSTPSV, // Stores a variable (described in SymbolType) from the stack - static context (the period hasn’t to be indicated) FSTPSU, // Stores an element of the vector U from the stack - static context (the period hasn’t to
// be indicated)
FLDV, // Loads a variable (described in SymbolType) onto the stack - dynamic context (the period
// has to be indicated)
FLDSV, // Loads a variable (described in SymbolType) onto the stack - static context (the period
// hasn’t to be indicated)
FLDVS, // Loads a variable (described in SymbolType) onto the stack - dynamic context but inside
// the STEADY_STATE operator (the period hasn’t to be indicated)
FSTPV, // Stores a variable (described in SymbolType) from the stack - dynamic context (the period
// has to be indicated)
FSTPSV, // Stores a variable (described in SymbolType) from the stack - static context (the period
// hasn’t to be indicated)
FLDR, // Loads a residual onto the stack FLDR, // Loads a residual onto the stack
FSTPR, // Stores a residual from the stack FSTPR, // Stores a residual from the stack
FSTPG, // Stores a derivative from the stack FSTPG, // Stores the derivative of a simple (single-equation) block in simulate mode
FSTPG2, // Stores a derivative matrix for a static model from the stack FSTPG2, // Stores the derivative matrix of a block in evaluate mode
FSTPG3, // Stores a derivative matrix for a dynamic model from the stack
FUNARY, // A unary operator FUNARY, // A unary operator
FBINARY, // A binary operator FBINARY, // A binary operator
...@@ -71,7 +87,8 @@ enum class Tags ...@@ -71,7 +87,8 @@ enum class Tags
FBEGINBLOCK, // Marks the beginning of a model block FBEGINBLOCK, // Marks the beginning of a model block
FENDBLOCK, // Marks the end of a model block FENDBLOCK, // Marks the end of a model block
FENDEQU, // Marks the last equation of the block; for a block that has to be solved, the derivatives appear just after this flag FENDEQU, // Marks the last equation of the block; for a block that has to be solved, the
// derivatives appear just after this flag
FEND, // Marks the end of the model code FEND, // Marks the end of the model code
FNUMEXPR, // Stores the expression type and references FNUMEXPR, // Stores the expression type and references
...@@ -105,660 +122,342 @@ enum class ExternalFunctionCallType ...@@ -105,660 +122,342 @@ enum class ExternalFunctionCallType
numericalSecondDerivative numericalSecondDerivative
}; };
struct Block_contain_type class Writer;
{
int Equation, Variable, Own_Derivative;
};
class BytecodeWriter;
struct BytecodeInstruction struct Instruction
{ {
const Tags op_code; const Tag tag;
explicit BytecodeInstruction(Tags op_code_arg) : explicit Instruction(Tag tag_arg) : tag {tag_arg}
op_code {op_code_arg}
{ {
} }
protected: protected:
/* This is a base class, so the destructor should be either public+virtual or /* This is a base class, so the destructor should be either public+virtual or
protected+non-virtual. We opt for the latter, because otherwise this class protected+non-virtual. We opt for the latter, because otherwise this class
would no longer be POD; its memory representation would also include would no longer be POD; its memory representation would also include
runtime type information, and our crude serialization technique (copying the runtime type information, and our crude serialization technique (copying the
whole object from memory) would thus not work. */ whole object from memory) would thus not work. */
~BytecodeInstruction() = default; ~Instruction() = default;
}; };
template<typename T1> template<typename T>
class TagWithOneArgument : public BytecodeInstruction concept IsInstruction = derived_from<T, Instruction>;
{
protected:
T1 arg1;
public:
TagWithOneArgument(Tags op_code_arg, T1 arg_arg1) : BytecodeInstruction{op_code_arg},
arg1{arg_arg1}
{
};
protected:
// See BytecodeInstruction destructor for the rationale
~TagWithOneArgument() = default;
};
template<typename T1, typename T2> struct FLDZ final : public Instruction
class TagWithTwoArguments : public BytecodeInstruction
{ {
protected: FLDZ() : Instruction {Tag::FLDZ}
T1 arg1;
T2 arg2;
public:
TagWithTwoArguments(Tags op_code_arg, T1 arg_arg1, T2 arg_arg2) :
BytecodeInstruction{op_code_arg}, arg1{arg_arg1}, arg2{arg_arg2}
{ {
}; }
protected:
// See BytecodeInstruction destructor for the rationale
~TagWithTwoArguments() = default;
};
template<typename T1, typename T2, typename T3>
class TagWithThreeArguments : public BytecodeInstruction
{
protected:
T1 arg1;
T2 arg2;
T3 arg3;
public:
TagWithThreeArguments(Tags op_code_arg, T1 arg_arg1, T2 arg_arg2, T3 arg_arg3) :
BytecodeInstruction{op_code_arg}, arg1{arg_arg1}, arg2{arg_arg2}, arg3{arg_arg3}
{
};
protected:
// See BytecodeInstruction destructor for the rationale
~TagWithThreeArguments() = default;
};
template<typename T1, typename T2, typename T3, typename T4>
class TagWithFourArguments : public BytecodeInstruction
{
protected:
T1 arg1;
T2 arg2;
T3 arg3;
T4 arg4;
public:
TagWithFourArguments(Tags op_code_arg, T1 arg_arg1, T2 arg_arg2, T3 arg_arg3, T4 arg_arg4) :
BytecodeInstruction{op_code_arg}, arg1{arg_arg1}, arg2{arg_arg2},
arg3{move(arg_arg3)}, arg4{arg_arg4}
{
};
protected:
// See BytecodeInstruction destructor for the rationale
~TagWithFourArguments() = default;
};
class FLDZ_ final : public BytecodeInstruction
{
public:
FLDZ_() : BytecodeInstruction{Tags::FLDZ}
{
};
}; };
class FEND_ final : public BytecodeInstruction struct FEND final : public Instruction
{ {
public: FEND() : Instruction {Tag::FEND}
FEND_() : BytecodeInstruction{Tags::FEND}
{ {
}; }
}; };
class FENDBLOCK_ final : public BytecodeInstruction struct FENDBLOCK final : public Instruction
{ {
public: FENDBLOCK() : Instruction {Tag::FENDBLOCK}
FENDBLOCK_() : BytecodeInstruction{Tags::FENDBLOCK}
{ {
}; }
}; };
class FENDEQU_ final : public BytecodeInstruction struct FENDEQU final : public Instruction
{ {
public: FENDEQU() : Instruction {Tag::FENDEQU}
FENDEQU_() : BytecodeInstruction{Tags::FENDEQU}
{ {
}; }
}; };
class FDIMT_ final : public TagWithOneArgument<int> struct FDIMT final : public Instruction
{ {
public: const int size;
explicit FDIMT_(int size_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FDIMT, size_arg} explicit FDIMT(int size_arg) : Instruction {Tag::FDIMT}, size {size_arg}
{ {
}; }
int
get_size()
{
return arg1;
};
}; };
class FDIMST_ final : public TagWithOneArgument<int> struct FDIMST final : public Instruction
{ {
public: const int size;
explicit FDIMST_(int size_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FDIMST, size_arg} explicit FDIMST(int size_arg) : Instruction {Tag::FDIMST}, size {size_arg}
{ {
}; }
int
get_size()
{
return arg1;
};
}; };
class FLDC_ final : public TagWithOneArgument<double> struct FLDC final : public Instruction
{
public:
explicit FLDC_(double value_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FLDC, value_arg}
{ {
}; const double value;
double explicit FLDC(double value_arg) : Instruction {Tag::FLDC}, value {value_arg}
get_value()
{ {
return arg1; }
};
}; };
class FLDU_ final : public TagWithOneArgument<int> struct FLDU final : public Instruction
{ {
public: const int pos;
explicit FLDU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FLDU, pos_arg} explicit FLDU(int pos_arg) : Instruction {Tag::FLDU}, pos {pos_arg}
{
};
int
get_pos()
{ {
return arg1; }
};
}; };
class FLDSU_ final : public TagWithOneArgument<int> struct FLDSU final : public Instruction
{ {
public: const int pos;
explicit FLDSU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FLDSU, pos_arg} explicit FLDSU(int pos_arg) : Instruction {Tag::FLDSU}, pos {pos_arg}
{
};
int
get_pos()
{ {
return arg1; }
};
}; };
class FLDR_ final : public TagWithOneArgument<int> struct FLDR final : public Instruction
{ {
public: const int pos;
explicit FLDR_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FLDR, pos_arg} explicit FLDR(int pos_arg) : Instruction {Tag::FLDR}, pos {pos_arg}
{ {
}; }
int
get_pos()
{
return arg1;
};
}; };
class FLDT_ final : public TagWithOneArgument<int> struct FLDT final : public Instruction
{
public:
explicit FLDT_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FLDT, pos_arg}
{ {
}; const int pos;
int explicit FLDT(int pos_arg) : Instruction {Tag::FLDT}, pos {pos_arg}
get_pos()
{ {
return arg1; }
};
}; };
class FLDST_ final : public TagWithOneArgument<int> struct FLDST final : public Instruction
{
public:
explicit FLDST_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FLDST, pos_arg}
{ {
}; const int pos;
int explicit FLDST(int pos_arg) : Instruction {Tag::FLDST}, pos {pos_arg}
get_pos()
{ {
return arg1; }
};
}; };
class FSTPT_ final : public TagWithOneArgument<int> struct FSTPT final : public Instruction
{
public:
explicit FSTPT_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPT, pos_arg}
{ {
}; const int pos;
int explicit FSTPT(int pos_arg) : Instruction {Tag::FSTPT}, pos {pos_arg}
get_pos()
{ {
return arg1; }
};
}; };
class FSTPST_ final : public TagWithOneArgument<int> struct FSTPST final : public Instruction
{
public:
explicit FSTPST_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPST, pos_arg}
{ {
}; const int pos;
int explicit FSTPST(int pos_arg) : Instruction {Tag::FSTPST}, pos {pos_arg}
get_pos()
{ {
return arg1; }
};
}; };
class FSTPR_ final : public TagWithOneArgument<int> struct FSTPR final : public Instruction
{
public:
explicit FSTPR_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPR, pos_arg}
{ {
}; const int pos;
int explicit FSTPR(int pos_arg) : Instruction {Tag::FSTPR}, pos {pos_arg}
get_pos()
{ {
return arg1; }
};
}; };
class FSTPU_ final : public TagWithOneArgument<int> struct FSTPU final : public Instruction
{
public:
explicit FSTPU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPU, pos_arg}
{ {
}; const int pos;
int explicit FSTPU(int pos_arg) : Instruction {Tag::FSTPU}, pos {pos_arg}
get_pos()
{ {
return arg1; }
};
}; };
class FSTPSU_ final : public TagWithOneArgument<int> struct FSTPSU final : public Instruction
{
public:
explicit FSTPSU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPSU, pos_arg}
{ {
}; const int pos;
int explicit FSTPSU(int pos_arg) : Instruction {Tag::FSTPSU}, pos {pos_arg}
get_pos()
{ {
return arg1; }
};
}; };
class FSTPG_ final : public TagWithOneArgument<int> struct FSTPG final : public Instruction
{
public:
explicit FSTPG_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPG, pos_arg}
{ {
}; explicit FSTPG() : Instruction {Tag::FSTPG}
int
get_pos()
{ {
return arg1; }
};
}; };
class FSTPG2_ final : public TagWithTwoArguments<int, int> struct FSTPG2 final : public Instruction
{
public:
FSTPG2_(int row_arg, int col_arg) : TagWithTwoArguments::TagWithTwoArguments{Tags::FSTPG2, row_arg, col_arg}
{
};
int
get_row()
{ {
return arg1; const int row, col;
}; FSTPG2(int row_arg, int col_arg) : Instruction {Tag::FSTPG2}, row {row_arg}, col {col_arg}
int
get_col()
{ {
return arg2; }
};
}; };
class FSTPG3_ final : public TagWithFourArguments<int, int, int, int> struct FUNARY final : public Instruction
{
public:
FSTPG3_(int row_arg, int col_arg, int lag_arg, int col_pos_arg) : TagWithFourArguments::TagWithFourArguments{Tags::FSTPG3, row_arg, col_arg, lag_arg, col_pos_arg}
{
};
int
get_row()
{
return arg1;
};
int
get_col()
{ {
return arg2; const UnaryOpcode op_code;
}; explicit FUNARY(UnaryOpcode op_code_arg) : Instruction {Tag::FUNARY}, op_code {op_code_arg}
int
get_lag()
{
return arg3;
};
int
get_col_pos()
{ {
return arg4; }
};
}; };
class FUNARY_ final : public TagWithOneArgument<UnaryOpcode> struct FBINARY final : public Instruction
{
public:
explicit FUNARY_(UnaryOpcode op_type_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FUNARY, op_type_arg}
{ {
}; const BinaryOpcode op_code;
UnaryOpcode explicit FBINARY(BinaryOpcode op_code_arg) : Instruction {Tag::FBINARY}, op_code {op_code_arg}
get_op_type()
{ {
return arg1; }
};
}; };
class FBINARY_ final : public TagWithOneArgument<BinaryOpcode> struct FTRINARY final : public Instruction
{ {
public: const TrinaryOpcode op_code;
explicit FBINARY_(BinaryOpcode op_type_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FBINARY, op_type_arg} explicit FTRINARY(TrinaryOpcode op_code_arg) : Instruction {Tag::FTRINARY}, op_code {op_code_arg}
{
};
BinaryOpcode
get_op_type()
{ {
return arg1; }
};
}; };
class FTRINARY_ final : public TagWithOneArgument<TrinaryOpcode> struct FJMPIFEVAL final : public Instruction
{ {
public: const int pos;
explicit FTRINARY_(TrinaryOpcode op_type_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FTRINARY, op_type_arg} explicit FJMPIFEVAL(int pos_arg) : Instruction {Tag::FJMPIFEVAL}, pos {pos_arg}
{ {
}; }
TrinaryOpcode
get_op_type()
{
return arg1;
};
}; };
class FJMPIFEVAL_ final : public TagWithOneArgument<int> struct FJMP final : public Instruction
{
public:
explicit FJMPIFEVAL_(int arg_pos) : TagWithOneArgument::TagWithOneArgument{Tags::FJMPIFEVAL, arg_pos}
{ {
}; const int pos;
int explicit FJMP(int pos_arg) : Instruction {Tag::FJMP}, pos {pos_arg}
get_pos()
{ {
return arg1;
} }
}; };
class FJMP_ final : public TagWithOneArgument<int> struct FLDTEF final : public Instruction
{ {
public: const int number;
explicit FJMP_(int arg_pos) : TagWithOneArgument::TagWithOneArgument{Tags::FJMP, arg_pos} explicit FLDTEF(int number_arg) : Instruction {Tag::FLDTEF}, number {number_arg}
{
};
int
get_pos()
{ {
return arg1;
} }
}; };
class FLDTEF_ final : public TagWithOneArgument<int> struct FSTPTEF final : public Instruction
{
public:
explicit FLDTEF_(int number) : TagWithOneArgument::TagWithOneArgument{Tags::FLDTEF, number}
{ {
}; const int number;
int explicit FSTPTEF(int number_arg) : Instruction {Tag::FSTPTEF}, number {number_arg}
get_number()
{ {
return arg1;
} }
}; };
class FSTPTEF_ final : public TagWithOneArgument<int> struct FLDTEFD final : public Instruction
{
public:
explicit FSTPTEF_(int number) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPTEF, number}
{ {
}; const int indx, row;
int FLDTEFD(int indx_arg, int row_arg) : Instruction {Tag::FLDTEFD}, indx {indx_arg}, row {row_arg}
get_number()
{ {
return arg1;
} }
}; };
class FLDTEFD_ final : public TagWithTwoArguments<int, int> struct FSTPTEFD final : public Instruction
{
public:
FLDTEFD_(int indx, int row) : TagWithTwoArguments::TagWithTwoArguments{Tags::FLDTEFD, indx, row}
{
};
int
get_indx()
{ {
return arg1; const int indx, row;
}; FSTPTEFD(int indx_arg, int row_arg) : Instruction {Tag::FSTPTEFD}, indx {indx_arg}, row {row_arg}
int
get_row()
{ {
return arg2; }
};
}; };
class FSTPTEFD_ final : public TagWithTwoArguments<int, int> struct FLDTEFDD final : public Instruction
{
public:
FSTPTEFD_(int indx, int row) : TagWithTwoArguments::TagWithTwoArguments{Tags::FSTPTEFD, indx, row}
{
};
int
get_indx()
{ {
return arg1; const int indx, row, col;
}; FLDTEFDD(int indx_arg, int row_arg, int col_arg) :
int Instruction {Tag::FLDTEFDD}, indx {indx_arg}, row {row_arg}, col {col_arg}
get_row()
{ {
return arg2; }
};
}; };
class FLDTEFDD_ final : public TagWithThreeArguments<int, int, int> struct FSTPTEFDD final : public Instruction
{
public:
FLDTEFDD_(int indx, int row, int col) : TagWithThreeArguments::TagWithThreeArguments{Tags::FLDTEFDD, indx, row, col}
{ {
}; const int indx, row, col;
int FSTPTEFDD(int indx_arg, int row_arg, int col_arg) :
get_indx() Instruction {Tag::FSTPTEF}, indx {indx_arg}, row {row_arg}, col {col_arg}
{ {
return arg1; }
};
int
get_row()
{
return arg2;
};
int
get_col()
{
return arg3;
};
}; };
class FSTPTEFDD_ final : public TagWithThreeArguments<int, int, int> struct FLDVS final : public Instruction
{
public:
FSTPTEFDD_(int indx, int row, int col) : TagWithThreeArguments::TagWithThreeArguments{Tags::FSTPTEF, indx, row, col}
{ {
}; const SymbolType type;
int const int pos;
get_indx() FLDVS(SymbolType type_arg, int pos_arg) : Instruction {Tag::FLDVS}, type {type_arg}, pos {pos_arg}
{ {
return arg1; }
};
int
get_row()
{
return arg2;
};
int
get_col()
{
return arg3;
};
}; };
class FLDVS_ final : public TagWithTwoArguments<SymbolType, int> struct FLDSV final : public Instruction
{
public:
FLDVS_(SymbolType type_arg, int pos_arg) : TagWithTwoArguments::TagWithTwoArguments{Tags::FLDVS, type_arg, pos_arg}
{
};
SymbolType
get_type()
{ {
return arg1; const SymbolType type;
}; const int pos;
int FLDSV(SymbolType type_arg, int pos_arg) : Instruction {Tag::FLDSV}, type {type_arg}, pos {pos_arg}
get_pos()
{ {
return arg2; }
};
}; };
class FLDSV_ final : public TagWithTwoArguments<SymbolType, int> struct FSTPSV final : public Instruction
{ {
public: const SymbolType type;
FLDSV_(SymbolType type_arg, int pos_arg) : TagWithTwoArguments::TagWithTwoArguments{Tags::FLDSV, type_arg, pos_arg} const int pos;
{ FSTPSV(SymbolType type_arg, int pos_arg) :
}; Instruction {Tag::FSTPSV}, type {type_arg}, pos {pos_arg}
SymbolType
get_type()
{ {
return arg1; }
};
int
get_pos()
{
return arg2;
};
}; };
class FSTPSV_ final : public TagWithTwoArguments<SymbolType, int> struct FLDV final : public Instruction
{ {
public: const SymbolType type;
FSTPSV_(SymbolType type_arg, int pos_arg) : TagWithTwoArguments::TagWithTwoArguments{Tags::FSTPSV, type_arg, pos_arg} const int pos, lead_lag;
FLDV(SymbolType type_arg, int pos_arg, int lead_lag_arg) :
Instruction {Tag::FLDV}, type {type_arg}, pos {pos_arg}, lead_lag {lead_lag_arg}
{ {
}; }
SymbolType
get_type()
{
return arg1;
};
int
get_pos()
{
return arg2;
};
}; };
class FLDV_ final : public TagWithThreeArguments<SymbolType, int, int> struct FSTPV final : public Instruction
{
public:
FLDV_(SymbolType type_arg, int pos_arg, int lead_lag_arg) :
TagWithThreeArguments::TagWithThreeArguments{Tags::FLDV, type_arg, pos_arg, lead_lag_arg}
{
};
SymbolType
get_type()
{ {
return arg1; const SymbolType type;
}; const int pos, lead_lag;
int FSTPV(SymbolType type_arg, int pos_arg, int lead_lag_arg) :
get_pos() Instruction {Tag::FSTPV}, type {type_arg}, pos {pos_arg}, lead_lag {lead_lag_arg}
{
return arg2;
};
int
get_lead_lag()
{ {
return arg3; }
};
}; };
class FSTPV_ final : public TagWithThreeArguments<SymbolType, int, int> class FCALL final : public Instruction
{
public:
FSTPV_(SymbolType type_arg, int pos_arg, int lead_lag_arg) :
TagWithThreeArguments::TagWithThreeArguments{Tags::FSTPV, type_arg, pos_arg, lead_lag_arg}
{
};
SymbolType
get_type()
{
return arg1;
};
int
get_pos()
{
return arg2;
};
int
get_lead_lag()
{ {
return arg3; template<IsInstruction B>
}; friend Writer& operator<<(Writer& code_file, const B& instr);
};
class FCALL_ final : public BytecodeInstruction
{
template<typename B>
friend BytecodeWriter &operator<<(BytecodeWriter &code_file, const B &instr);
private: private:
int nb_output_arguments, nb_input_arguments, indx; int nb_output_arguments, nb_input_arguments, indx;
string func_name; string func_name;
string arg_func_name; string arg_func_name;
int add_input_arguments {0}, row {0}, col {0}; int add_input_arguments {0}, row {0}, col {0};
ExternalFunctionCallType call_type; ExternalFunctionCallType call_type;
public: public:
FCALL_(int nb_output_arguments_arg, int nb_input_arguments_arg, string func_name_arg, int indx_arg, ExternalFunctionCallType call_type_arg) : FCALL(int nb_output_arguments_arg, int nb_input_arguments_arg, string func_name_arg, int indx_arg,
BytecodeInstruction{Tags::FCALL}, ExternalFunctionCallType call_type_arg) :
Instruction {Tag::FCALL},
nb_output_arguments {nb_output_arguments_arg}, nb_output_arguments {nb_output_arguments_arg},
nb_input_arguments {nb_input_arguments_arg}, nb_input_arguments {nb_input_arguments_arg},
indx {indx_arg}, indx {indx_arg},
func_name {move(func_name_arg)}, func_name {move(func_name_arg)},
call_type {call_type_arg} call_type {call_type_arg}
{ {
}; }
/* Deserializing constructor. /* Deserializing constructor.
Updates the code pointer to point beyond the bytes read. */ Updates the code pointer to point beyond the bytes read. */
FCALL_(char *&code) : FCALL(char*& code) : Instruction {Tag::FCALL}
BytecodeInstruction{Tags::FCALL}
{ {
code += sizeof(op_code); code += sizeof(tag);
auto read_member = [&code](auto &member) auto read_member = [&code](auto& member) {
{
member = *reinterpret_cast<add_pointer_t<decltype(member)>>(code); member = *reinterpret_cast<add_pointer_t<decltype(member)>>(code);
code += sizeof member; code += sizeof member;
}; };
...@@ -786,47 +485,47 @@ public: ...@@ -786,47 +485,47 @@ public:
{ {
// printf("get_function_name => func_name=%s\n",func_name.c_str());fflush(stdout); // printf("get_function_name => func_name=%s\n",func_name.c_str());fflush(stdout);
return func_name; return func_name;
}; }
int int
get_nb_output_arguments() get_nb_output_arguments()
{ {
return nb_output_arguments; return nb_output_arguments;
}; }
int int
get_nb_input_arguments() get_nb_input_arguments()
{ {
return nb_input_arguments; return nb_input_arguments;
}; }
int int
get_indx() get_indx()
{ {
return indx; return indx;
}; }
void void
set_arg_func_name(string arg_arg_func_name) set_arg_func_name(string arg_arg_func_name)
{ {
arg_func_name = arg_arg_func_name; arg_func_name = move(arg_arg_func_name);
}; }
string string
get_arg_func_name() get_arg_func_name()
{ {
return arg_func_name; return arg_func_name;
}; }
void void
set_nb_add_input_arguments(int arg_add_input_arguments) set_nb_add_input_arguments(int arg_add_input_arguments)
{ {
add_input_arguments = arg_add_input_arguments; add_input_arguments = arg_add_input_arguments;
}; }
int int
get_nb_add_input_arguments() get_nb_add_input_arguments()
{ {
return add_input_arguments; return add_input_arguments;
}; }
void void
set_row(int arg_row) set_row(int arg_row)
{ {
row = arg_row; row = arg_row;
}; }
int int
get_row() get_row()
{ {
...@@ -836,12 +535,12 @@ public: ...@@ -836,12 +535,12 @@ public:
set_col(int arg_col) set_col(int arg_col)
{ {
col = arg_col; col = arg_col;
}; }
int int
get_col() get_col()
{ {
return col; return col;
}; }
ExternalFunctionCallType ExternalFunctionCallType
get_call_type() get_call_type()
{ {
...@@ -849,38 +548,40 @@ public: ...@@ -849,38 +548,40 @@ public:
} }
}; };
class FNUMEXPR_ final : public BytecodeInstruction class FNUMEXPR final : public Instruction
{ {
private: private:
ExpressionType expression_type; ExpressionType expression_type;
int equation; // Equation number (non-block-specific) (or temporary term number for ExpressionType::TemporaryTerm) int equation; // Equation number (non-block-specific) (or temporary term number for
// ExpressionType::TemporaryTerm)
int dvariable1; // For derivatives, type-specific ID of the derivation variable int dvariable1; // For derivatives, type-specific ID of the derivation variable
int lag1; // For derivatives, lead/lag of the derivation variable int lag1; // For derivatives, lead/lag of the derivation variable
public: public:
FNUMEXPR_(const ExpressionType expression_type_arg, int equation_arg) : FNUMEXPR(const ExpressionType expression_type_arg, int equation_arg) :
BytecodeInstruction{Tags::FNUMEXPR}, Instruction {Tag::FNUMEXPR},
expression_type {expression_type_arg}, expression_type {expression_type_arg},
equation {equation_arg}, equation {equation_arg},
dvariable1 {0}, dvariable1 {0},
lag1 {0} lag1 {0}
{ {
}; }
FNUMEXPR_(const ExpressionType expression_type_arg, int equation_arg, int dvariable1_arg) : FNUMEXPR(const ExpressionType expression_type_arg, int equation_arg, int dvariable1_arg) :
BytecodeInstruction{Tags::FNUMEXPR}, Instruction {Tag::FNUMEXPR},
expression_type {expression_type_arg}, expression_type {expression_type_arg},
equation {equation_arg}, equation {equation_arg},
dvariable1 {dvariable1_arg}, dvariable1 {dvariable1_arg},
lag1 {0} lag1 {0}
{ {
}; }
FNUMEXPR_(const ExpressionType expression_type_arg, int equation_arg, int dvariable1_arg, int lag1_arg) : FNUMEXPR(const ExpressionType expression_type_arg, int equation_arg, int dvariable1_arg,
BytecodeInstruction{Tags::FNUMEXPR}, int lag1_arg) :
Instruction {Tag::FNUMEXPR},
expression_type {expression_type_arg}, expression_type {expression_type_arg},
equation {equation_arg}, equation {equation_arg},
dvariable1 {dvariable1_arg}, dvariable1 {dvariable1_arg},
lag1 {lag1_arg} lag1 {lag1_arg}
{ {
}; }
ExpressionType ExpressionType
get_expression_type() get_expression_type()
{ {
...@@ -890,49 +591,51 @@ public: ...@@ -890,49 +591,51 @@ public:
get_equation() get_equation()
{ {
return equation; return equation;
}; }
int int
get_dvariable1() get_dvariable1()
{ {
return dvariable1; return dvariable1;
}; }
int int
get_lag1() get_lag1()
{ {
return lag1; return lag1;
}; }
}; };
class FBEGINBLOCK_ final : public BytecodeInstruction class FBEGINBLOCK final : public Instruction
{ {
template<typename B> template<IsInstruction B>
friend BytecodeWriter &operator<<(BytecodeWriter &code_file, const B &instr); friend Writer& operator<<(Writer& code_file, const B& instr);
private: private:
int size {0}; int size {0};
BlockSimulationType type; BlockSimulationType type;
vector<int> variable; vector<int> variables;
vector<int> equation; vector<int> equations;
vector<int> exogenous; vector<int> exogenous;
vector<int> det_exogenous; vector<int> det_exogenous;
bool is_linear {false}; bool is_linear {false};
vector<Block_contain_type> Block_Contain_;
int u_count_int {0}; int u_count_int {0};
int nb_col_jacob {0}; int nb_col_jacob {0};
int det_exo_size, exo_size; int det_exo_size, exo_size;
public: public:
/* Constructor when derivatives w.r.t. exogenous are present (only makes /* Constructor when derivatives w.r.t. exogenous are present (only makes
sense when there is no block-decomposition, since there is no provision for sense when there is no block-decomposition, since there is no provision for
derivatives w.r.t. endogenous not belonging to the block) */ derivatives w.r.t. endogenous not belonging to the block) */
FBEGINBLOCK_(int size_arg, BlockSimulationType type_arg, int first_element, int block_size, FBEGINBLOCK(int size_arg, BlockSimulationType type_arg, int first_element, int block_size,
const vector<int> &variable_arg, const vector<int> &equation_arg, const vector<int>& variables_arg, const vector<int>& equations_arg,
bool is_linear_arg, int u_count_int_arg, int nb_col_jacob_arg, bool is_linear_arg, int u_count_int_arg, int nb_col_jacob_arg, int det_exo_size_arg,
int det_exo_size_arg, int exo_size_arg, int exo_size_arg, vector<int> det_exogenous_arg, vector<int> exogenous_arg) :
vector<int> det_exogenous_arg, vector<int> exogenous_arg) : Instruction {Tag::FBEGINBLOCK},
BytecodeInstruction{Tags::FBEGINBLOCK},
size {size_arg}, size {size_arg},
type {type_arg}, type {type_arg},
variable{variable_arg.begin()+first_element, variable_arg.begin()+(first_element+block_size)}, variables {variables_arg.begin() + first_element,
equation{equation_arg.begin()+first_element, equation_arg.begin()+(first_element+block_size)}, variables_arg.begin() + (first_element + block_size)},
equations {equations_arg.begin() + first_element,
equations_arg.begin() + (first_element + block_size)},
exogenous {move(exogenous_arg)}, exogenous {move(exogenous_arg)},
det_exogenous {move(det_exogenous_arg)}, det_exogenous {move(det_exogenous_arg)},
is_linear {is_linear_arg}, is_linear {is_linear_arg},
...@@ -943,14 +646,16 @@ public: ...@@ -943,14 +646,16 @@ public:
{ {
} }
// Constructor when derivatives w.r.t. exogenous are absent // Constructor when derivatives w.r.t. exogenous are absent
FBEGINBLOCK_(int size_arg, BlockSimulationType type_arg, int first_element, int block_size, FBEGINBLOCK(int size_arg, BlockSimulationType type_arg, int first_element, int block_size,
const vector<int> &variable_arg, const vector<int> &equation_arg, const vector<int>& variables_arg, const vector<int>& equations_arg,
bool is_linear_arg, int u_count_int_arg, int nb_col_jacob_arg) : bool is_linear_arg, int u_count_int_arg, int nb_col_jacob_arg) :
BytecodeInstruction{Tags::FBEGINBLOCK}, Instruction {Tag::FBEGINBLOCK},
size {size_arg}, size {size_arg},
type {type_arg}, type {type_arg},
variable{variable_arg.begin()+first_element, variable_arg.begin()+(first_element+block_size)}, variables {variables_arg.begin() + first_element,
equation{equation_arg.begin()+first_element, equation_arg.begin()+(first_element+block_size)}, variables_arg.begin() + (first_element + block_size)},
equations {equations_arg.begin() + first_element,
equations_arg.begin() + (first_element + block_size)},
is_linear {is_linear_arg}, is_linear {is_linear_arg},
u_count_int {u_count_int_arg}, u_count_int {u_count_int_arg},
nb_col_jacob {nb_col_jacob_arg}, nb_col_jacob {nb_col_jacob_arg},
...@@ -960,25 +665,23 @@ public: ...@@ -960,25 +665,23 @@ public:
} }
/* Deserializing constructor. /* Deserializing constructor.
Updates the code pointer to point beyond the bytes read. */ Updates the code pointer to point beyond the bytes read. */
FBEGINBLOCK_(char *&code) : FBEGINBLOCK(char*& code) : Instruction {Tag::FBEGINBLOCK}
BytecodeInstruction{Tags::FBEGINBLOCK}
{ {
code += sizeof(op_code); code += sizeof(tag);
auto read_member = [&code](auto &member) auto read_member = [&code](auto& member) {
{
member = *reinterpret_cast<add_pointer_t<decltype(member)>>(code); member = *reinterpret_cast<add_pointer_t<decltype(member)>>(code);
code += sizeof member; code += sizeof member;
}; };
read_member(size); read_member(size);
read_member(type); read_member(type);
variables.resize(size);
equations.resize(size);
for (int i {0}; i < size; i++) for (int i {0}; i < size; i++)
{ {
Block_contain_type bc; read_member(variables[i]);
read_member(bc.Variable); read_member(equations[i]);
read_member(bc.Equation);
Block_Contain_.push_back(move(bc));
} }
if (type == BlockSimulationType::solveTwoBoundariesSimple if (type == BlockSimulationType::solveTwoBoundariesSimple
|| type == BlockSimulationType::solveTwoBoundariesComplete || type == BlockSimulationType::solveTwoBoundariesComplete
...@@ -1010,46 +713,46 @@ public: ...@@ -1010,46 +713,46 @@ public:
get_size() get_size()
{ {
return size; return size;
}; }
BlockSimulationType BlockSimulationType
get_type() get_type()
{ {
return type; return type;
}; }
bool bool
get_is_linear() get_is_linear()
{ {
return is_linear; return is_linear;
}; }
int int
get_u_count_int() get_u_count_int()
{ {
return u_count_int; return u_count_int;
}; }
vector<Block_contain_type> vector<int>
get_Block_Contain() get_variables()
{ {
return Block_Contain_; return variables;
}; }
vector<int>
get_equations()
{
return equations;
}
int int
get_nb_col_jacob() get_nb_col_jacob()
{ {
return nb_col_jacob; return nb_col_jacob;
}; }
int int
get_exo_size() get_exo_size()
{ {
return exo_size; return exo_size;
}; }
int int
get_det_exo_size() get_det_exo_size()
{ {
return det_exo_size; return det_exo_size;
};
vector<int>
get_endogenous()
{
return variable;
} }
vector<int> vector<int>
get_exogenous() get_exogenous()
...@@ -1059,15 +762,17 @@ public: ...@@ -1059,15 +762,17 @@ public:
}; };
// Superclass of std::ofstream for writing a sequence of bytecode instructions // Superclass of std::ofstream for writing a sequence of bytecode instructions
class BytecodeWriter : private ofstream class Writer : private ofstream
{ {
template<typename B> template<IsInstruction B>
friend BytecodeWriter &operator<<(BytecodeWriter &code_file, const B &instr); friend Writer& operator<<(Writer& code_file, const B& instr);
private: private:
// Stores the positions of all instructions in the byte stream // Stores the positions of all instructions in the byte stream
vector<pos_type> instructions_positions; vector<pos_type> instructions_positions;
public: public:
BytecodeWriter(const filesystem::path &filename); Writer(const filesystem::path& filename);
// Returns the number of the next instruction to be written // Returns the number of the next instruction to be written
int int
getInstructionCounter() const getInstructionCounter() const
...@@ -1077,9 +782,8 @@ public: ...@@ -1077,9 +782,8 @@ public:
/* Overwrites an existing instruction, given its number. /* Overwrites an existing instruction, given its number.
It is the responsibility of the caller to ensure that the new instruction It is the responsibility of the caller to ensure that the new instruction
occupies exactly as many bytes as the former one. */ occupies exactly as many bytes as the former one. */
template<typename B>
void void
overwriteInstruction(int instruction_number, const B &new_instruction) overwriteInstruction(int instruction_number, const IsInstruction auto& new_instruction)
{ {
seekp(instructions_positions.at(instruction_number)); seekp(instructions_positions.at(instruction_number));
*this << new_instruction; *this << new_instruction;
...@@ -1090,9 +794,9 @@ public: ...@@ -1090,9 +794,9 @@ public:
// Overloads of operator<< for writing bytecode instructions // Overloads of operator<< for writing bytecode instructions
template<typename B> template<IsInstruction B>
BytecodeWriter & Writer&
operator<<(BytecodeWriter &code_file, const B &instr) operator<<(Writer& code_file, const B& instr)
{ {
code_file.instructions_positions.push_back(code_file.tellp()); code_file.instructions_positions.push_back(code_file.tellp());
code_file.write(reinterpret_cast<const char*>(&instr), sizeof(B)); code_file.write(reinterpret_cast<const char*>(&instr), sizeof(B));
...@@ -1100,9 +804,11 @@ operator<<(BytecodeWriter &code_file, const B &instr) ...@@ -1100,9 +804,11 @@ operator<<(BytecodeWriter &code_file, const B &instr)
} }
template<> template<>
BytecodeWriter &operator<<(BytecodeWriter &code_file, const FCALL_ &instr); Writer& operator<<(Writer& code_file, const FCALL& instr);
template<> template<>
BytecodeWriter &operator<<(BytecodeWriter &code_file, const FBEGINBLOCK_ &instr); Writer& operator<<(Writer& code_file, const FBEGINBLOCK& instr);
}
#endif // _BYTECODE_HH #endif
/* /*
* Copyright © 2007-2022 Dynare Team * Copyright © 2007-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -17,24 +17,30 @@ ...@@ -17,24 +17,30 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef _COMMON_ENUMS_HH #ifndef COMMON_ENUMS_HH
#define _COMMON_ENUMS_HH #define COMMON_ENUMS_HH
//! Enumeration of possible symbol types //! Enumeration of possible symbol types
/*! Warning: do not to change existing values for 0 to 4: the values matter for homotopy_setup command */ /*! Warning: do not to change existing values for 0 to 4: the values matter for homotopy_setup
* command */
enum class SymbolType enum class SymbolType
{ {
endogenous = 0, //!< Endogenous endogenous = 0, // Endogenous (non-heterogeneous)
exogenous = 1, //!< Exogenous exogenous = 1, // Exogenous (non-heterogeneous)
exogenousDet = 2, //!< Exogenous deterministic exogenousDet = 2, // Exogenous deterministic (non-heterogeneous)
parameter = 4, //!< Parameter parameter = 4, // Parameter (non-heterogeneous)
modelLocalVariable = 10, //!< Local variable whose scope is model (pound expression) heterogeneousEndogenous = 5, // Endogenous that is heterogeneous across some dimension
modFileLocalVariable = 11, //!< Local variable whose scope is mod file (model excluded) heterogeneousExogenous = 6, // Exogenous that is heterogeneous across some dimension
externalFunction = 12, //!< External (user-defined) function heterogeneousParameter = 7, // Parameter that is heterogeneous across some dimension
trend = 13, //!< Trend variable modelLocalVariable = 10, // Local variable whose scope is model (pound expression)
statementDeclaredVariable = 14, //!< Local variable assigned within a Statement (see subsample statement for example) modFileLocalVariable = 11, // Local variable whose scope is mod file (model excluded)
externalFunction = 12, // External (user-defined) function
trend = 13, // Trend variable
statementDeclaredVariable
= 14, //!< Local variable assigned within a Statement (see subsample statement for example)
logTrend = 15, //!< Log-trend variable logTrend = 15, //!< Log-trend variable
unusedEndogenous = 16, //!< Type to mark unused endogenous variables when `nostrict` option is passed unusedEndogenous
= 16, //!< Type to mark unused endogenous variables when `nostrict` option is passed
// Value 17 is unused for the time being (but could be reused) // Value 17 is unused for the time being (but could be reused)
...@@ -42,6 +48,13 @@ enum class SymbolType ...@@ -42,6 +48,13 @@ enum class SymbolType
excludedVariable = 19 //!< Variable excluded via model_remove/var_remove/include_eqs/exclude_eqs excludedVariable = 19 //!< Variable excluded via model_remove/var_remove/include_eqs/exclude_eqs
}; };
constexpr bool
isHeterogeneous(SymbolType type)
{
return type == SymbolType::heterogeneousEndogenous || type == SymbolType::heterogeneousExogenous
|| type == SymbolType::heterogeneousParameter;
}
enum class UnaryOpcode enum class UnaryOpcode
{ {
uminus, uminus,
...@@ -66,12 +79,14 @@ enum class UnaryOpcode ...@@ -66,12 +79,14 @@ enum class UnaryOpcode
sign, sign,
steadyState, steadyState,
steadyStateParamDeriv, // for the derivative of the STEADY_STATE operator w.r.t. to a parameter steadyStateParamDeriv, // for the derivative of the STEADY_STATE operator w.r.t. to a parameter
steadyStateParam2ndDeriv, // for the 2nd derivative of the STEADY_STATE operator w.r.t. to a parameter steadyStateParam2ndDeriv, // for the 2nd derivative of the STEADY_STATE operator w.r.t. to a
// parameter
expectation, expectation,
erf, erf,
erfc, erfc,
diff, diff,
adl adl,
sum
}; };
enum class BinaryOpcode enum class BinaryOpcode
...@@ -119,8 +134,10 @@ enum class PriorDistributions ...@@ -119,8 +134,10 @@ enum class PriorDistributions
enum class EquationType enum class EquationType
{ {
evaluate, //!< Simple evaluation, normalized variable on left-hand side (written as such by the user) evaluate, //!< Simple evaluation, normalized variable on left-hand side (written as such by the
evaluateRenormalized, //!< Simple evaluation, normalized variable on left-hand side (normalization computed by the preprocessor) //!< user)
evaluateRenormalized, //!< Simple evaluation, normalized variable on left-hand side (normalization
//!< computed by the preprocessor)
solve //!< No simple evaluation of the equation, it has to be solved solve //!< No simple evaluation of the equation, it has to be solved
}; };
...@@ -133,7 +150,8 @@ enum class BlockSimulationType ...@@ -133,7 +150,8 @@ enum class BlockSimulationType
solveTwoBoundariesSimple, //!< Block of one equation, Newton solver needed, forward and backward solveTwoBoundariesSimple, //!< Block of one equation, Newton solver needed, forward and backward
solveForwardComplete, //!< Block of several equations, Newton solver needed, forward solveForwardComplete, //!< Block of several equations, Newton solver needed, forward
solveBackwardComplete, //!< Block of several equations, Newton solver needed, backward solveBackwardComplete, //!< Block of several equations, Newton solver needed, backward
solveTwoBoundariesComplete //!< Block of several equations, Newton solver needed, forward and backwar solveTwoBoundariesComplete //!< Block of several equations, Newton solver needed, forward and
//!< backwar
}; };
enum class PacTargetKind enum class PacTargetKind
...@@ -144,4 +162,4 @@ enum class PacTargetKind ...@@ -144,4 +162,4 @@ enum class PacTargetKind
dd dd
}; };
#endif // _COMMON_ENUMS_HH #endif
/* /*
* Copyright © 2003-2023 Dynare Team * Copyright © 2003-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -17,27 +17,27 @@ ...@@ -17,27 +17,27 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <algorithm>
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
#include <sstream>
#include <algorithm>
#include <iterator> #include <iterator>
#include <sstream>
using namespace std; using namespace std;
#include "ComputingTasks.hh" #include "ComputingTasks.hh"
#include "Statement.hh"
#include "ParsingDriver.hh" #include "ParsingDriver.hh"
#include "Statement.hh"
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wold-style-cast"
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/tokenizer.hpp> #include <boost/tokenizer.hpp>
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#include <utility>
#include <algorithm> #include <algorithm>
#include <utility>
SteadyStatement::SteadyStatement(OptionsList options_list_arg) : SteadyStatement::SteadyStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)} options_list {move(options_list_arg)}
...@@ -71,8 +71,7 @@ SteadyStatement::writeJsonOutput(ostream &output) const ...@@ -71,8 +71,7 @@ SteadyStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
CheckStatement::CheckStatement(OptionsList options_list_arg) : CheckStatement::CheckStatement(OptionsList options_list_arg) : options_list {move(options_list_arg)}
options_list{move(options_list_arg)}
{ {
} }
...@@ -128,8 +127,7 @@ ModelInfoStatement::writeJsonOutput(ostream &output) const ...@@ -128,8 +127,7 @@ ModelInfoStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
SimulStatement::SimulStatement(OptionsList options_list_arg) : SimulStatement::SimulStatement(OptionsList options_list_arg) : options_list {move(options_list_arg)}
options_list{move(options_list_arg)}
{ {
} }
...@@ -155,8 +153,8 @@ SimulStatement::writeOutput(ostream &output, [[maybe_unused]] const string &base ...@@ -155,8 +153,8 @@ SimulStatement::writeOutput(ostream &output, [[maybe_unused]] const string &base
options_list_new.erase("datafile"); options_list_new.erase("datafile");
} }
options_list_new.writeOutput(output); options_list_new.writeOutput(output);
output << "perfect_foresight_setup;" << endl output << "oo_ = perfect_foresight_setup(M_, options_, oo_);" << endl
<< "perfect_foresight_solver;" << endl; << "[oo_, Simulated_time_series] = perfect_foresight_solver(M_, options_, oo_);" << endl;
} }
void void
...@@ -177,7 +175,8 @@ PerfectForesightSetupStatement::PerfectForesightSetupStatement(OptionsList optio ...@@ -177,7 +175,8 @@ PerfectForesightSetupStatement::PerfectForesightSetupStatement(OptionsList optio
} }
void void
PerfectForesightSetupStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename, PerfectForesightSetupStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
auto options_list_new = options_list; // Need a copy, because of const auto options_list_new = options_list; // Need a copy, because of const
...@@ -190,7 +189,7 @@ PerfectForesightSetupStatement::writeOutput(ostream &output, [[maybe_unused]] co ...@@ -190,7 +189,7 @@ PerfectForesightSetupStatement::writeOutput(ostream &output, [[maybe_unused]] co
options_list_new.erase("datafile"); options_list_new.erase("datafile");
} }
options_list_new.writeOutput(output); options_list_new.writeOutput(output);
output << "perfect_foresight_setup;" << endl; output << "oo_ = perfect_foresight_setup(M_, options_, oo_);" << endl;
} }
void void
...@@ -218,11 +217,12 @@ PerfectForesightSolverStatement::checkPass(ModFileStructure &mod_file_struct, ...@@ -218,11 +217,12 @@ PerfectForesightSolverStatement::checkPass(ModFileStructure &mod_file_struct,
} }
void void
PerfectForesightSolverStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename, PerfectForesightSolverStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output); options_list.writeOutput(output);
output << "perfect_foresight_solver;" << endl; output << "[oo_, Simulated_time_series] = perfect_foresight_solver(M_, options_, oo_);" << endl;
} }
void void
...@@ -237,18 +237,19 @@ PerfectForesightSolverStatement::writeJsonOutput(ostream &output) const ...@@ -237,18 +237,19 @@ PerfectForesightSolverStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
PerfectForesightWithExpectationErrorsSetupStatement::PerfectForesightWithExpectationErrorsSetupStatement(OptionsList options_list_arg) : PerfectForesightWithExpectationErrorsSetupStatement::
PerfectForesightWithExpectationErrorsSetupStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)} options_list {move(options_list_arg)}
{ {
} }
void void
PerfectForesightWithExpectationErrorsSetupStatement::writeOutput(ostream &output, PerfectForesightWithExpectationErrorsSetupStatement::writeOutput(
[[maybe_unused]] const string &basename, ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output); options_list.writeOutput(output);
output << "perfect_foresight_with_expectation_errors_setup;" << endl; output << "oo_ = perfect_foresight_with_expectation_errors_setup(M_, options_, oo_);" << endl;
} }
void void
...@@ -263,25 +264,28 @@ PerfectForesightWithExpectationErrorsSetupStatement::writeJsonOutput(ostream &ou ...@@ -263,25 +264,28 @@ PerfectForesightWithExpectationErrorsSetupStatement::writeJsonOutput(ostream &ou
output << "}"; output << "}";
} }
PerfectForesightWithExpectationErrorsSolverStatement::PerfectForesightWithExpectationErrorsSolverStatement(OptionsList options_list_arg) : PerfectForesightWithExpectationErrorsSolverStatement::
PerfectForesightWithExpectationErrorsSolverStatement(OptionsList options_list_arg) :
options_list(move(options_list_arg)) options_list(move(options_list_arg))
{ {
} }
void void
PerfectForesightWithExpectationErrorsSolverStatement::checkPass(ModFileStructure &mod_file_struct, PerfectForesightWithExpectationErrorsSolverStatement::checkPass(
[[maybe_unused]] WarningConsolidation &warnings) ModFileStructure& mod_file_struct, [[maybe_unused]] WarningConsolidation& warnings)
{ {
mod_file_struct.perfect_foresight_with_expectation_errors_solver_present = true; mod_file_struct.perfect_foresight_with_expectation_errors_solver_present = true;
} }
void void
PerfectForesightWithExpectationErrorsSolverStatement::writeOutput(ostream &output, PerfectForesightWithExpectationErrorsSolverStatement::writeOutput(
[[maybe_unused]] const string &basename, ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output); options_list.writeOutput(output);
output << "perfect_foresight_with_expectation_errors_solver;" << endl; output << "[oo_, Simulated_time_series] = perfect_foresight_with_expectation_errors_solver(M_, "
"options_, oo_);"
<< endl;
} }
void void
...@@ -298,8 +302,7 @@ PerfectForesightWithExpectationErrorsSolverStatement::writeJsonOutput(ostream &o ...@@ -298,8 +302,7 @@ PerfectForesightWithExpectationErrorsSolverStatement::writeJsonOutput(ostream &o
PriorPosteriorFunctionStatement::PriorPosteriorFunctionStatement(const bool prior_func_arg, PriorPosteriorFunctionStatement::PriorPosteriorFunctionStatement(const bool prior_func_arg,
OptionsList options_list_arg) : OptionsList options_list_arg) :
prior_func{prior_func_arg}, prior_func {prior_func_arg}, options_list {move(options_list_arg)}
options_list{move(options_list_arg)}
{ {
} }
...@@ -307,17 +310,18 @@ void ...@@ -307,17 +310,18 @@ void
PriorPosteriorFunctionStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct, PriorPosteriorFunctionStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings) [[maybe_unused]] WarningConsolidation& warnings)
{ {
if (auto opt = options_list.get_if<OptionsList::StringVal>("function"); if (auto opt = options_list.get_if<OptionsList::StringVal>("function"); !opt || opt->empty())
!opt || opt->empty())
{ {
cerr << "ERROR: both the 'prior_function' and 'posterior_function' commands require the 'function' option" cerr << "ERROR: both the 'prior_function' and 'posterior_function' commands require the "
"'function' option"
<< endl; << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
void void
PriorPosteriorFunctionStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename, PriorPosteriorFunctionStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output); options_list.writeOutput(output);
...@@ -506,92 +510,6 @@ RamseyModelStatement::writeJsonOutput(ostream &output) const ...@@ -506,92 +510,6 @@ RamseyModelStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
RamseyConstraintsStatement::RamseyConstraintsStatement(const SymbolTable &symbol_table_arg, constraints_t constraints_arg) :
symbol_table{symbol_table_arg},
constraints{move(constraints_arg)}
{
}
void
RamseyConstraintsStatement::checkPass(ModFileStructure &mod_file_struct,
[[maybe_unused]] WarningConsolidation &warnings)
{
mod_file_struct.ramsey_constraints_present = true;
}
void
RamseyConstraintsStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "M_.ramsey_model_constraints = {" << endl;
for (bool printed_something{false};
const auto &it : constraints)
{
if (exchange(printed_something, true))
output << ", ";
output << "{" << it.endo + 1 << ", '";
switch (it.code)
{
case BinaryOpcode::less:
output << '<';
break;
case BinaryOpcode::greater:
output << '>';
break;
case BinaryOpcode::lessEqual:
output << "<=";
break;
case BinaryOpcode::greaterEqual:
output << ">=";
break;
default:
cerr << "Ramsey constraints: this shouldn't happen." << endl;
exit(EXIT_FAILURE);
}
output << "', '";
it.expression->writeOutput(output);
output << "'}" << endl;
}
output << "};" << endl;
}
void
RamseyConstraintsStatement::writeJsonOutput(ostream &output) const
{
output << R"({"statementName": "ramsey_constraints")"
<< R"(, "ramsey_model_constraints": [)" << endl;
for (bool printed_something{false};
const auto &it : constraints)
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"constraint": ")" << symbol_table.getName(it.endo) << " ";
switch (it.code)
{
case BinaryOpcode::less:
output << '<';
break;
case BinaryOpcode::greater:
output << '>';
break;
case BinaryOpcode::lessEqual:
output << "<=";
break;
case BinaryOpcode::greaterEqual:
output << ">=";
break;
default:
cerr << "Ramsey constraints: this shouldn't happen." << endl;
exit(EXIT_FAILURE);
}
output << " ";
it.expression->writeJsonOutput(output, {}, {});
output << R"("})" << endl;
}
output << "]" << endl;
output << "}";
}
RamseyPolicyStatement::RamseyPolicyStatement(SymbolList symbol_list_arg, RamseyPolicyStatement::RamseyPolicyStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
...@@ -714,7 +632,8 @@ DiscretionaryPolicyStatement::DiscretionaryPolicyStatement(SymbolList symbol_lis ...@@ -714,7 +632,8 @@ DiscretionaryPolicyStatement::DiscretionaryPolicyStatement(SymbolList symbol_lis
} }
void void
DiscretionaryPolicyStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) DiscretionaryPolicyStatement::checkPass(ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{ {
mod_file_struct.discretionary_policy_present = true; mod_file_struct.discretionary_policy_present = true;
...@@ -775,7 +694,8 @@ DiscretionaryPolicyStatement::writeOutput(ostream &output, [[maybe_unused]] cons ...@@ -775,7 +694,8 @@ DiscretionaryPolicyStatement::writeOutput(ostream &output, [[maybe_unused]] cons
options_list.writeOutput(output); options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output); symbol_list.writeOutput("var_list_", output);
output << "[info, oo_, options_, M_] = discretionary_policy(M_, options_, oo_, var_list_);" << endl; output << "[info, oo_, options_, M_] = discretionary_policy(M_, options_, oo_, var_list_);"
<< endl;
} }
void void
...@@ -830,7 +750,9 @@ OccbinSolverStatement::writeOutput(ostream &output, [[maybe_unused]] const strin ...@@ -830,7 +750,9 @@ OccbinSolverStatement::writeOutput(ostream &output, [[maybe_unused]] const strin
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output, "options_.occbin"); options_list.writeOutput(output, "options_.occbin");
output << "[oo_.dr, oo_.occbin.simul]= occbin.solver(M_, options_, oo_.dr , oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state);" << endl; output << "[oo_.dr, oo_.occbin.simul]= occbin.solver(M_, options_, oo_.dr , oo_.steady_state, "
"oo_.exo_steady_state, oo_.exo_det_steady_state);"
<< endl;
} }
void void
...@@ -872,8 +794,7 @@ OccbinWriteRegimesStatement::writeJsonOutput(ostream &output) const ...@@ -872,8 +794,7 @@ OccbinWriteRegimesStatement::writeJsonOutput(ostream &output) const
OccbinGraphStatement::OccbinGraphStatement(SymbolList symbol_list_arg, OccbinGraphStatement::OccbinGraphStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg) : OptionsList options_list_arg) :
symbol_list{move(symbol_list_arg)}, symbol_list {move(symbol_list_arg)}, options_list {move(options_list_arg)}
options_list{move(options_list_arg)}
{ {
} }
...@@ -904,8 +825,7 @@ OccbinGraphStatement::writeJsonOutput(ostream &output) const ...@@ -904,8 +825,7 @@ OccbinGraphStatement::writeJsonOutput(ostream &output) const
} }
EstimationStatement::EstimationStatement(const SymbolTable& symbol_table_arg, EstimationStatement::EstimationStatement(const SymbolTable& symbol_table_arg,
SymbolList symbol_list_arg, SymbolList symbol_list_arg, OptionsList options_list_arg) :
OptionsList options_list_arg) :
symbol_table {symbol_table_arg}, symbol_table {symbol_table_arg},
symbol_list {move(symbol_list_arg)}, symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)} options_list {move(options_list_arg)}
...@@ -939,8 +859,7 @@ EstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli ...@@ -939,8 +859,7 @@ EstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli
mod_file_struct.estimation_analytic_derivation = true; mod_file_struct.estimation_analytic_derivation = true;
if (options_list.contains("dsge_var")) if (options_list.contains("dsge_var"))
options_list.visit("dsge_var", [&]<class T>(const T &v) options_list.visit("dsge_var", [&]<class T>(const T& v) {
{
if constexpr (is_same_v<T, OptionsList::StringVal>) if constexpr (is_same_v<T, OptionsList::StringVal>)
mod_file_struct.dsge_var_estimated = true; mod_file_struct.dsge_var_estimated = true;
else if constexpr (is_same_v<T, OptionsList::NumVal>) else if constexpr (is_same_v<T, OptionsList::NumVal>)
...@@ -948,37 +867,36 @@ EstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli ...@@ -948,37 +867,36 @@ EstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli
}); });
// Fill in mod_file_struct.bayesian_irf_present // Fill in mod_file_struct.bayesian_irf_present
if (auto opt = options_list.get_if<OptionsList::NumVal>("bayesian_irf"); if (auto opt = options_list.get_if<OptionsList::NumVal>("bayesian_irf"); opt && *opt == "true")
opt && *opt == "true")
mod_file_struct.bayesian_irf_present = true; mod_file_struct.bayesian_irf_present = true;
if (options_list.contains("dsge_varlag")) if (options_list.contains("dsge_varlag"))
if (mod_file_struct.dsge_var_calibrated.empty() if (mod_file_struct.dsge_var_calibrated.empty() && !mod_file_struct.dsge_var_estimated)
&& !mod_file_struct.dsge_var_estimated)
{ {
cerr << "ERROR: The estimation statement requires a dsge_var option to be passed " cerr << "ERROR: The estimation statement requires a dsge_var option to be passed "
<< "if the dsge_varlag option is passed." << endl; << "if the dsge_varlag option is passed." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!mod_file_struct.dsge_var_calibrated.empty() if (!mod_file_struct.dsge_var_calibrated.empty() && mod_file_struct.dsge_var_estimated)
&& mod_file_struct.dsge_var_estimated)
{ {
cerr << "ERROR: An estimation statement cannot take more than one dsge_var option." << endl; cerr << "ERROR: An estimation statement cannot take more than one dsge_var option." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!options_list.contains("datafile") if (!options_list.contains("datafile") && !mod_file_struct.estimation_data_statement_present)
&& !mod_file_struct.estimation_data_statement_present)
{ {
cerr << "ERROR: The estimation statement requires a data file to be supplied via the datafile option." << endl; cerr << "ERROR: The estimation statement requires a data file to be supplied via the "
"datafile option."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (options_list.contains("mode_file") if (options_list.contains("mode_file") && mod_file_struct.estim_params_use_calib)
&& mod_file_struct.estim_params_use_calib)
{ {
cerr << "ERROR: The mode_file option of the estimation statement is incompatible with the use_calibration option of the estimated_params_init block." << endl; cerr << "ERROR: The mode_file option of the estimation statement is incompatible with the "
"use_calibration option of the estimated_params_init block."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -987,30 +905,33 @@ EstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli ...@@ -987,30 +905,33 @@ EstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli
{ {
if (options_list.contains("mh_jscale")) if (options_list.contains("mh_jscale"))
{ {
cerr << "ERROR: The mh_tune_jscale and mh_jscale options of the estimation statement are incompatible." << endl; cerr << "ERROR: The mh_tune_jscale and mh_jscale options of the estimation statement are "
"incompatible."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
else if (options_list.contains("mh_tune_jscale.guess")) else if (options_list.contains("mh_tune_jscale.guess"))
{ {
cerr << "ERROR: The option mh_tune_guess in estimation statement cannot be used without option mh_tune_jscale." << endl; cerr << "ERROR: The option mh_tune_guess in estimation statement cannot be used without "
"option mh_tune_jscale."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* Check that we are not trying to estimate a parameter appearing in the /* Check that we are not trying to estimate a parameter appearing in the
planner discount factor (see dynare#1173) */ planner discount factor (see dynare#1173) */
vector<int> estimated_params_in_planner_discount; vector<int> estimated_params_in_planner_discount;
set_intersection(mod_file_struct.estimated_parameters.begin(), ranges::set_intersection(mod_file_struct.estimated_parameters,
mod_file_struct.estimated_parameters.end(), mod_file_struct.parameters_in_planner_discount,
mod_file_struct.parameters_in_planner_discount.begin(),
mod_file_struct.parameters_in_planner_discount.end(),
back_inserter(estimated_params_in_planner_discount)); back_inserter(estimated_params_in_planner_discount));
if (!estimated_params_in_planner_discount.empty()) if (!estimated_params_in_planner_discount.empty())
{ {
cerr << "ERROR: It is not possible to estimate a parameter (" cerr << "ERROR: It is not possible to estimate a parameter ("
<< symbol_table.getName(estimated_params_in_planner_discount[0]) << symbol_table.getName(estimated_params_in_planner_discount[0])
<< ") that appears in the discount factor of the planner (i.e. in the 'planner_discount' option)." << endl; << ") that appears in the discount factor of the planner (i.e. in the "
"'planner_discount' option)."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -1032,11 +953,9 @@ EstimationStatement::writeOutput(ostream &output, [[maybe_unused]] const string ...@@ -1032,11 +953,9 @@ EstimationStatement::writeOutput(ostream &output, [[maybe_unused]] const string
options_list.writeOutput(output); options_list.writeOutput(output);
// Special treatment for order option and particle filter // Special treatment for order option and particle filter
if (auto opt = options_list.get_if<OptionsList::NumVal>("order"); if (auto opt = options_list.get_if<OptionsList::NumVal>("order"); !opt)
!opt)
output << "options_.order = 1;" << endl; output << "options_.order = 1;" << endl;
else if (int order {stoi(*opt)}; else if (int order {stoi(*opt)}; order >= 2)
order >= 2)
{ {
output << "options_.particle.status = true;" << endl; output << "options_.particle.status = true;" << endl;
if (order > 2) if (order > 2)
...@@ -1044,8 +963,7 @@ EstimationStatement::writeOutput(ostream &output, [[maybe_unused]] const string ...@@ -1044,8 +963,7 @@ EstimationStatement::writeOutput(ostream &output, [[maybe_unused]] const string
} }
// Do not check for the steady state in diffuse filter mode (#400) // Do not check for the steady state in diffuse filter mode (#400)
if (auto opt = options_list.get_if<OptionsList::NumVal>("diffuse_filter"); if (auto opt = options_list.get_if<OptionsList::NumVal>("diffuse_filter"); opt && *opt == "true")
opt && *opt == "true")
output << "options_.steadystate.nocheck = true;" << endl; output << "options_.steadystate.nocheck = true;" << endl;
symbol_list.writeOutput("var_list_", output); symbol_list.writeOutput("var_list_", output);
...@@ -1069,17 +987,16 @@ EstimationStatement::writeJsonOutput(ostream &output) const ...@@ -1069,17 +987,16 @@ EstimationStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
DynareSensitivityStatement::DynareSensitivityStatement(OptionsList options_list_arg) : SensitivityStatement::SensitivityStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)} options_list {move(options_list_arg)}
{ {
} }
void void
DynareSensitivityStatement::checkPass(ModFileStructure &mod_file_struct, SensitivityStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings) [[maybe_unused]] WarningConsolidation& warnings)
{ {
if (auto opt = options_list.get_if<OptionsList::NumVal>("identification"); if (auto opt = options_list.get_if<OptionsList::NumVal>("identification"); opt && *opt == "1")
opt && *opt == "1")
{ {
mod_file_struct.identification_present = true; mod_file_struct.identification_present = true;
// The following triggers 3rd order derivatives, see preprocessor#40 // The following triggers 3rd order derivatives, see preprocessor#40
...@@ -1089,7 +1006,7 @@ DynareSensitivityStatement::checkPass(ModFileStructure &mod_file_struct, ...@@ -1089,7 +1006,7 @@ DynareSensitivityStatement::checkPass(ModFileStructure &mod_file_struct,
} }
void void
DynareSensitivityStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename, SensitivityStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output, "options_gsa"); options_list.writeOutput(output, "options_gsa");
...@@ -1106,13 +1023,13 @@ DynareSensitivityStatement::writeOutput(ostream &output, [[maybe_unused]] const ...@@ -1106,13 +1023,13 @@ DynareSensitivityStatement::writeOutput(ostream &output, [[maybe_unused]] const
if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("graph_format")) if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("graph_format"))
opt->writeOutput("options_.graph_format", output); opt->writeOutput("options_.graph_format", output);
output << "dynare_sensitivity(options_gsa);" << endl; output << "gsa.run(M_,oo_,options_,bayestopt_,estim_params_,options_gsa);" << endl;
} }
void void
DynareSensitivityStatement::writeJsonOutput(ostream &output) const SensitivityStatement::writeJsonOutput(ostream& output) const
{ {
output << R"({"statementName": "dynare_sensitivity")"; output << R"({"statementName": "sensitivity")";
if (!options_list.empty()) if (!options_list.empty())
{ {
output << ", "; output << ", ";
...@@ -1121,10 +1038,8 @@ DynareSensitivityStatement::writeJsonOutput(ostream &output) const ...@@ -1121,10 +1038,8 @@ DynareSensitivityStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
RplotStatement::RplotStatement(SymbolList symbol_list_arg, RplotStatement::RplotStatement(SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg) :
const SymbolTable &symbol_table_arg) : symbol_list {move(symbol_list_arg)}, symbol_table {symbol_table_arg}
symbol_list{move(symbol_list_arg)},
symbol_table{symbol_table_arg}
{ {
} }
...@@ -1134,7 +1049,8 @@ RplotStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct, ...@@ -1134,7 +1049,8 @@ RplotStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct,
{ {
try try
{ {
symbol_list.checkPass(warnings, { SymbolType::endogenous, SymbolType::exogenous}, symbol_table); symbol_list.checkPass(warnings, {SymbolType::endogenous, SymbolType::exogenous},
symbol_table);
} }
catch (SymbolList::SymbolListException& e) catch (SymbolList::SymbolListException& e)
{ {
...@@ -1167,8 +1083,7 @@ void ...@@ -1167,8 +1083,7 @@ void
UnitRootVarsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename, UnitRootVarsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
output << "options_.diffuse_filter = 1;" << endl output << "options_.diffuse_filter = 1;" << endl << "options_.steadystate.nocheck = 1;" << endl;
<< "options_.steadystate.nocheck = 1;" << endl;
} }
void void
...@@ -1205,10 +1120,9 @@ DsampleStatement::writeJsonOutput(ostream &output) const ...@@ -1205,10 +1120,9 @@ DsampleStatement::writeJsonOutput(ostream &output) const
<< R"("value2": )" << val2 << "}"; << R"("value2": )" << val2 << "}";
} }
AbstractEstimatedParamsStatement::AbstractEstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg, AbstractEstimatedParamsStatement::AbstractEstimatedParamsStatement(
const SymbolTable &symbol_table_arg) : vector<EstimationParams> estim_params_list_arg, const SymbolTable& symbol_table_arg) :
estim_params_list{move(estim_params_list_arg)}, estim_params_list {move(estim_params_list_arg)}, symbol_table {symbol_table_arg}
symbol_table{symbol_table_arg}
{ {
} }
...@@ -1229,7 +1143,8 @@ AbstractEstimatedParamsStatement::commonCheckPass() const ...@@ -1229,7 +1143,8 @@ AbstractEstimatedParamsStatement::commonCheckPass() const
if (already_declared_corr.contains(x)) if (already_declared_corr.contains(x))
{ {
cerr << "ERROR: in `" << blockName() << "' block, the correlation between " << it.name << " and " << it.name2 << " is declared twice." << endl; cerr << "ERROR: in `" << blockName() << "' block, the correlation between " << it.name
<< " and " << it.name2 << " is declared twice." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else else
...@@ -1239,7 +1154,8 @@ AbstractEstimatedParamsStatement::commonCheckPass() const ...@@ -1239,7 +1154,8 @@ AbstractEstimatedParamsStatement::commonCheckPass() const
{ {
if (already_declared.contains(it.name)) if (already_declared.contains(it.name))
{ {
cerr << "ERROR: in `" << blockName() << "' block, the symbol " << it.name << " is declared twice." << endl; cerr << "ERROR: in `" << blockName() << "' block, the symbol " << it.name
<< " is declared twice." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else else
...@@ -1267,10 +1183,8 @@ AbstractEstimatedParamsStatement::commonCheckPass() const ...@@ -1267,10 +1183,8 @@ AbstractEstimatedParamsStatement::commonCheckPass() const
it.p4->collectVariables(SymbolType::parameter, used_params); it.p4->collectVariables(SymbolType::parameter, used_params);
it.jscale->collectVariables(SymbolType::parameter, used_params); it.jscale->collectVariables(SymbolType::parameter, used_params);
vector<int> intersect; vector<int> intersect;
set_intersection(declared_params.begin(), declared_params.end(), ranges::set_intersection(declared_params, used_params, back_inserter(intersect));
used_params.begin(), used_params.end(), if (!intersect.empty())
back_inserter(intersect));
if (intersect.size() > 0)
{ {
cerr << "ERROR: in `" << blockName() << "' block, the value of estimated parameter " cerr << "ERROR: in `" << blockName() << "' block, the value of estimated parameter "
<< symbol_table.getName(intersect[0]) << " is used in the declaration for "; << symbol_table.getName(intersect[0]) << " is used in the declaration for ";
...@@ -1307,10 +1221,11 @@ EstimatedParamsStatement::checkPass(ModFileStructure &mod_file_struct, ...@@ -1307,10 +1221,11 @@ EstimatedParamsStatement::checkPass(ModFileStructure &mod_file_struct,
if (it.prior == PriorDistributions::beta) if (it.prior == PriorDistributions::beta)
try try
{ {
if (it.mean->eval(eval_context_t()) == 0.5 if (it.mean->eval(eval_context_t()) == 0.5 && it.std->eval(eval_context_t()) == 0.5)
&& it.std->eval(eval_context_t()) == 0.5)
{ {
cerr << "ERROR: The prior density is not defined for the beta distribution when the mean = standard deviation = 0.5." << endl; cerr << "ERROR: The prior density is not defined for the beta distribution when "
"the mean = standard deviation = 0.5."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -1352,7 +1267,9 @@ EstimatedParamsStatement::writeOutput(ostream &output, [[maybe_unused]] const st ...@@ -1352,7 +1267,9 @@ EstimatedParamsStatement::writeOutput(ostream &output, [[maybe_unused]] const st
int tsid = symbol_table.getTypeSpecificID(it.name) + 1; int tsid = symbol_table.getTypeSpecificID(it.name) + 1;
int tsid2; int tsid2;
SymbolType symb_type = symbol_table.getType(it.name); SymbolType symb_type = symbol_table.getType(it.name);
string errmsg = " has been specified twice in two concatenated ''estimated_params'' blocks. Depending on your intention, you may want to use the ''overwrite'' option or an ''estimated_params_remove'' block."; string errmsg = " has been specified twice in two concatenated ''estimated_params'' blocks. "
"Depending on your intention, you may want to use the ''overwrite'' option "
"or an ''estimated_params_remove'' block.";
switch (it.type) switch (it.type)
{ {
...@@ -1364,7 +1281,8 @@ EstimatedParamsStatement::writeOutput(ostream &output, [[maybe_unused]] const st ...@@ -1364,7 +1281,8 @@ EstimatedParamsStatement::writeOutput(ostream &output, [[maybe_unused]] const st
<< "estim_params_.var_exo = [estim_params_.var_exo; "; << "estim_params_.var_exo = [estim_params_.var_exo; ";
else if (symb_type == SymbolType::endogenous) else if (symb_type == SymbolType::endogenous)
output << "if ~isempty(find(estim_params_.var_endo(:,1)==" << tsid << "))" << endl output << "if ~isempty(find(estim_params_.var_endo(:,1)==" << tsid << "))" << endl
<< " error('The standard deviation of the measurement error for " << it.name << errmsg << "')" << endl << " error('The standard deviation of the measurement error for " << it.name
<< errmsg << "')" << endl
<< "end" << endl << "end" << endl
<< "estim_params_.var_endo = [estim_params_.var_endo; "; << "estim_params_.var_endo = [estim_params_.var_endo; ";
output << tsid; output << tsid;
...@@ -1373,21 +1291,26 @@ EstimatedParamsStatement::writeOutput(ostream &output, [[maybe_unused]] const st ...@@ -1373,21 +1291,26 @@ EstimatedParamsStatement::writeOutput(ostream &output, [[maybe_unused]] const st
output << "if ~isempty(find(estim_params_.param_vals(:,1)==" << tsid << "))" << endl output << "if ~isempty(find(estim_params_.param_vals(:,1)==" << tsid << "))" << endl
<< " error('Parameter " << it.name << errmsg << "')" << endl << " error('Parameter " << it.name << errmsg << "')" << endl
<< "end" << endl << "end" << endl
<< "estim_params_.param_vals = [estim_params_.param_vals; " << "estim_params_.param_vals = [estim_params_.param_vals; " << tsid;
<< tsid;
break; break;
case 3: case 3:
tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1; tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1;
if (symb_type == SymbolType::exogenous) if (symb_type == SymbolType::exogenous)
output << "if ~isempty(find((estim_params_.corrx(:,1)==" << tsid << " & estim_params_.corrx(:,2)==" << tsid2 << ") | " output << "if ~isempty(find((estim_params_.corrx(:,1)==" << tsid
<< "(estim_params_.corrx(:,2)==" << tsid << " & estim_params_.corrx(:,1)==" << tsid2 << ")))" << endl << " & estim_params_.corrx(:,2)==" << tsid2 << ") | "
<< " error('The correlation between " << it.name << " and " << it.name2 << errmsg << "')" << endl << "(estim_params_.corrx(:,2)==" << tsid
<< " & estim_params_.corrx(:,1)==" << tsid2 << ")))" << endl
<< " error('The correlation between " << it.name << " and " << it.name2
<< errmsg << "')" << endl
<< "end" << endl << "end" << endl
<< "estim_params_.corrx = [estim_params_.corrx; "; << "estim_params_.corrx = [estim_params_.corrx; ";
else if (symb_type == SymbolType::endogenous) else if (symb_type == SymbolType::endogenous)
output << "if ~isempty(find((estim_params_.corrn(:,1)==" << tsid << " & estim_params_.corrn(:,2)==" << tsid2 << ") | " output << "if ~isempty(find((estim_params_.corrn(:,1)==" << tsid
<< "(estim_params_.corrn(:,2)==" << tsid << " & estim_params_.corrn(:,1)==" << tsid2 << ")))" << endl << " & estim_params_.corrn(:,2)==" << tsid2 << ") | "
<< " error('The correlation between measurement errors on " << it.name << " and " << it.name2 << errmsg << "')" << endl << "(estim_params_.corrn(:,2)==" << tsid
<< " & estim_params_.corrn(:,1)==" << tsid2 << ")))" << endl
<< " error('The correlation between measurement errors on " << it.name
<< " and " << it.name2 << errmsg << "')" << endl
<< "end" << endl << "end" << endl
<< "estim_params_.corrn = [estim_params_.corrn; "; << "estim_params_.corrn = [estim_params_.corrn; ";
output << tsid << ", " << symbol_table.getTypeSpecificID(it.name2) + 1; output << tsid << ", " << symbol_table.getTypeSpecificID(it.name2) + 1;
...@@ -1399,8 +1322,7 @@ EstimatedParamsStatement::writeOutput(ostream &output, [[maybe_unused]] const st ...@@ -1399,8 +1322,7 @@ EstimatedParamsStatement::writeOutput(ostream &output, [[maybe_unused]] const st
it.low_bound->writeOutput(output); it.low_bound->writeOutput(output);
output << ", "; output << ", ";
it.up_bound->writeOutput(output); it.up_bound->writeOutput(output);
output << ", " output << ", " << static_cast<int>(it.prior) << ", ";
<< static_cast<int>(it.prior) << ", ";
it.mean->writeOutput(output); it.mean->writeOutput(output);
output << ", "; output << ", ";
it.std->writeOutput(output); it.std->writeOutput(output);
...@@ -1419,8 +1341,7 @@ EstimatedParamsStatement::writeJsonOutput(ostream &output) const ...@@ -1419,8 +1341,7 @@ EstimatedParamsStatement::writeJsonOutput(ostream &output) const
{ {
output << R"({"statementName": "estimated_params", )" output << R"({"statementName": "estimated_params", )"
<< R"("params": [)"; << R"("params": [)";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& it : estim_params_list)
const auto &it : estim_params_list)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
...@@ -1445,9 +1366,7 @@ EstimatedParamsStatement::writeJsonOutput(ostream &output) const ...@@ -1445,9 +1366,7 @@ EstimatedParamsStatement::writeJsonOutput(ostream &output) const
it.low_bound->writeJsonOutput(output, {}, {}); it.low_bound->writeJsonOutput(output, {}, {});
output << R"(", "upper_bound": ")"; output << R"(", "upper_bound": ")";
it.up_bound->writeJsonOutput(output, {}, {}); it.up_bound->writeJsonOutput(output, {}, {});
output << R"(", "prior_distribution": )" output << R"(", "prior_distribution": )" << static_cast<int>(it.prior) << R"(, "mean": ")";
<< static_cast<int>(it.prior)
<< R"(, "mean": ")";
it.mean->writeJsonOutput(output, {}, {}); it.mean->writeJsonOutput(output, {}, {});
output << R"(", "std": ")"; output << R"(", "std": ")";
it.std->writeJsonOutput(output, {}, {}); it.std->writeJsonOutput(output, {}, {});
...@@ -1463,8 +1382,8 @@ EstimatedParamsStatement::writeJsonOutput(ostream &output) const ...@@ -1463,8 +1382,8 @@ EstimatedParamsStatement::writeJsonOutput(ostream &output) const
<< "}"; << "}";
} }
EstimatedParamsInitStatement::EstimatedParamsInitStatement(vector<EstimationParams> estim_params_list_arg, EstimatedParamsInitStatement::EstimatedParamsInitStatement(
const SymbolTable &symbol_table_arg, vector<EstimationParams> estim_params_list_arg, const SymbolTable& symbol_table_arg,
const bool use_calibration_arg) : const bool use_calibration_arg) :
AbstractEstimatedParamsStatement(move(estim_params_list_arg), symbol_table_arg), AbstractEstimatedParamsStatement(move(estim_params_list_arg), symbol_table_arg),
use_calibration {use_calibration_arg} use_calibration {use_calibration_arg}
...@@ -1501,37 +1420,38 @@ EstimatedParamsInitStatement::writeOutput(ostream &output, [[maybe_unused]] cons ...@@ -1501,37 +1420,38 @@ EstimatedParamsInitStatement::writeOutput(ostream &output, [[maybe_unused]] cons
{ {
output << "tmp1 = find(estim_params_.var_exo(:,1)==" << tsid << ");" << endl output << "tmp1 = find(estim_params_.var_exo(:,1)==" << tsid << ");" << endl
<< "if isempty(tmp1)" << endl << "if isempty(tmp1)" << endl
<< " disp(sprintf('The standard deviation of %s is not estimated (the value provided in estimated_params_init is not used).', M_.exo_names{" << tsid << "}))" << endl; << " disp(sprintf('The standard deviation of %s is not estimated (the "
"value provided in estimated_params_init is not used).', M_.exo_names{"
<< tsid << "}))" << endl;
skipline = true; skipline = true;
output << "else" << endl output << "else" << endl << " estim_params_.var_exo(tmp1,2) = ";
<< " estim_params_.var_exo(tmp1,2) = ";
it.init_val->writeOutput(output); it.init_val->writeOutput(output);
output << ";" << endl output << ";" << endl << "end" << endl;
<< "end" << endl;
} }
else if (symb_type == SymbolType::endogenous) else if (symb_type == SymbolType::endogenous)
{ {
output << "tmp1 = find(estim_params_.var_endo(:,1)==" << tsid << ");" << endl output << "tmp1 = find(estim_params_.var_endo(:,1)==" << tsid << ");" << endl
<< "if isempty(tmp1)" << endl << "if isempty(tmp1)" << endl
<< " disp(sprintf('The standard deviation of the measurement error on %s is not estimated (the value provided in estimated_params_init is not used).', M_.endo_names{" << tsid << "}))" << endl; << " disp(sprintf('The standard deviation of the measurement error on %s "
"is not estimated (the value provided in estimated_params_init is not "
"used).', M_.endo_names{"
<< tsid << "}))" << endl;
skipline = true; skipline = true;
output << "else" << endl output << "else" << endl << " estim_params_.var_endo(tmp1,2) = ";
<< " estim_params_.var_endo(tmp1,2) = ";
it.init_val->writeOutput(output); it.init_val->writeOutput(output);
output << ";" << endl output << ";" << endl << "end" << endl;
<< "end" << endl;
} }
else if (symb_type == SymbolType::parameter) else if (symb_type == SymbolType::parameter)
{ {
output << "tmp1 = find(estim_params_.param_vals(:,1)==" << tsid << ");" << endl output << "tmp1 = find(estim_params_.param_vals(:,1)==" << tsid << ");" << endl
<< "if isempty(tmp1)" << endl << "if isempty(tmp1)" << endl
<< " disp(sprintf('Parameter %s is not estimated (the value provided in estimated_params_init is not used).', M_.param_names{" << tsid << "}))" << endl; << " disp(sprintf('Parameter %s is not estimated (the value provided in "
"estimated_params_init is not used).', M_.param_names{"
<< tsid << "}))" << endl;
skipline = true; skipline = true;
output << "else" << endl output << "else" << endl << " estim_params_.param_vals(tmp1,2) = ";
<< " estim_params_.param_vals(tmp1,2) = ";
it.init_val->writeOutput(output); it.init_val->writeOutput(output);
output << ";" << endl output << ";" << endl << "end" << endl;
<< "end" << endl;
} }
} }
else else
...@@ -1539,31 +1459,34 @@ EstimatedParamsInitStatement::writeOutput(ostream &output, [[maybe_unused]] cons ...@@ -1539,31 +1459,34 @@ EstimatedParamsInitStatement::writeOutput(ostream &output, [[maybe_unused]] cons
int tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1; int tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1;
if (symb_type == SymbolType::exogenous) if (symb_type == SymbolType::exogenous)
{ {
output << "tmp1 = find((estim_params_.corrx(:,1)==" << tsid << " & estim_params_.corrx(:,2)==" << tsid2 << ") | " output << "tmp1 = find((estim_params_.corrx(:,1)==" << tsid
<< "(estim_params_.corrx(:,2)==" << tsid << " & estim_params_.corrx(:,1)==" << tsid2 << "));" << endl << " & estim_params_.corrx(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrx(:,2)==" << tsid
<< " & estim_params_.corrx(:,1)==" << tsid2 << "));" << endl
<< "if isempty(tmp1)" << endl << "if isempty(tmp1)" << endl
<< " disp(sprintf('The correlation between %s and %s is not estimated (the value provided in estimated_params_init is not used).', M_.exo_names{" << " disp(sprintf('The correlation between %s and %s is not estimated (the "
"value provided in estimated_params_init is not used).', M_.exo_names{"
<< tsid << "}, M_.exo_names{" << tsid2 << "}))" << endl; << tsid << "}, M_.exo_names{" << tsid2 << "}))" << endl;
skipline = true; skipline = true;
output << "else" << endl output << "else" << endl << " estim_params_.corrx(tmp1,3) = ";
<< " estim_params_.corrx(tmp1,3) = ";
it.init_val->writeOutput(output); it.init_val->writeOutput(output);
output << ";" << endl output << ";" << endl << "end" << endl;
<< "end" << endl;
} }
else if (symb_type == SymbolType::endogenous) else if (symb_type == SymbolType::endogenous)
{ {
output << "tmp1 = find((estim_params_.corrn(:,1)==" << tsid << " & estim_params_.corrn(:,2)==" << tsid2 << ") | " output << "tmp1 = find((estim_params_.corrn(:,1)==" << tsid
<< "(estim_params_.corrn(:,2)==" << tsid << " & estim_params_.corrn(:,1)==" << tsid2 << "));" << endl << " & estim_params_.corrn(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrn(:,2)==" << tsid
<< " & estim_params_.corrn(:,1)==" << tsid2 << "));" << endl
<< "if isempty(tmp1)" << endl << "if isempty(tmp1)" << endl
<< " disp(sprintf('The correlation between measurement errors on %s and %s is not estimated (the value provided in estimated_params_init is not used).', M_.endo_names{" << " disp(sprintf('The correlation between measurement errors on %s and %s "
"is not estimated (the value provided in estimated_params_init is not "
"used).', M_.endo_names{"
<< tsid << "}, M_.endo_names{" << tsid2 << "}))" << endl; << tsid << "}, M_.endo_names{" << tsid2 << "}))" << endl;
skipline = true; skipline = true;
output << "else" << endl output << "else" << endl << " estim_params_.corrn(tmp1,3) = ";
<< " estim_params_.corrn(tmp1,3) = ";
it.init_val->writeOutput(output); it.init_val->writeOutput(output);
output << ";" << endl output << ";" << endl << "end" << endl;
<< "end" << endl;
} }
} }
} }
...@@ -1580,8 +1503,7 @@ EstimatedParamsInitStatement::writeJsonOutput(ostream &output) const ...@@ -1580,8 +1503,7 @@ EstimatedParamsInitStatement::writeJsonOutput(ostream &output) const
output << R"(, "use_calibration_initialization": 1)"; output << R"(, "use_calibration_initialization": 1)";
output << R"(, "params": [)"; output << R"(, "params": [)";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& it : estim_params_list)
const auto &it : estim_params_list)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
...@@ -1607,8 +1529,8 @@ EstimatedParamsInitStatement::writeJsonOutput(ostream &output) const ...@@ -1607,8 +1529,8 @@ EstimatedParamsInitStatement::writeJsonOutput(ostream &output) const
<< "}"; << "}";
} }
EstimatedParamsBoundsStatement::EstimatedParamsBoundsStatement(vector<EstimationParams> estim_params_list_arg, EstimatedParamsBoundsStatement::EstimatedParamsBoundsStatement(
const SymbolTable &symbol_table_arg) : vector<EstimationParams> estim_params_list_arg, const SymbolTable& symbol_table_arg) :
AbstractEstimatedParamsStatement(move(estim_params_list_arg), symbol_table_arg) AbstractEstimatedParamsStatement(move(estim_params_list_arg), symbol_table_arg)
{ {
} }
...@@ -1621,7 +1543,8 @@ EstimatedParamsBoundsStatement::checkPass([[maybe_unused]] ModFileStructure &mod ...@@ -1621,7 +1543,8 @@ EstimatedParamsBoundsStatement::checkPass([[maybe_unused]] ModFileStructure &mod
} }
void void
EstimatedParamsBoundsStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename, EstimatedParamsBoundsStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
for (const auto& it : estim_params_list) for (const auto& it : estim_params_list)
...@@ -1636,8 +1559,7 @@ EstimatedParamsBoundsStatement::writeOutput(ostream &output, [[maybe_unused]] co ...@@ -1636,8 +1559,7 @@ EstimatedParamsBoundsStatement::writeOutput(ostream &output, [[maybe_unused]] co
output << "tmp1 = find(estim_params_.var_exo(:,1)==" << tsid << ");" << endl output << "tmp1 = find(estim_params_.var_exo(:,1)==" << tsid << ");" << endl
<< "estim_params_.var_exo(tmp1,3) = "; << "estim_params_.var_exo(tmp1,3) = ";
it.low_bound->writeOutput(output); it.low_bound->writeOutput(output);
output << ";" << endl output << ";" << endl << "estim_params_.var_exo(tmp1,4) = ";
<< "estim_params_.var_exo(tmp1,4) = ";
it.up_bound->writeOutput(output); it.up_bound->writeOutput(output);
output << ";" << endl; output << ";" << endl;
} }
...@@ -1646,8 +1568,7 @@ EstimatedParamsBoundsStatement::writeOutput(ostream &output, [[maybe_unused]] co ...@@ -1646,8 +1568,7 @@ EstimatedParamsBoundsStatement::writeOutput(ostream &output, [[maybe_unused]] co
output << "tmp1 = find(estim_params_.var_endo(:,1)==" << tsid << ");" << endl output << "tmp1 = find(estim_params_.var_endo(:,1)==" << tsid << ");" << endl
<< "estim_params_.var_endo(tmp1,3) = "; << "estim_params_.var_endo(tmp1,3) = ";
it.low_bound->writeOutput(output); it.low_bound->writeOutput(output);
output << ";" << endl output << ";" << endl << "estim_params_.var_endo(tmp1,4) = ";
<< "estim_params_.var_endo(tmp1,4) = ";
it.up_bound->writeOutput(output); it.up_bound->writeOutput(output);
output << ";" << endl; output << ";" << endl;
} }
...@@ -1656,8 +1577,7 @@ EstimatedParamsBoundsStatement::writeOutput(ostream &output, [[maybe_unused]] co ...@@ -1656,8 +1577,7 @@ EstimatedParamsBoundsStatement::writeOutput(ostream &output, [[maybe_unused]] co
output << "tmp1 = find(estim_params_.param_vals(:,1)==" << tsid << ");" << endl output << "tmp1 = find(estim_params_.param_vals(:,1)==" << tsid << ");" << endl
<< "estim_params_.param_vals(tmp1,3) = "; << "estim_params_.param_vals(tmp1,3) = ";
it.low_bound->writeOutput(output); it.low_bound->writeOutput(output);
output << ";" << endl output << ";" << endl << "estim_params_.param_vals(tmp1,4) = ";
<< "estim_params_.param_vals(tmp1,4) = ";
it.up_bound->writeOutput(output); it.up_bound->writeOutput(output);
output << ";" << endl; output << ";" << endl;
} }
...@@ -1667,23 +1587,25 @@ EstimatedParamsBoundsStatement::writeOutput(ostream &output, [[maybe_unused]] co ...@@ -1667,23 +1587,25 @@ EstimatedParamsBoundsStatement::writeOutput(ostream &output, [[maybe_unused]] co
int tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1; int tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1;
if (symb_type == SymbolType::exogenous) if (symb_type == SymbolType::exogenous)
{ {
output << "tmp1 = find((estim_params_.corrx(:,1)==" << tsid << " & estim_params_.corrx(:,2)==" << tsid2 << ") | " output << "tmp1 = find((estim_params_.corrx(:,1)==" << tsid
<< "(estim_params_.corrx(:,2)==" << tsid << " & estim_params_.corrx(:,1)==" << tsid2 << "));" << endl << " & estim_params_.corrx(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrx(:,2)==" << tsid
<< " & estim_params_.corrx(:,1)==" << tsid2 << "));" << endl
<< "estim_params_.corrx(tmp1,4) = "; << "estim_params_.corrx(tmp1,4) = ";
it.low_bound->writeOutput(output); it.low_bound->writeOutput(output);
output << ";" << endl output << ";" << endl << "estim_params_.corrx(tmp1,5) = ";
<< "estim_params_.corrx(tmp1,5) = ";
it.up_bound->writeOutput(output); it.up_bound->writeOutput(output);
output << ";" << endl; output << ";" << endl;
} }
else if (symb_type == SymbolType::endogenous) else if (symb_type == SymbolType::endogenous)
{ {
output << "tmp1 = find((estim_params_.corrn(:,1)==" << tsid << " & estim_params_.corrn(:,2)==" << tsid2 << ") | " output << "tmp1 = find((estim_params_.corrn(:,1)==" << tsid
<< "(estim_params_.corrn(:,2)==" << tsid << " & estim_params_.corrn(:,1)==" << tsid2 << "));" << endl << " & estim_params_.corrn(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrn(:,2)==" << tsid
<< " & estim_params_.corrn(:,1)==" << tsid2 << "));" << endl
<< "estim_params_.corrn(tmp1,4) = "; << "estim_params_.corrn(tmp1,4) = ";
it.low_bound->writeOutput(output); it.low_bound->writeOutput(output);
output << ";" << endl output << ";" << endl << "estim_params_.corrn(tmp1,5) = ";
<< "estim_params_.corrn(tmp1,5) = ";
it.up_bound->writeOutput(output); it.up_bound->writeOutput(output);
output << ";" << endl; output << ";" << endl;
} }
...@@ -1697,8 +1619,7 @@ EstimatedParamsBoundsStatement::writeJsonOutput(ostream &output) const ...@@ -1697,8 +1619,7 @@ EstimatedParamsBoundsStatement::writeJsonOutput(ostream &output) const
output << R"({"statementName": "estimated_params_bounds", )" output << R"({"statementName": "estimated_params_bounds", )"
<< R"("params": [)"; << R"("params": [)";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& it : estim_params_list)
const auto &it : estim_params_list)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
...@@ -1726,15 +1647,15 @@ EstimatedParamsBoundsStatement::writeJsonOutput(ostream &output) const ...@@ -1726,15 +1647,15 @@ EstimatedParamsBoundsStatement::writeJsonOutput(ostream &output) const
<< "}"; << "}";
} }
EstimatedParamsRemoveStatement::EstimatedParamsRemoveStatement(vector<EstimationParams> estim_params_list_arg, EstimatedParamsRemoveStatement::EstimatedParamsRemoveStatement(
const SymbolTable &symbol_table_arg) : vector<EstimationParams> estim_params_list_arg, const SymbolTable& symbol_table_arg) :
estim_params_list{move(estim_params_list_arg)}, estim_params_list {move(estim_params_list_arg)}, symbol_table {symbol_table_arg}
symbol_table{symbol_table_arg}
{ {
} }
void void
EstimatedParamsRemoveStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename, EstimatedParamsRemoveStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
for (const auto& it : estim_params_list) for (const auto& it : estim_params_list)
...@@ -1747,21 +1668,27 @@ EstimatedParamsRemoveStatement::writeOutput(ostream &output, [[maybe_unused]] co ...@@ -1747,21 +1668,27 @@ EstimatedParamsRemoveStatement::writeOutput(ostream &output, [[maybe_unused]] co
if (symb_type == SymbolType::exogenous) if (symb_type == SymbolType::exogenous)
output << "tmp1 = find(estim_params_.var_exo(:,1)==" << tsid << ");" << endl output << "tmp1 = find(estim_params_.var_exo(:,1)==" << tsid << ");" << endl
<< "if isempty(tmp1)" << endl << "if isempty(tmp1)" << endl
<< " error(sprintf('estimated_params_remove: the standard deviation of %s is not estimated.', M_.exo_names{" << tsid << "}))" << endl << " error(sprintf('estimated_params_remove: the standard deviation of %s is "
"not estimated.', M_.exo_names{"
<< tsid << "}))" << endl
<< "else" << endl << "else" << endl
<< " estim_params_.var_exo(tmp1,:) = [];" << " estim_params_.var_exo(tmp1,:) = [];"
<< "end" << endl; << "end" << endl;
else if (symb_type == SymbolType::endogenous) else if (symb_type == SymbolType::endogenous)
output << "tmp1 = find(estim_params_.var_endo(:,1)==" << tsid << ");" << endl output << "tmp1 = find(estim_params_.var_endo(:,1)==" << tsid << ");" << endl
<< "if isempty(tmp1)" << endl << "if isempty(tmp1)" << endl
<< " error(sprintf('estimated_params_remove: the standard deviation of the measurement error on %s is not estimated.', M_.endo_names{" << tsid << "}))" << endl << " error(sprintf('estimated_params_remove: the standard deviation of the "
"measurement error on %s is not estimated.', M_.endo_names{"
<< tsid << "}))" << endl
<< "else" << endl << "else" << endl
<< " estim_params_.var_endo(tmp1,:) = [];" << " estim_params_.var_endo(tmp1,:) = [];"
<< "end" << endl; << "end" << endl;
else if (symb_type == SymbolType::parameter) else if (symb_type == SymbolType::parameter)
output << "tmp1 = find(estim_params_.param_vals(:,1)==" << tsid << ");" << endl output << "tmp1 = find(estim_params_.param_vals(:,1)==" << tsid << ");" << endl
<< "if isempty(tmp1)" << endl << "if isempty(tmp1)" << endl
<< " error(sprintf('estimated_params_remove: parameter %s is not estimated.', M_.param_names{" << tsid << "}))" << endl << " error(sprintf('estimated_params_remove: parameter %s is not "
"estimated.', M_.param_names{"
<< tsid << "}))" << endl
<< "else" << endl << "else" << endl
<< " estim_params_.param_vals(tmp1,:) = [];" << " estim_params_.param_vals(tmp1,:) = [];"
<< "end" << endl; << "end" << endl;
...@@ -1770,19 +1697,25 @@ EstimatedParamsRemoveStatement::writeOutput(ostream &output, [[maybe_unused]] co ...@@ -1770,19 +1697,25 @@ EstimatedParamsRemoveStatement::writeOutput(ostream &output, [[maybe_unused]] co
{ {
int tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1; int tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1;
if (symb_type == SymbolType::exogenous) if (symb_type == SymbolType::exogenous)
output << "tmp1 = find((estim_params_.corrx(:,1)==" << tsid << " & estim_params_.corrx(:,2)==" << tsid2 << ") | " output << "tmp1 = find((estim_params_.corrx(:,1)==" << tsid
<< "(estim_params_.corrx(:,2)==" << tsid << " & estim_params_.corrx(:,1)==" << tsid2 << "));" << endl << " & estim_params_.corrx(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrx(:,2)==" << tsid
<< " & estim_params_.corrx(:,1)==" << tsid2 << "));" << endl
<< "if isempty(tmp1)" << endl << "if isempty(tmp1)" << endl
<< " error(sprintf('estimated_params_remove: the correlation between %s and %s is not estimated.', M_.exo_names{" << " error(sprintf('estimated_params_remove: the correlation between %s and "
"%s is not estimated.', M_.exo_names{"
<< tsid << "}, M_.exo_names{" << tsid2 << "}))" << endl << tsid << "}, M_.exo_names{" << tsid2 << "}))" << endl
<< "else" << endl << "else" << endl
<< " estim_params_.corrx(tmp1,:) = [];" << " estim_params_.corrx(tmp1,:) = [];"
<< "end" << endl; << "end" << endl;
else if (symb_type == SymbolType::endogenous) else if (symb_type == SymbolType::endogenous)
output << "tmp1 = find((estim_params_.corrn(:,1)==" << tsid << " & estim_params_.corrn(:,2)==" << tsid2 << ") | " output << "tmp1 = find((estim_params_.corrn(:,1)==" << tsid
<< "(estim_params_.corrn(:,2)==" << tsid << " & estim_params_.corrn(:,1)==" << tsid2 << "));" << endl << " & estim_params_.corrn(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrn(:,2)==" << tsid
<< " & estim_params_.corrn(:,1)==" << tsid2 << "));" << endl
<< "if isempty(tmp1)" << endl << "if isempty(tmp1)" << endl
<< " error(sprintf('estimated_params_remove: the correlation between measurement errors on %s and %s is not estimated.', M_.endo_names{" << " error(sprintf('estimated_params_remove: the correlation between "
"measurement errors on %s and %s is not estimated.', M_.endo_names{"
<< tsid << "}, M_.endo_names{" << tsid2 << "}))" << endl << tsid << "}, M_.endo_names{" << tsid2 << "}))" << endl
<< "else" << endl << "else" << endl
<< " estim_params_.corrn(tmp1,:) = [];" << " estim_params_.corrn(tmp1,:) = [];"
...@@ -1797,8 +1730,7 @@ EstimatedParamsRemoveStatement::writeJsonOutput(ostream &output) const ...@@ -1797,8 +1730,7 @@ EstimatedParamsRemoveStatement::writeJsonOutput(ostream &output) const
output << R"({"statementName": "estimated_params_remove", )" output << R"({"statementName": "estimated_params_remove", )"
<< R"("params": [)"; << R"("params": [)";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& it : estim_params_list)
const auto &it : estim_params_list)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
...@@ -1824,8 +1756,7 @@ EstimatedParamsRemoveStatement::writeJsonOutput(ostream &output) const ...@@ -1824,8 +1756,7 @@ EstimatedParamsRemoveStatement::writeJsonOutput(ostream &output) const
DeterministicTrendsStatement::DeterministicTrendsStatement(trend_elements_t trend_elements_arg, DeterministicTrendsStatement::DeterministicTrendsStatement(trend_elements_t trend_elements_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
trend_elements{move(trend_elements_arg)}, trend_elements {move(trend_elements_arg)}, symbol_table {symbol_table_arg}
symbol_table{symbol_table_arg}
{ {
} }
...@@ -1834,19 +1765,16 @@ DeterministicTrendsStatement::writeOutput(ostream &output, [[maybe_unused]] cons ...@@ -1834,19 +1765,16 @@ DeterministicTrendsStatement::writeOutput(ostream &output, [[maybe_unused]] cons
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
output << "options_.trend_coeff = {};" << endl; output << "options_.trend_coeff = {};" << endl;
for (const auto &trend_element : trend_elements) for (const auto& [name, val] : trend_elements)
if (symbol_table.getType(name) == SymbolType::endogenous)
{ {
SymbolType type = symbol_table.getType(trend_element.first); output << "tmp1 = strmatch('" << name << "',M_.endogenous_names,'exact');" << endl
if (type == SymbolType::endogenous) << "options_.deterministic_trend_coeffs{tmp1} = '";
{ val->writeOutput(output);
output << "tmp1 = strmatch('" << trend_element.first << "',M_.endogenous_names,'exact');" << endl;
output << "options_.deterministic_trend_coeffs{tmp1} = '";
trend_element.second->writeOutput(output);
output << "';" << endl; output << "';" << endl;
} }
else else
cerr << "Warning : Non-variable symbol used in deterministic_trends: " << trend_element.first << endl; cerr << "Warning: Non-variable symbol used in deterministic_trends: " << name << endl;
}
} }
void void
...@@ -1854,28 +1782,24 @@ DeterministicTrendsStatement::writeJsonOutput(ostream &output) const ...@@ -1854,28 +1782,24 @@ DeterministicTrendsStatement::writeJsonOutput(ostream &output) const
{ {
output << R"({"statementName": "deterministic_trends", )" output << R"({"statementName": "deterministic_trends", )"
<< R"("trends" : {)"; << R"("trends" : {)";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& [name, val] : trend_elements)
const auto &trend_element : trend_elements) if (symbol_table.getType(name) == SymbolType::endogenous)
{
if (symbol_table.getType(trend_element.first) == SymbolType::endogenous)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
output << R"(")" << trend_element.first << R"(": ")"; output << R"(")" << name << R"(": ")";
trend_element.second->writeJsonOutput(output, {}, {}); val->writeJsonOutput(output, {}, {});
output << R"(")" << endl; output << R"(")" << endl;
} }
else else
cerr << "Warning : Non-variable symbol used in deterministic_trends: " << trend_element.first << endl; cerr << "Warning: Non-variable symbol used in deterministic_trends: " << name << endl;
}
output << "}" output << "}"
<< "}"; << "}";
} }
ObservationTrendsStatement::ObservationTrendsStatement(trend_elements_t trend_elements_arg, ObservationTrendsStatement::ObservationTrendsStatement(trend_elements_t trend_elements_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
trend_elements{move(trend_elements_arg)}, trend_elements {move(trend_elements_arg)}, symbol_table {symbol_table_arg}
symbol_table{symbol_table_arg}
{ {
} }
...@@ -1884,19 +1808,16 @@ ObservationTrendsStatement::writeOutput(ostream &output, [[maybe_unused]] const ...@@ -1884,19 +1808,16 @@ ObservationTrendsStatement::writeOutput(ostream &output, [[maybe_unused]] const
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
output << "options_.trend_coeff = {};" << endl; output << "options_.trend_coeff = {};" << endl;
for (const auto &trend_element : trend_elements) for (const auto& [name, val] : trend_elements)
if (symbol_table.getType(name) == SymbolType::endogenous)
{ {
SymbolType type = symbol_table.getType(trend_element.first); output << "tmp1 = strmatch('" << name << "',options_.varobs,'exact');" << endl
if (type == SymbolType::endogenous) << "options_.trend_coeffs{tmp1} = '";
{ val->writeOutput(output);
output << "tmp1 = strmatch('" << trend_element.first << "',options_.varobs,'exact');" << endl;
output << "options_.trend_coeffs{tmp1} = '";
trend_element.second->writeOutput(output);
output << "';" << endl; output << "';" << endl;
} }
else else
cerr << "Warning : Non-variable symbol used in observation_trends: " << trend_element.first << endl; cerr << "Warning: Non-variable symbol used in observation_trends: " << name << endl;
}
} }
void void
...@@ -1904,25 +1825,23 @@ ObservationTrendsStatement::writeJsonOutput(ostream &output) const ...@@ -1904,25 +1825,23 @@ ObservationTrendsStatement::writeJsonOutput(ostream &output) const
{ {
output << R"({"statementName": "observation_trends", )" output << R"({"statementName": "observation_trends", )"
<< R"("trends" : {)"; << R"("trends" : {)";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& [name, val] : trend_elements)
const auto &trend_element : trend_elements) if (symbol_table.getType(name) == SymbolType::endogenous)
{
if (symbol_table.getType(trend_element.first) == SymbolType::endogenous)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
output << R"(")" << trend_element.first << R"(": ")"; output << R"(")" << name << R"(": ")";
trend_element.second->writeJsonOutput(output, {}, {}); val->writeJsonOutput(output, {}, {});
output << R"(")" << endl; output << R"(")" << endl;
} }
else else
cerr << "Warning : Non-variable symbol used in observation_trends: " << trend_element.first << endl; cerr << "Warning: Non-variable symbol used in observation_trends: " << name << endl;
}
output << "}" output << "}"
<< "}"; << "}";
} }
FilterInitialStateStatement::FilterInitialStateStatement(filter_initial_state_elements_t filter_initial_state_elements_arg, FilterInitialStateStatement::FilterInitialStateStatement(
filter_initial_state_elements_t filter_initial_state_elements_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
filter_initial_state_elements {move(filter_initial_state_elements_arg)}, filter_initial_state_elements {move(filter_initial_state_elements_arg)},
symbol_table {symbol_table_arg} symbol_table {symbol_table_arg}
...@@ -1958,8 +1877,7 @@ FilterInitialStateStatement::writeOutput(ostream &output, [[maybe_unused]] const ...@@ -1958,8 +1877,7 @@ FilterInitialStateStatement::writeOutput(ostream &output, [[maybe_unused]] const
} }
} }
output << "M_.filter_initial_state(" output << "M_.filter_initial_state(" << symbol_table.getTypeSpecificID(symb_id) + 1
<< symbol_table.getTypeSpecificID(symb_id) + 1
<< ",:) = {'" << symbol_table.getName(symb_id) << "', '"; << ",:) = {'" << symbol_table.getName(symb_id) << "', '";
val->writeOutput(output); val->writeOutput(output);
output << ";'};" << endl; output << ";'};" << endl;
...@@ -1972,14 +1890,12 @@ FilterInitialStateStatement::writeJsonOutput(ostream &output) const ...@@ -1972,14 +1890,12 @@ FilterInitialStateStatement::writeJsonOutput(ostream &output) const
output << R"({"statementName": "filter_initial_state", )" output << R"({"statementName": "filter_initial_state", )"
<< R"("states": [)"; << R"("states": [)";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& [key, val] : filter_initial_state_elements)
const auto &[key, val] : filter_initial_state_elements)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
auto& [symb_id, lag] = key; auto& [symb_id, lag] = key;
output << R"({ "var": ")" << symbol_table.getName(symb_id) output << R"({ "var": ")" << symbol_table.getName(symb_id) << R"(", "lag": )" << lag
<< R"(", "lag": )" << lag
<< R"(, "value": ")"; << R"(, "value": ")";
val->writeJsonOutput(output, {}, {}); val->writeJsonOutput(output, {}, {});
output << R"(" })"; output << R"(" })";
...@@ -1987,9 +1903,9 @@ FilterInitialStateStatement::writeJsonOutput(ostream &output) const ...@@ -1987,9 +1903,9 @@ FilterInitialStateStatement::writeJsonOutput(ostream &output) const
output << "] }"; output << "] }";
} }
OsrParamsStatement::OsrParamsStatement(SymbolList symbol_list_arg, const SymbolTable &symbol_table_arg) : OsrParamsStatement::OsrParamsStatement(SymbolList symbol_list_arg,
symbol_list{move(symbol_list_arg)}, const SymbolTable& symbol_table_arg) :
symbol_table{symbol_table_arg} symbol_list {move(symbol_list_arg)}, symbol_table {symbol_table_arg}
{ {
} }
...@@ -1997,7 +1913,7 @@ void ...@@ -1997,7 +1913,7 @@ void
OsrParamsStatement::checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) OsrParamsStatement::checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings)
{ {
if (mod_file_struct.osr_params_present) if (mod_file_struct.osr_params_present)
cerr << "WARNING: You have more than one osr_params statement in the .mod file." << endl; warnings << "WARNING: You have more than one osr_params statement in the .mod file." << endl;
mod_file_struct.osr_params_present = true; mod_file_struct.osr_params_present = true;
try try
...@@ -2018,9 +1934,9 @@ OsrParamsStatement::writeOutput(ostream &output, [[maybe_unused]] const string & ...@@ -2018,9 +1934,9 @@ OsrParamsStatement::writeOutput(ostream &output, [[maybe_unused]] const string &
symbol_list.writeOutput("M_.osr.param_names", output); symbol_list.writeOutput("M_.osr.param_names", output);
output << "M_.osr.param_names = cellstr(M_.osr.param_names);" << endl output << "M_.osr.param_names = cellstr(M_.osr.param_names);" << endl
<< "M_.osr.param_indices = zeros(length(M_.osr.param_names), 1);" << endl; << "M_.osr.param_indices = zeros(length(M_.osr.param_names), 1);" << endl;
for (int i{0}; for (int i {0}; auto& symbol : symbol_list.getSymbols())
auto &symbol : symbol_list.getSymbols()) output << "M_.osr.param_indices(" << ++i << ") = " << symbol_table.getTypeSpecificID(symbol) + 1
output << "M_.osr.param_indices(" << ++i <<") = " << symbol_table.getTypeSpecificID(symbol) + 1 << ";" << endl; << ";" << endl;
} }
void void
...@@ -2046,7 +1962,8 @@ OsrParamsBoundsStatement::checkPass(ModFileStructure &mod_file_struct, ...@@ -2046,7 +1962,8 @@ OsrParamsBoundsStatement::checkPass(ModFileStructure &mod_file_struct,
{ {
if (!mod_file_struct.osr_params_present) if (!mod_file_struct.osr_params_present)
{ {
cerr << "ERROR: you must have an osr_params statement before the osr_params_bounds block." << endl; cerr << "ERROR: you must have an osr_params statement before the osr_params_bounds block."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -2056,7 +1973,9 @@ OsrParamsBoundsStatement::writeOutput(ostream &output, [[maybe_unused]] const st ...@@ -2056,7 +1973,9 @@ OsrParamsBoundsStatement::writeOutput(ostream &output, [[maybe_unused]] const st
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
output << "M_.osr.param_bounds = [-inf(length(M_.osr.param_names), 1), inf(length(M_.osr.param_names), 1)];" << endl; output << "M_.osr.param_bounds = [-inf(length(M_.osr.param_names), 1), "
"inf(length(M_.osr.param_names), 1)];"
<< endl;
for (const auto& it : osr_params_list) for (const auto& it : osr_params_list)
{ {
...@@ -2073,8 +1992,7 @@ OsrParamsBoundsStatement::writeJsonOutput(ostream &output) const ...@@ -2073,8 +1992,7 @@ OsrParamsBoundsStatement::writeJsonOutput(ostream &output) const
{ {
output << R"({"statementName": "osr_params_bounds")" output << R"({"statementName": "osr_params_bounds")"
<< R"(, "bounds": [)"; << R"(, "bounds": [)";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& it : osr_params_list)
const auto &it : osr_params_list)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
...@@ -2117,7 +2035,6 @@ OsrStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation ...@@ -2117,7 +2035,6 @@ OsrStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation
opt && *opt == "1") opt && *opt == "1")
mod_file_struct.osr_analytic_derivation = true; mod_file_struct.osr_analytic_derivation = true;
// Option k_order_solver (implicit when order >= 3) // Option k_order_solver (implicit when order >= 3)
if (auto opt = options_list.get_if<OptionsList::NumVal>("k_order_solver"); if (auto opt = options_list.get_if<OptionsList::NumVal>("k_order_solver");
(opt && *opt == "true") || mod_file_struct.order_option >= 3) (opt && *opt == "true") || mod_file_struct.order_option >= 3)
...@@ -2146,7 +2063,9 @@ OsrStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basena ...@@ -2146,7 +2063,9 @@ OsrStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basena
options_list.writeOutput(output); options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output); symbol_list.writeOutput("var_list_", output);
output << "[info, oo_, options_, M_] = osr.run(M_, options_, oo_, var_list_,M_.osr.param_names,M_.osr.variable_indices,M_.osr.variable_weights);" << endl; output << "[info, oo_, options_, M_] = osr.run(M_, options_, oo_, "
"var_list_,M_.osr.param_names,M_.osr.variable_indices,M_.osr.variable_weights);"
<< endl;
} }
void void
...@@ -2190,7 +2109,8 @@ OptimWeightsStatement::writeOutput(ostream &output, [[maybe_unused]] const strin ...@@ -2190,7 +2109,8 @@ OptimWeightsStatement::writeOutput(ostream &output, [[maybe_unused]] const strin
<< "% OPTIM_WEIGHTS" << endl << "% OPTIM_WEIGHTS" << endl
<< "%" << endl << "%" << endl
<< "M_.osr.variable_weights = sparse(M_.endo_nbr,M_.endo_nbr);" << endl << "M_.osr.variable_weights = sparse(M_.endo_nbr,M_.endo_nbr);" << endl
<< "M_.osr.variable_indices = [];" << endl << endl; << "M_.osr.variable_indices = [];" << endl
<< endl;
for (const auto& [name, value] : var_weights) for (const auto& [name, value] : var_weights)
{ {
...@@ -2208,7 +2128,8 @@ OptimWeightsStatement::writeOutput(ostream &output, [[maybe_unused]] const strin ...@@ -2208,7 +2128,8 @@ OptimWeightsStatement::writeOutput(ostream &output, [[maybe_unused]] const strin
output << "M_.osr.variable_weights(" << id1 << "," << id2 << ") = "; output << "M_.osr.variable_weights(" << id1 << "," << id2 << ") = ";
value->writeOutput(output); value->writeOutput(output);
output << ";" << endl; output << ";" << endl;
output << "M_.osr.variable_indices = [M_.osr.variable_indices; " << id1 << "; " << id2 << "];" << endl; output << "M_.osr.variable_indices = [M_.osr.variable_indices; " << id1 << "; " << id2 << "];"
<< endl;
} }
} }
...@@ -2255,7 +2176,8 @@ DynaSaveStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct, ...@@ -2255,7 +2176,8 @@ DynaSaveStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct,
{ {
try try
{ {
symbol_list.checkPass(warnings, { SymbolType::endogenous, SymbolType::exogenous }, symbol_table); symbol_list.checkPass(warnings, {SymbolType::endogenous, SymbolType::exogenous},
symbol_table);
} }
catch (SymbolList::SymbolListException& e) catch (SymbolList::SymbolListException& e)
{ {
...@@ -2269,8 +2191,7 @@ DynaSaveStatement::writeOutput(ostream &output, [[maybe_unused]] const string &b ...@@ -2269,8 +2191,7 @@ DynaSaveStatement::writeOutput(ostream &output, [[maybe_unused]] const string &b
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
symbol_list.writeOutput("var_list_", output); symbol_list.writeOutput("var_list_", output);
output << "dynasave('" << filename output << "dynasave('" << filename << "',var_list_);" << endl;
<< "',var_list_);" << endl;
} }
void void
...@@ -2300,7 +2221,8 @@ DynaTypeStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct, ...@@ -2300,7 +2221,8 @@ DynaTypeStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct,
{ {
try try
{ {
symbol_list.checkPass(warnings, { SymbolType::endogenous, SymbolType::exogenous }, symbol_table); symbol_list.checkPass(warnings, {SymbolType::endogenous, SymbolType::exogenous},
symbol_table);
} }
catch (SymbolList::SymbolListException& e) catch (SymbolList::SymbolListException& e)
{ {
...@@ -2314,8 +2236,7 @@ DynaTypeStatement::writeOutput(ostream &output, [[maybe_unused]] const string &b ...@@ -2314,8 +2236,7 @@ DynaTypeStatement::writeOutput(ostream &output, [[maybe_unused]] const string &b
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
symbol_list.writeOutput("var_list_", output); symbol_list.writeOutput("var_list_", output);
output << "dynatype('" << filename output << "dynatype('" << filename << "',var_list_);" << endl;
<< "',var_list_);" << endl;
} }
void void
...@@ -2333,8 +2254,7 @@ DynaTypeStatement::writeJsonOutput(ostream &output) const ...@@ -2333,8 +2254,7 @@ DynaTypeStatement::writeJsonOutput(ostream &output) const
ModelComparisonStatement::ModelComparisonStatement(filename_list_t filename_list_arg, ModelComparisonStatement::ModelComparisonStatement(filename_list_t filename_list_arg,
OptionsList options_list_arg) : OptionsList options_list_arg) :
filename_list{move(filename_list_arg)}, filename_list {move(filename_list_arg)}, options_list {move(options_list_arg)}
options_list{move(options_list_arg)}
{ {
} }
...@@ -2344,8 +2264,7 @@ ModelComparisonStatement::writeOutput(ostream &output, [[maybe_unused]] const st ...@@ -2344,8 +2264,7 @@ ModelComparisonStatement::writeOutput(ostream &output, [[maybe_unused]] const st
{ {
options_list.writeOutput(output); options_list.writeOutput(output);
output << "ModelNames_ = {};" << endl output << "ModelNames_ = {};" << endl << "ModelPriors_ = [];" << endl;
<< "ModelPriors_ = [];" << endl;
for (const auto& [name, prior] : filename_list) for (const auto& [name, prior] : filename_list)
output << "ModelNames_ = { ModelNames_{:} '" << name << "'};" << endl output << "ModelNames_ = { ModelNames_{:} '" << name << "'};" << endl
...@@ -2361,8 +2280,7 @@ ModelComparisonStatement::writeJsonOutput(ostream &output) const ...@@ -2361,8 +2280,7 @@ ModelComparisonStatement::writeJsonOutput(ostream &output) const
if (!filename_list.empty()) if (!filename_list.empty())
output << R"(, "filename_list": {)"; output << R"(, "filename_list": {)";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& [name, prior] : filename_list)
const auto &[name, prior] : filename_list)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
...@@ -2382,8 +2300,8 @@ ModelComparisonStatement::writeJsonOutput(ostream &output) const ...@@ -2382,8 +2300,8 @@ ModelComparisonStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
PlannerObjectiveStatement::PlannerObjectiveStatement(const PlannerObjective &model_tree_arg) : PlannerObjectiveStatement::PlannerObjectiveStatement(unique_ptr<PlannerObjective> model_tree_arg) :
model_tree{model_tree_arg} model_tree {move(model_tree_arg)}
{ {
} }
...@@ -2391,10 +2309,11 @@ void ...@@ -2391,10 +2309,11 @@ void
PlannerObjectiveStatement::checkPass(ModFileStructure& mod_file_struct, PlannerObjectiveStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings) [[maybe_unused]] WarningConsolidation& warnings)
{ {
assert(model_tree.equation_number() == 1); assert(model_tree->equation_number() == 1);
if (model_tree.exoPresentInEqs()) if (model_tree->exoPresentInEqs())
{ {
cerr << "ERROR: You cannot include exogenous variables (or variables of undeclared type) in the planner objective. Please " cerr << "ERROR: You cannot include exogenous variables (or variables of undeclared type) in "
"the planner objective. Please "
<< "define an auxiliary endogenous variable like eps_aux=epsilon and use it instead " << "define an auxiliary endogenous variable like eps_aux=epsilon and use it instead "
<< "of the varexo." << endl; << "of the varexo." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -2405,13 +2324,13 @@ PlannerObjectiveStatement::checkPass(ModFileStructure &mod_file_struct, ...@@ -2405,13 +2324,13 @@ PlannerObjectiveStatement::checkPass(ModFileStructure &mod_file_struct,
const PlannerObjective& const PlannerObjective&
PlannerObjectiveStatement::getPlannerObjective() const PlannerObjectiveStatement::getPlannerObjective() const
{ {
return model_tree; return *model_tree;
} }
void void
PlannerObjectiveStatement::computingPass(const ModFileStructure& mod_file_struct) PlannerObjectiveStatement::computingPass(const ModFileStructure& mod_file_struct)
{ {
model_tree.computingPass(max(3, mod_file_struct.order_option), 0, {}, false, false, false); model_tree->computingPass(max(3, mod_file_struct.order_option), 0, {}, false, false, false);
computing_pass_called = true; computing_pass_called = true;
} }
...@@ -2419,15 +2338,8 @@ void ...@@ -2419,15 +2338,8 @@ void
PlannerObjectiveStatement::writeOutput(ostream& output, const string& basename, PlannerObjectiveStatement::writeOutput(ostream& output, const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
output << "M_.NNZDerivatives_objective = ["; model_tree->writeDriverOutput(output);
for (int i=1; i < static_cast<int>(model_tree.getNNZDerivatives().size()); i++) model_tree->writeStaticFile(basename + ".objective", false, "", {}, false);
output << (i > model_tree.getComputedDerivsOrder() ? -1 : model_tree.getNNZDerivatives()[i]) << ";";
output << "];" << endl
<< "M_.objective_tmp_nbr = [";
for (const auto &temporary_terms_derivative : model_tree.getTemporaryTermsDerivatives())
output << temporary_terms_derivative.size() << "; ";
output << "];" << endl;
model_tree.writeStaticFile(basename + ".objective", false, "", {}, false);
} }
void void
...@@ -2436,16 +2348,15 @@ PlannerObjectiveStatement::writeJsonOutput(ostream &output) const ...@@ -2436,16 +2348,15 @@ PlannerObjectiveStatement::writeJsonOutput(ostream &output) const
output << R"({"statementName": "planner_objective")" output << R"({"statementName": "planner_objective")"
<< ", "; << ", ";
if (computing_pass_called) if (computing_pass_called)
model_tree.writeJsonComputingPassOutput(output, false); model_tree->writeJsonComputingPassOutput(output, false);
else else
model_tree.writeJsonOutput(output); model_tree->writeJsonOutput(output);
output << "}"; output << "}";
} }
BVARDensityStatement::BVARDensityStatement(int maxnlags_arg, OptionsList options_list_arg) : BVARDensityStatement::BVARDensityStatement(int maxnlags_arg, OptionsList options_list_arg) :
maxnlags{maxnlags_arg}, maxnlags {maxnlags_arg}, options_list {move(options_list_arg)}
options_list{move(options_list_arg)}
{ {
} }
...@@ -2477,8 +2388,7 @@ BVARDensityStatement::writeJsonOutput(ostream &output) const ...@@ -2477,8 +2388,7 @@ BVARDensityStatement::writeJsonOutput(ostream &output) const
} }
BVARForecastStatement::BVARForecastStatement(int nlags_arg, OptionsList options_list_arg) : BVARForecastStatement::BVARForecastStatement(int nlags_arg, OptionsList options_list_arg) :
nlags{nlags_arg}, nlags {nlags_arg}, options_list {move(options_list_arg)}
options_list{move(options_list_arg)}
{ {
} }
...@@ -2510,8 +2420,7 @@ BVARForecastStatement::writeJsonOutput(ostream &output) const ...@@ -2510,8 +2420,7 @@ BVARForecastStatement::writeJsonOutput(ostream &output) const
} }
BVARIRFStatement::BVARIRFStatement(int nirf_arg, string identificationname_arg) : BVARIRFStatement::BVARIRFStatement(int nirf_arg, string identificationname_arg) :
nirf{nirf_arg}, nirf {nirf_arg}, identificationname {move(identificationname_arg)}
identificationname{move(identificationname_arg)}
{ {
} }
...@@ -2536,8 +2445,7 @@ BVARIRFStatement::writeJsonOutput(ostream &output) const ...@@ -2536,8 +2445,7 @@ BVARIRFStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
SBVARStatement::SBVARStatement(OptionsList options_list_arg) : SBVARStatement::SBVARStatement(OptionsList options_list_arg) : options_list {move(options_list_arg)}
options_list{move(options_list_arg)}
{ {
} }
...@@ -2580,8 +2488,7 @@ MSSBVAREstimationStatement::checkPass(ModFileStructure &mod_file_struct, ...@@ -2580,8 +2488,7 @@ MSSBVAREstimationStatement::checkPass(ModFileStructure &mod_file_struct,
mod_file_struct.bvar_present = true; mod_file_struct.bvar_present = true;
if (!options_list.contains("ms.create_init") if (!options_list.contains("ms.create_init")
&& (!options_list.contains("datafile") && (!options_list.contains("datafile") || !options_list.contains("ms.initial_year")))
|| !options_list.contains("ms.initial_year")))
{ {
cerr << "ERROR: If you do not pass no_create_init to ms_estimation, " cerr << "ERROR: If you do not pass no_create_init to ms_estimation, "
<< "you must pass the datafile and initial_year options." << endl; << "you must pass the datafile and initial_year options." << endl;
...@@ -2631,8 +2538,7 @@ MSSBVARSimulationStatement::writeOutput(ostream &output, [[maybe_unused]] const ...@@ -2631,8 +2538,7 @@ MSSBVARSimulationStatement::writeOutput(ostream &output, [[maybe_unused]] const
options_list.writeOutput(output); options_list.writeOutput(output);
// Redeclare drop option if necessary // Redeclare drop option if necessary
if ((options_list.contains("ms.mh_replic") if ((options_list.contains("ms.mh_replic") || options_list.contains("ms.thinning_factor"))
|| options_list.contains("ms.thinning_factor"))
&& !options_list.contains("ms.drop")) && !options_list.contains("ms.drop"))
output << "options_.ms.drop = 0.1*options_.ms.mh_replic*options_.ms.thinning_factor;" << endl; output << "options_.ms.drop = 0.1*options_.ms.mh_replic*options_.ms.thinning_factor;" << endl;
...@@ -2684,7 +2590,8 @@ MSSBVARComputeMDDStatement::writeJsonOutput(ostream &output) const ...@@ -2684,7 +2590,8 @@ MSSBVARComputeMDDStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
MSSBVARComputeProbabilitiesStatement::MSSBVARComputeProbabilitiesStatement(OptionsList options_list_arg) : MSSBVARComputeProbabilitiesStatement::MSSBVARComputeProbabilitiesStatement(
OptionsList options_list_arg) :
options_list {move(options_list_arg)} options_list {move(options_list_arg)}
{ {
} }
...@@ -2743,8 +2650,7 @@ MSSBVARIrfStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli ...@@ -2743,8 +2650,7 @@ MSSBVARIrfStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli
regimes_present = options_list.contains("ms.regimes"), regimes_present = options_list.contains("ms.regimes"),
filtered_probabilities_present = options_list.contains("ms.filtered_probabilities"); filtered_probabilities_present = options_list.contains("ms.filtered_probabilities");
(filtered_probabilities_present && regime_present) (filtered_probabilities_present && regime_present)
|| (filtered_probabilities_present && regimes_present) || (filtered_probabilities_present && regimes_present) || (regimes_present && regime_present))
|| (regimes_present && regime_present))
{ {
cerr << "ERROR: You may only pass one of regime, regimes and " cerr << "ERROR: You may only pass one of regime, regimes and "
<< "filtered_probabilities to ms_irf" << endl; << "filtered_probabilities to ms_irf" << endl;
...@@ -2800,8 +2706,7 @@ MSSBVARForecastStatement::checkPass(ModFileStructure &mod_file_struct, ...@@ -2800,8 +2706,7 @@ MSSBVARForecastStatement::checkPass(ModFileStructure &mod_file_struct,
{ {
mod_file_struct.bvar_present = true; mod_file_struct.bvar_present = true;
if (options_list.contains("ms.regimes") if (options_list.contains("ms.regimes") && options_list.contains("ms.regime"))
&& options_list.contains("ms.regime"))
{ {
cerr << "ERROR: You may only pass one of regime and regimes to ms_forecast" << endl; cerr << "ERROR: You may only pass one of regime and regimes to ms_forecast" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -2829,7 +2734,8 @@ MSSBVARForecastStatement::writeJsonOutput(ostream &output) const ...@@ -2829,7 +2734,8 @@ MSSBVARForecastStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
MSSBVARVarianceDecompositionStatement::MSSBVARVarianceDecompositionStatement(OptionsList options_list_arg) : MSSBVARVarianceDecompositionStatement::MSSBVARVarianceDecompositionStatement(
OptionsList options_list_arg) :
options_list {move(options_list_arg)} options_list {move(options_list_arg)}
{ {
} }
...@@ -2844,8 +2750,7 @@ MSSBVARVarianceDecompositionStatement::checkPass(ModFileStructure &mod_file_stru ...@@ -2844,8 +2750,7 @@ MSSBVARVarianceDecompositionStatement::checkPass(ModFileStructure &mod_file_stru
regimes_present = options_list.contains("ms.regimes"), regimes_present = options_list.contains("ms.regimes"),
filtered_probabilities_present = options_list.contains("ms.filtered_probabilities"); filtered_probabilities_present = options_list.contains("ms.filtered_probabilities");
(filtered_probabilities_present && regime_present) (filtered_probabilities_present && regime_present)
|| (filtered_probabilities_present && regimes_present) || (filtered_probabilities_present && regimes_present) || (regimes_present && regime_present))
|| (regimes_present && regime_present))
{ {
cerr << "ERROR: You may only pass one of regime, regimes and " cerr << "ERROR: You may only pass one of regime, regimes and "
<< "filtered_probabilities to ms_variance_decomposition" << endl; << "filtered_probabilities to ms_variance_decomposition" << endl;
...@@ -2875,13 +2780,14 @@ MSSBVARVarianceDecompositionStatement::writeJsonOutput(ostream &output) const ...@@ -2875,13 +2780,14 @@ MSSBVARVarianceDecompositionStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
IdentificationStatement::IdentificationStatement(OptionsList options_list_arg) IdentificationStatement::IdentificationStatement(OptionsList options_list_arg) :
: options_list{move(options_list_arg)} options_list {move(options_list_arg)}
{ {
if (auto opt = options_list.get_if<OptionsList::NumVal>("max_dim_cova_group"); if (auto opt = options_list.get_if<OptionsList::NumVal>("max_dim_cova_group");
opt && stoi(*opt) == 0) opt && stoi(*opt) == 0)
{ {
cerr << "ERROR: The max_dim_cova_group option to identification only accepts integers > 0." << endl; cerr << "ERROR: The max_dim_cova_group option to identification only accepts integers > 0."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -2897,14 +2803,16 @@ IdentificationStatement::checkPass(ModFileStructure &mod_file_struct, ...@@ -2897,14 +2803,16 @@ IdentificationStatement::checkPass(ModFileStructure &mod_file_struct,
int order = stoi(*opt); int order = stoi(*opt);
if (order < 1 || order > 3) if (order < 1 || order > 3)
{ {
cerr << "ERROR: the order option of identification command must be between 1 and 3" << endl; cerr << "ERROR: the order option of identification command must be between 1 and 3"
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
mod_file_struct.identification_order = max(mod_file_struct.identification_order, order); mod_file_struct.identification_order = max(mod_file_struct.identification_order, order);
} }
else else
// The default value for order is 1 (which triggers 2nd order dynamic derivatives, see preprocessor#40) // The default value for order is 1 (which triggers 2nd order dynamic derivatives, see
// preprocessor#40)
mod_file_struct.identification_order = max(mod_file_struct.identification_order, 1); mod_file_struct.identification_order = max(mod_file_struct.identification_order, 1);
} }
...@@ -2926,7 +2834,8 @@ IdentificationStatement::writeOutput(ostream &output, [[maybe_unused]] const str ...@@ -2926,7 +2834,8 @@ IdentificationStatement::writeOutput(ostream &output, [[maybe_unused]] const str
if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("graph_format")) if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("graph_format"))
opt->writeOutput("options_.graph_format", output); opt->writeOutput("options_.graph_format", output);
output << "dynare_identification(options_ident);" << endl; output << "identification.run(M_,oo_,options_,bayestopt_,estim_params_,"
<< "options_ident);" << endl;
} }
void void
...@@ -2941,14 +2850,15 @@ IdentificationStatement::writeJsonOutput(ostream &output) const ...@@ -2941,14 +2850,15 @@ IdentificationStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
WriteLatexDynamicModelStatement::WriteLatexDynamicModelStatement(const DynamicModel &dynamic_model_arg, bool write_equation_tags_arg) : WriteLatexDynamicModelStatement::WriteLatexDynamicModelStatement(
dynamic_model{dynamic_model_arg}, const DynamicModel& dynamic_model_arg, bool write_equation_tags_arg) :
write_equation_tags{write_equation_tags_arg} dynamic_model {dynamic_model_arg}, write_equation_tags {write_equation_tags_arg}
{ {
} }
void void
WriteLatexDynamicModelStatement::writeOutput([[maybe_unused]] ostream &output, const string &basename, WriteLatexDynamicModelStatement::writeOutput([[maybe_unused]] ostream& output,
const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
dynamic_model.writeLatexFile(basename, write_equation_tags); dynamic_model.writeLatexFile(basename, write_equation_tags);
...@@ -2960,14 +2870,15 @@ WriteLatexDynamicModelStatement::writeJsonOutput(ostream &output) const ...@@ -2960,14 +2870,15 @@ WriteLatexDynamicModelStatement::writeJsonOutput(ostream &output) const
output << R"({"statementName": "write_latex_dynamic_model"})"; output << R"({"statementName": "write_latex_dynamic_model"})";
} }
WriteLatexStaticModelStatement::WriteLatexStaticModelStatement(const StaticModel &static_model_arg, bool write_equation_tags_arg) : WriteLatexStaticModelStatement::WriteLatexStaticModelStatement(const StaticModel& static_model_arg,
static_model(static_model_arg), bool write_equation_tags_arg) :
write_equation_tags(write_equation_tags_arg) static_model(static_model_arg), write_equation_tags(write_equation_tags_arg)
{ {
} }
void void
WriteLatexStaticModelStatement::writeOutput([[maybe_unused]] ostream &output, const string &basename, WriteLatexStaticModelStatement::writeOutput([[maybe_unused]] ostream& output,
const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
static_model.writeLatexFile(basename, write_equation_tags); static_model.writeLatexFile(basename, write_equation_tags);
...@@ -2979,14 +2890,15 @@ WriteLatexStaticModelStatement::writeJsonOutput(ostream &output) const ...@@ -2979,14 +2890,15 @@ WriteLatexStaticModelStatement::writeJsonOutput(ostream &output) const
output << R"({"statementName": "write_latex_static_model"})"; output << R"({"statementName": "write_latex_static_model"})";
} }
WriteLatexOriginalModelStatement::WriteLatexOriginalModelStatement(const DynamicModel &original_model_arg, bool write_equation_tags_arg) : WriteLatexOriginalModelStatement::WriteLatexOriginalModelStatement(
original_model{original_model_arg}, const DynamicModel& original_model_arg, bool write_equation_tags_arg) :
write_equation_tags{write_equation_tags_arg} original_model {original_model_arg}, write_equation_tags {write_equation_tags_arg}
{ {
} }
void void
WriteLatexOriginalModelStatement::writeOutput([[maybe_unused]] ostream &output, const string &basename, WriteLatexOriginalModelStatement::writeOutput([[maybe_unused]] ostream& output,
const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
original_model.writeLatexOriginalFile(basename, write_equation_tags); original_model.writeLatexOriginalFile(basename, write_equation_tags);
...@@ -2998,7 +2910,8 @@ WriteLatexOriginalModelStatement::writeJsonOutput(ostream &output) const ...@@ -2998,7 +2910,8 @@ WriteLatexOriginalModelStatement::writeJsonOutput(ostream &output) const
output << R"({"statementName": "write_latex_original_model"})"; output << R"({"statementName": "write_latex_original_model"})";
} }
WriteLatexSteadyStateModelStatement::WriteLatexSteadyStateModelStatement(const SteadyStateModel &steady_state_model_arg) : WriteLatexSteadyStateModelStatement::WriteLatexSteadyStateModelStatement(
const SteadyStateModel& steady_state_model_arg) :
steady_state_model {steady_state_model_arg} steady_state_model {steady_state_model_arg}
{ {
} }
...@@ -3034,7 +2947,8 @@ ShockDecompositionStatement::ShockDecompositionStatement(SymbolList symbol_list_ ...@@ -3034,7 +2947,8 @@ ShockDecompositionStatement::ShockDecompositionStatement(SymbolList symbol_list_
} }
void void
ShockDecompositionStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) ShockDecompositionStatement::checkPass(ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{ {
if (auto opt = options_list.get_if<OptionsList::NumVal>("shock_decomp.with_epilogue"); if (auto opt = options_list.get_if<OptionsList::NumVal>("shock_decomp.with_epilogue");
opt && *opt == "true") opt && *opt == "true")
...@@ -3057,7 +2971,8 @@ ShockDecompositionStatement::writeOutput(ostream &output, [[maybe_unused]] const ...@@ -3057,7 +2971,8 @@ ShockDecompositionStatement::writeOutput(ostream &output, [[maybe_unused]] const
{ {
options_list.writeOutput(output); options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output); symbol_list.writeOutput("var_list_", output);
output << "oo_ = shock_decomposition(M_,oo_,options_,var_list_,bayestopt_,estim_params_);" << endl; output << "oo_ = shock_decomposition(M_,oo_,options_,var_list_,bayestopt_,estim_params_);"
<< endl;
} }
void void
...@@ -3077,9 +2992,8 @@ ShockDecompositionStatement::writeJsonOutput(ostream &output) const ...@@ -3077,9 +2992,8 @@ ShockDecompositionStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
RealtimeShockDecompositionStatement::RealtimeShockDecompositionStatement(SymbolList symbol_list_arg, RealtimeShockDecompositionStatement::RealtimeShockDecompositionStatement(
OptionsList options_list_arg, SymbolList symbol_list_arg, OptionsList options_list_arg, const SymbolTable& symbol_table_arg) :
const SymbolTable &symbol_table_arg) :
symbol_list {move(symbol_list_arg)}, symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)}, options_list {move(options_list_arg)},
symbol_table {symbol_table_arg} symbol_table {symbol_table_arg}
...@@ -3087,7 +3001,8 @@ RealtimeShockDecompositionStatement::RealtimeShockDecompositionStatement(SymbolL ...@@ -3087,7 +3001,8 @@ RealtimeShockDecompositionStatement::RealtimeShockDecompositionStatement(SymbolL
} }
void void
RealtimeShockDecompositionStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) RealtimeShockDecompositionStatement::checkPass(ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{ {
if (auto opt = options_list.get_if<OptionsList::NumVal>("shock_decomp.with_epilogue"); if (auto opt = options_list.get_if<OptionsList::NumVal>("shock_decomp.with_epilogue");
opt && *opt == "true") opt && *opt == "true")
...@@ -3111,7 +3026,9 @@ RealtimeShockDecompositionStatement::writeOutput(ostream &output, ...@@ -3111,7 +3026,9 @@ RealtimeShockDecompositionStatement::writeOutput(ostream &output,
{ {
options_list.writeOutput(output); options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output); symbol_list.writeOutput("var_list_", output);
output << "oo_ = realtime_shock_decomposition(M_,oo_,options_,var_list_,bayestopt_,estim_params_);" << endl; output
<< "oo_ = realtime_shock_decomposition(M_,oo_,options_,var_list_,bayestopt_,estim_params_);"
<< endl;
} }
void void
...@@ -3131,9 +3048,8 @@ RealtimeShockDecompositionStatement::writeJsonOutput(ostream &output) const ...@@ -3131,9 +3048,8 @@ RealtimeShockDecompositionStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
PlotShockDecompositionStatement::PlotShockDecompositionStatement(SymbolList symbol_list_arg, PlotShockDecompositionStatement::PlotShockDecompositionStatement(
OptionsList options_list_arg, SymbolList symbol_list_arg, OptionsList options_list_arg, const SymbolTable& symbol_table_arg) :
const SymbolTable &symbol_table_arg) :
symbol_list {move(symbol_list_arg)}, symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)}, options_list {move(options_list_arg)},
symbol_table {symbol_table_arg} symbol_table {symbol_table_arg}
...@@ -3156,7 +3072,8 @@ PlotShockDecompositionStatement::checkPass([[maybe_unused]] ModFileStructure &mo ...@@ -3156,7 +3072,8 @@ PlotShockDecompositionStatement::checkPass([[maybe_unused]] ModFileStructure &mo
} }
void void
PlotShockDecompositionStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename, PlotShockDecompositionStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
output << "options_ = set_default_plot_shock_decomposition_options(options_);" << endl; output << "options_ = set_default_plot_shock_decomposition_options(options_);" << endl;
...@@ -3182,9 +3099,8 @@ PlotShockDecompositionStatement::writeJsonOutput(ostream &output) const ...@@ -3182,9 +3099,8 @@ PlotShockDecompositionStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
InitialConditionDecompositionStatement::InitialConditionDecompositionStatement(SymbolList symbol_list_arg, InitialConditionDecompositionStatement::InitialConditionDecompositionStatement(
OptionsList options_list_arg, SymbolList symbol_list_arg, OptionsList options_list_arg, const SymbolTable& symbol_table_arg) :
const SymbolTable &symbol_table_arg) :
symbol_list {move(symbol_list_arg)}, symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)}, options_list {move(options_list_arg)},
symbol_table {symbol_table_arg} symbol_table {symbol_table_arg}
...@@ -3192,7 +3108,8 @@ InitialConditionDecompositionStatement::InitialConditionDecompositionStatement(S ...@@ -3192,7 +3108,8 @@ InitialConditionDecompositionStatement::InitialConditionDecompositionStatement(S
} }
void void
InitialConditionDecompositionStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) InitialConditionDecompositionStatement::checkPass(ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{ {
if (auto opt = options_list.get_if<OptionsList::NumVal>("initial_condition_decomp.with_epilogue"); if (auto opt = options_list.get_if<OptionsList::NumVal>("initial_condition_decomp.with_epilogue");
opt && *opt == "true") opt && *opt == "true")
...@@ -3217,7 +3134,9 @@ InitialConditionDecompositionStatement::writeOutput(ostream &output, ...@@ -3217,7 +3134,9 @@ InitialConditionDecompositionStatement::writeOutput(ostream &output,
output << "options_ = set_default_initial_condition_decomposition_options(options_);" << endl; output << "options_ = set_default_initial_condition_decomposition_options(options_);" << endl;
options_list.writeOutput(output); options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output); symbol_list.writeOutput("var_list_", output);
output << "oo_ = initial_condition_decomposition(M_, oo_, options_, var_list_, bayestopt_, estim_params_);" << endl; output << "oo_ = initial_condition_decomposition(M_, oo_, options_, var_list_, bayestopt_, "
"estim_params_);"
<< endl;
} }
void void
...@@ -3237,10 +3156,9 @@ InitialConditionDecompositionStatement::writeJsonOutput(ostream &output) const ...@@ -3237,10 +3156,9 @@ InitialConditionDecompositionStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
SqueezeShockDecompositionStatement::SqueezeShockDecompositionStatement(SymbolList symbol_list_arg, SqueezeShockDecompositionStatement::SqueezeShockDecompositionStatement(
const SymbolTable &symbol_table_arg) : SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg) :
symbol_list{move(symbol_list_arg)}, symbol_list {move(symbol_list_arg)}, symbol_table {symbol_table_arg}
symbol_table{symbol_table_arg}
{ {
} }
...@@ -3306,7 +3224,9 @@ ConditionalForecastStatement::writeOutput(ostream &output, [[maybe_unused]] cons ...@@ -3306,7 +3224,9 @@ ConditionalForecastStatement::writeOutput(ostream &output, [[maybe_unused]] cons
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output, "options_cond_fcst_"); options_list.writeOutput(output, "options_cond_fcst_");
output << "imcforecast(constrained_paths_, constrained_vars_, options_cond_fcst_);" << endl; output << "oo_.conditional_forecast=conditional_forecasts.run(M_,options_,"
<< "oo_,bayestopt_,estim_params_,constrained_paths_, constrained_vars_,"
<< "options_cond_fcst_);" << endl;
} }
void void
...@@ -3321,12 +3241,10 @@ ConditionalForecastStatement::writeJsonOutput(ostream &output) const ...@@ -3321,12 +3241,10 @@ ConditionalForecastStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
PlotConditionalForecastStatement::PlotConditionalForecastStatement(optional<int> periods_arg, PlotConditionalForecastStatement::PlotConditionalForecastStatement(
SymbolList symbol_list_arg, const optional<int>& periods_arg, SymbolList symbol_list_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
periods{move(periods_arg)}, periods {periods_arg}, symbol_list {move(symbol_list_arg)}, symbol_table {symbol_table_arg}
symbol_list{move(symbol_list_arg)},
symbol_table{symbol_table_arg}
{ {
} }
...@@ -3346,14 +3264,15 @@ PlotConditionalForecastStatement::checkPass([[maybe_unused]] ModFileStructure &m ...@@ -3346,14 +3264,15 @@ PlotConditionalForecastStatement::checkPass([[maybe_unused]] ModFileStructure &m
} }
void void
PlotConditionalForecastStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename, PlotConditionalForecastStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
symbol_list.writeOutput("var_list_", output); symbol_list.writeOutput("var_list_", output);
if (periods) if (periods)
output << "plot_icforecast(var_list_, " << *periods << ",options_,oo_);" << endl; output << "conditional_forecasts.plot(var_list_, " << *periods << ",options_,oo_);" << endl;
else else
output << "plot_icforecast(var_list_,[],options_,oo_);" << endl; output << "conditional_forecasts.plot(var_list_,[],options_,oo_);" << endl;
} }
void void
...@@ -3370,10 +3289,9 @@ PlotConditionalForecastStatement::writeJsonOutput(ostream &output) const ...@@ -3370,10 +3289,9 @@ PlotConditionalForecastStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
SvarIdentificationStatement::SvarIdentificationStatement(svar_identification_restrictions_t restrictions_arg, SvarIdentificationStatement::SvarIdentificationStatement(
bool upper_cholesky_present_arg, svar_identification_restrictions_t restrictions_arg, bool upper_cholesky_present_arg,
bool lower_cholesky_present_arg, bool lower_cholesky_present_arg, bool constants_exclusion_present_arg,
bool constants_exclusion_present_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
restrictions {move(restrictions_arg)}, restrictions {move(restrictions_arg)},
upper_cholesky_present {upper_cholesky_present_arg}, upper_cholesky_present {upper_cholesky_present_arg},
...@@ -3420,9 +3338,7 @@ SvarIdentificationStatement::writeOutput(ostream &output, [[maybe_unused]] const ...@@ -3420,9 +3338,7 @@ SvarIdentificationStatement::writeOutput(ostream &output, [[maybe_unused]] const
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
assert(!(upper_cholesky_present && lower_cholesky_present)); assert(!(upper_cholesky_present && lower_cholesky_present));
output << "%" << endl output << "%" << endl << "% SVAR IDENTIFICATION" << endl << "%" << endl;
<< "% SVAR IDENTIFICATION" << endl
<< "%" << endl;
if (upper_cholesky_present) if (upper_cholesky_present)
output << "options_.ms.upper_cholesky=1;" << endl; output << "options_.ms.upper_cholesky=1;" << endl;
...@@ -3442,8 +3358,7 @@ SvarIdentificationStatement::writeOutput(ostream &output, [[maybe_unused]] const ...@@ -3442,8 +3358,7 @@ SvarIdentificationStatement::writeOutput(ostream &output, [[maybe_unused]] const
if (k < 1) if (k < 1)
{ {
cerr << "ERROR: lag = " << r cerr << "ERROR: lag = " << r << ", number of endogenous variables = " << n
<< ", number of endogenous variables = " << n
<< ", number of exogenous variables = " << m << ", number of exogenous variables = " << m
<< ". If this is not a logical error in the specification" << ". If this is not a logical error in the specification"
<< " of the .mod file, please report it to the Dynare Team." << endl; << " of the .mod file, please report it to the Dynare Team." << endl;
...@@ -3451,8 +3366,10 @@ SvarIdentificationStatement::writeOutput(ostream &output, [[maybe_unused]] const ...@@ -3451,8 +3366,10 @@ SvarIdentificationStatement::writeOutput(ostream &output, [[maybe_unused]] const
} }
if (n < 1) if (n < 1)
{ {
cerr << "ERROR: Number of endogenous variables = " << n << "< 1. If this is not a logical " cerr
<< "error in the specification of the .mod file, please report it to the Dynare Team." << endl; << "ERROR: Number of endogenous variables = " << n << "< 1. If this is not a logical "
<< "error in the specification of the .mod file, please report it to the Dynare Team."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
output << "options_.ms.Qi = cell(" << n << ",1);" << endl output << "options_.ms.Qi = cell(" << n << ",1);" << endl
...@@ -3462,17 +3379,22 @@ SvarIdentificationStatement::writeOutput(ostream &output, [[maybe_unused]] const ...@@ -3462,17 +3379,22 @@ SvarIdentificationStatement::writeOutput(ostream &output, [[maybe_unused]] const
{ {
assert(it.lag >= 0); assert(it.lag >= 0);
if (it.lag == 0) if (it.lag == 0)
output << "options_.ms.Qi{" << it.equation << "}(" << it.restriction_nbr << ", " << it.variable + 1 << ") = "; output << "options_.ms.Qi{" << it.equation << "}(" << it.restriction_nbr << ", "
<< it.variable + 1 << ") = ";
else else
{ {
int col = (it.lag - 1) * n + it.variable + 1; int col = (it.lag - 1) * n + it.variable + 1;
if (col > k) if (col > k)
{ {
cerr << "ERROR: lag =" << it.lag << ", num endog vars = " << n << "current endog var index = " << it.variable << ". Index " cerr << "ERROR: lag =" << it.lag << ", num endog vars = " << n
<< "out of bounds. If the above does not represent a logical error, please report this to the Dynare Team." << endl; << "current endog var index = " << it.variable << ". Index "
<< "out of bounds. If the above does not represent a logical error, please "
"report this to the Dynare Team."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
output << "options_.ms.Ri{" << it.equation << "}(" << it.restriction_nbr << ", " << col << ") = "; output << "options_.ms.Ri{" << it.equation << "}(" << it.restriction_nbr << ", "
<< col << ") = ";
} }
it.value->writeOutput(output); it.value->writeOutput(output);
output << ";" << endl; output << ";" << endl;
...@@ -3497,11 +3419,9 @@ SvarIdentificationStatement::writeJsonOutput(ostream &output) const ...@@ -3497,11 +3419,9 @@ SvarIdentificationStatement::writeJsonOutput(ostream &output) const
if (!upper_cholesky_present && !lower_cholesky_present) if (!upper_cholesky_present && !lower_cholesky_present)
{ {
output << R"(, "nlags": )" << getMaxLag() output << R"(, "nlags": )" << getMaxLag() << R"(, "restrictions": [)";
<< R"(, "restrictions": [)";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& it : restrictions)
const auto &it : restrictions)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
...@@ -3529,7 +3449,8 @@ MarkovSwitchingStatement::MarkovSwitchingStatement(OptionsList options_list_arg) ...@@ -3529,7 +3449,8 @@ MarkovSwitchingStatement::MarkovSwitchingStatement(OptionsList options_list_arg)
{ {
if (restriction.size() != 3) if (restriction.size() != 3)
{ {
cerr << "ERROR: restrictions in the subsample statement must be specified in the form " cerr
<< "ERROR: restrictions in the subsample statement must be specified in the form "
<< "[current_period_regime, next_period_regime, transition_probability]" << endl; << "[current_period_regime, next_period_regime, transition_probability]" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -3541,7 +3462,8 @@ MarkovSwitchingStatement::MarkovSwitchingStatement(OptionsList options_list_arg) ...@@ -3541,7 +3462,8 @@ MarkovSwitchingStatement::MarkovSwitchingStatement(OptionsList options_list_arg)
if (from_regime > num_regimes || to_regime > num_regimes) if (from_regime > num_regimes || to_regime > num_regimes)
{ {
cerr << "ERROR: the regimes specified in the restrictions option must be " cerr << "ERROR: the regimes specified in the restrictions option must be "
<< "<= the number of regimes specified in the number_of_regimes option" << endl; << "<= the number of regimes specified in the number_of_regimes option"
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -3653,14 +3575,11 @@ MarkovSwitchingStatement::writeOutput(ostream &output, [[maybe_unused]] const st ...@@ -3653,14 +3575,11 @@ MarkovSwitchingStatement::writeOutput(ostream &output, [[maybe_unused]] const st
assert(options_list.contains("ms.duration")); assert(options_list.contains("ms.duration"));
output << "options_.ms.duration = "; output << "options_.ms.duration = ";
bool isDurationAVec { options_list.visit("ms.duration", bool isDurationAVec {options_list.visit("ms.duration", [&]<class T>(const T& v) -> bool {
[&]<class T>(const T &v) -> bool
{
if constexpr (is_same_v<T, OptionsList::VecValueVal>) if constexpr (is_same_v<T, OptionsList::VecValueVal>)
{ {
output << "["; output << "[";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& it : v)
const auto &it : v)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
...@@ -3676,7 +3595,9 @@ MarkovSwitchingStatement::writeOutput(ostream &output, [[maybe_unused]] const st ...@@ -3676,7 +3595,9 @@ MarkovSwitchingStatement::writeOutput(ostream &output, [[maybe_unused]] const st
} }
else else
{ {
cerr << "MarkovSwitchingStatement::writeOutput: incorrect value type for 'ms.duration' option" << endl; cerr << "MarkovSwitchingStatement::writeOutput: incorrect value type for 'ms.duration' "
"option"
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
})}; })};
...@@ -3685,18 +3606,16 @@ MarkovSwitchingStatement::writeOutput(ostream &output, [[maybe_unused]] const st ...@@ -3685,18 +3606,16 @@ MarkovSwitchingStatement::writeOutput(ostream &output, [[maybe_unused]] const st
int NOR {stoi(options_list.get<OptionsList::NumVal>("ms.number_of_regimes"))}; int NOR {stoi(options_list.get<OptionsList::NumVal>("ms.number_of_regimes"))};
for (int i {0}; i < NOR; i++) for (int i {0}; i < NOR; i++)
{ {
output << "options_.ms.ms_chain(" << chainNumber << ").regime(" output << "options_.ms.ms_chain(" << chainNumber << ").regime(" << i + 1
<< i+1 << ").duration = options_.ms.duration"; << ").duration = options_.ms.duration";
if (isDurationAVec) if (isDurationAVec)
output << "(" << i + 1 << ")"; output << "(" << i + 1 << ")";
output << ";" << endl; output << ";" << endl;
} }
for (int restrictions_index{0}; for (int restrictions_index {0}; const auto& [regimes, prob] : restriction_map)
const auto &[regimes, prob] : restriction_map) output << "options_.ms.ms_chain(" << chainNumber << ").restrictions(" << ++restrictions_index
output << "options_.ms.ms_chain(" << chainNumber << ").restrictions(" << ") = {[" << regimes.first << ", " << regimes.second << ", " << prob << "]};" << endl;
<< ++restrictions_index << ") = {[" << regimes.first << ", "
<< regimes.second << ", " << prob << "]};" << endl;
} }
void void
...@@ -3711,23 +3630,19 @@ MarkovSwitchingStatement::writeJsonOutput(ostream &output) const ...@@ -3711,23 +3630,19 @@ MarkovSwitchingStatement::writeJsonOutput(ostream &output) const
if (!restriction_map.empty()) if (!restriction_map.empty())
output << ", {"; output << ", {";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& [regimes, prob] : restriction_map)
const auto &[regimes, prob] : restriction_map)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
output << R"({"current_period_regime": )" << regimes.first output << R"({"current_period_regime": )" << regimes.first << R"(, "next_period_regime": )"
<< R"(, "next_period_regime": )" << regimes.second << regimes.second << R"(, "transition_probability": )" << prob << "}";
<< R"(, "transition_probability": )"<< prob
<< "}";
} }
if (!restriction_map.empty()) if (!restriction_map.empty())
output << "}"; output << "}";
output << "}"; output << "}";
} }
SvarStatement::SvarStatement(OptionsList options_list_arg) : SvarStatement::SvarStatement(OptionsList options_list_arg) : options_list {move(options_list_arg)}
options_list{move(options_list_arg)}
{ {
} }
...@@ -3800,8 +3715,7 @@ SvarGlobalIdentificationCheckStatement::writeJsonOutput(ostream &output) const ...@@ -3800,8 +3715,7 @@ SvarGlobalIdentificationCheckStatement::writeJsonOutput(ostream &output) const
output << R"({"statementName": "svar_global_identification"})"; output << R"({"statementName": "svar_global_identification"})";
} }
SetTimeStatement::SetTimeStatement(OptionsList options_list_arg) : SetTimeStatement::SetTimeStatement(string period_arg) : period {move(period_arg)}
options_list{move(options_list_arg)}
{ {
} }
...@@ -3809,19 +3723,13 @@ void ...@@ -3809,19 +3723,13 @@ void
SetTimeStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename, SetTimeStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output); output << "options_.initial_period = " << period << endl;
} }
void void
SetTimeStatement::writeJsonOutput(ostream& output) const SetTimeStatement::writeJsonOutput(ostream& output) const
{ {
output << R"({"statementName": "set_time")"; output << R"({"statementName": "set_time", "period": ")" << period << R"("})";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
} }
EstimationDataStatement::EstimationDataStatement(OptionsList options_list_arg) : EstimationDataStatement::EstimationDataStatement(OptionsList options_list_arg) :
...@@ -3838,12 +3746,12 @@ EstimationDataStatement::checkPass(ModFileStructure &mod_file_struct, ...@@ -3838,12 +3746,12 @@ EstimationDataStatement::checkPass(ModFileStructure &mod_file_struct,
if (auto opt = options_list.get_if<OptionsList::NumVal>("nobs")) if (auto opt = options_list.get_if<OptionsList::NumVal>("nobs"))
if (stoi(*opt) <= 0) if (stoi(*opt) <= 0)
{ {
cerr << "ERROR: The nobs option of the data statement only accepts positive integers." << endl; cerr << "ERROR: The nobs option of the data statement only accepts positive integers."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
bool has_file = options_list.contains("file"), bool has_file = options_list.contains("file"), has_series = options_list.contains("series");
has_series = options_list.contains("series");
if (!has_file && !has_series) if (!has_file && !has_series)
{ {
cerr << "ERROR: The file or series option must be passed to the data statement." << endl; cerr << "ERROR: The file or series option must be passed to the data statement." << endl;
...@@ -3851,7 +3759,9 @@ EstimationDataStatement::checkPass(ModFileStructure &mod_file_struct, ...@@ -3851,7 +3759,9 @@ EstimationDataStatement::checkPass(ModFileStructure &mod_file_struct,
} }
if (has_file && has_series) if (has_file && has_series)
{ {
cerr << "ERROR: The file and series options cannot be used simultaneously in the data statement." << endl; cerr << "ERROR: The file and series options cannot be used simultaneously in the data "
"statement."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -3875,8 +3785,7 @@ EstimationDataStatement::writeJsonOutput(ostream &output) const ...@@ -3875,8 +3785,7 @@ EstimationDataStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
SubsamplesStatement::SubsamplesStatement(string name1_arg, SubsamplesStatement::SubsamplesStatement(string name1_arg, string name2_arg,
string name2_arg,
subsample_declaration_map_t subsample_declaration_map_arg, subsample_declaration_map_t subsample_declaration_map_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
name1 {move(name1_arg)}, name1 {move(name1_arg)},
...@@ -3887,12 +3796,11 @@ SubsamplesStatement::SubsamplesStatement(string name1_arg, ...@@ -3887,12 +3796,11 @@ SubsamplesStatement::SubsamplesStatement(string name1_arg,
} }
void void
SubsamplesStatement::writeOutput(ostream &output, SubsamplesStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] const string &basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
output << "subsamples_indx = get_new_or_existing_ei_index('subsamples_index', '" output << "subsamples_indx = get_new_or_existing_ei_index('subsamples_index', '" << name1 << "','"
<< name1 << "','" << name2 << "');" << endl << name2 << "');" << endl
<< "estimation_info.subsamples_index(subsamples_indx) = {'" << name1; << "estimation_info.subsamples_index(subsamples_indx) = {'" << name1;
if (!name2.empty()) if (!name2.empty())
output << ":" << name2; output << ":" << name2;
...@@ -3900,15 +3808,14 @@ SubsamplesStatement::writeOutput(ostream &output, ...@@ -3900,15 +3808,14 @@ SubsamplesStatement::writeOutput(ostream &output,
<< "estimation_info.subsamples(subsamples_indx).range = {};" << endl << "estimation_info.subsamples(subsamples_indx).range = {};" << endl
<< "estimation_info.subsamples(subsamples_indx).range_index = {};" << endl; << "estimation_info.subsamples(subsamples_indx).range_index = {};" << endl;
for (int map_indx{1}; for (int map_indx {1}; const auto& [range, dates] : subsample_declaration_map)
const auto &[range, dates] : subsample_declaration_map)
{ {
output << "estimation_info.subsamples(subsamples_indx).range_index(" << map_indx << ") = {'" output << "estimation_info.subsamples(subsamples_indx).range_index(" << map_indx << ") = {'"
<< range << "'};" << endl << range << "'};" << endl
<< "estimation_info.subsamples(subsamples_indx).range(" << map_indx << ").date1 = " << "estimation_info.subsamples(subsamples_indx).range(" << map_indx
<< dates.first << ";" << endl << ").date1 = " << dates.first << ";" << endl
<< "estimation_info.subsamples(subsamples_indx).range(" << map_indx << ").date2 = " << "estimation_info.subsamples(subsamples_indx).range(" << map_indx
<< dates.second << ";" << endl; << ").date2 = " << dates.second << ";" << endl;
map_indx++; map_indx++;
} }
...@@ -3935,8 +3842,7 @@ SubsamplesStatement::writeOutput(ostream &output, ...@@ -3935,8 +3842,7 @@ SubsamplesStatement::writeOutput(ostream &output,
if (!name2.empty()) if (!name2.empty())
output << "_corr"; output << "_corr";
output << "_prior_index', '" output << "_prior_index', '" << name1 << "', '";
<< name1 << "', '";
if (!name2.empty()) if (!name2.empty())
output << name2; output << name2;
output << "');" << endl; output << "');" << endl;
...@@ -3952,7 +3858,8 @@ SubsamplesStatement::writeOutput(ostream &output, ...@@ -3952,7 +3858,8 @@ SubsamplesStatement::writeOutput(ostream &output,
output << lhs_field << "(eifind).subsample_prior = estimation_info.empty_prior;" << endl output << lhs_field << "(eifind).subsample_prior = estimation_info.empty_prior;" << endl
<< lhs_field << "(eifind).subsample_prior(1:" << subsample_declaration_map.size() << lhs_field << "(eifind).subsample_prior(1:" << subsample_declaration_map.size()
<< ") = estimation_info.empty_prior;" << endl << ") = estimation_info.empty_prior;" << endl
<< lhs_field << "(eifind).range_index = estimation_info.subsamples(subsamples_indx).range_index;" << lhs_field
<< "(eifind).range_index = estimation_info.subsamples(subsamples_indx).range_index;"
<< endl; << endl;
} }
...@@ -3965,8 +3872,7 @@ SubsamplesStatement::writeJsonOutput(ostream &output) const ...@@ -3965,8 +3872,7 @@ SubsamplesStatement::writeJsonOutput(ostream &output) const
output << R"(, "name2": ")" << name2 << R"(")"; output << R"(, "name2": ")" << name2 << R"(")";
output << R"(, "declarations": {)"; output << R"(, "declarations": {)";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& [range, dates] : subsample_declaration_map)
const auto &[range, dates] : subsample_declaration_map)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ","; output << ",";
...@@ -3980,10 +3886,8 @@ SubsamplesStatement::writeJsonOutput(ostream &output) const ...@@ -3980,10 +3886,8 @@ SubsamplesStatement::writeJsonOutput(ostream &output) const
<< "}"; << "}";
} }
SubsamplesEqualStatement::SubsamplesEqualStatement(string to_name1_arg, SubsamplesEqualStatement::SubsamplesEqualStatement(string to_name1_arg, string to_name2_arg,
string to_name2_arg, string from_name1_arg, string from_name2_arg,
string from_name1_arg,
string from_name2_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
to_name1 {move(to_name1_arg)}, to_name1 {move(to_name1_arg)},
to_name2 {move(to_name2_arg)}, to_name2 {move(to_name2_arg)},
...@@ -3997,15 +3901,16 @@ void ...@@ -3997,15 +3901,16 @@ void
SubsamplesEqualStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename, SubsamplesEqualStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
output << "subsamples_to_indx = get_new_or_existing_ei_index('subsamples_index', '" output << "subsamples_to_indx = get_new_or_existing_ei_index('subsamples_index', '" << to_name1
<< to_name1 << "','" << to_name2 << "');" << endl << "','" << to_name2 << "');" << endl
<< "estimation_info.subsamples_index(subsamples_to_indx) = {'" << to_name1; << "estimation_info.subsamples_index(subsamples_to_indx) = {'" << to_name1;
if (!to_name2.empty()) if (!to_name2.empty())
output << ":" << to_name2; output << ":" << to_name2;
output << "'};" << endl output << "'};" << endl
<< "subsamples_from_indx = get_existing_subsamples_indx('" << from_name1 << "','" << from_name2 << "');" << "subsamples_from_indx = get_existing_subsamples_indx('" << from_name1 << "','"
<< endl << from_name2 << "');" << endl
<< "estimation_info.subsamples(subsamples_to_indx) = estimation_info.subsamples(subsamples_from_indx);" << "estimation_info.subsamples(subsamples_to_indx) = "
"estimation_info.subsamples(subsamples_from_indx);"
<< endl; << endl;
// Initialize associated subsample substructures in estimation_info // Initialize associated subsample substructures in estimation_info
...@@ -4031,8 +3936,7 @@ SubsamplesEqualStatement::writeOutput(ostream &output, [[maybe_unused]] const st ...@@ -4031,8 +3936,7 @@ SubsamplesEqualStatement::writeOutput(ostream &output, [[maybe_unused]] const st
if (!to_name2.empty()) if (!to_name2.empty())
output << "_corr"; output << "_corr";
output << "_prior_index', '" output << "_prior_index', '" << to_name1 << "', '";
<< to_name1 << "', '";
if (!to_name2.empty()) if (!to_name2.empty())
output << to_name2; output << to_name2;
output << "');" << endl; output << "');" << endl;
...@@ -4046,9 +3950,12 @@ SubsamplesEqualStatement::writeOutput(ostream &output, [[maybe_unused]] const st ...@@ -4046,9 +3950,12 @@ SubsamplesEqualStatement::writeOutput(ostream &output, [[maybe_unused]] const st
output << "'};" << endl; output << "'};" << endl;
output << lhs_field << "(eifind).subsample_prior = estimation_info.empty_prior;" << endl output << lhs_field << "(eifind).subsample_prior = estimation_info.empty_prior;" << endl
<< lhs_field << "(eifind).subsample_prior(1:size(estimation_info.subsamples(subsamples_to_indx).range_index,2)) = estimation_info.empty_prior;" << lhs_field
<< "(eifind).subsample_prior(1:size(estimation_info.subsamples(subsamples_to_indx).range_"
"index,2)) = estimation_info.empty_prior;"
<< endl << endl
<< lhs_field << "(eifind).range_index = estimation_info.subsamples(subsamples_to_indx).range_index;" << lhs_field
<< "(eifind).range_index = estimation_info.subsamples(subsamples_to_indx).range_index;"
<< endl; << endl;
} }
...@@ -4096,8 +4003,7 @@ JointPriorStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struc ...@@ -4096,8 +4003,7 @@ JointPriorStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struc
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (auto opt = options_list.get_if<OptionsList::VecValueVal>("domain"); if (auto opt = options_list.get_if<OptionsList::VecValueVal>("domain"); opt && opt->size() != 4)
opt && opt->size() != 4)
{ {
cerr << "ERROR: You must pass exactly four values to the domain option." << endl; cerr << "ERROR: You must pass exactly four values to the domain option." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -4111,12 +4017,14 @@ JointPriorStatement::writeOutput(ostream &output, [[maybe_unused]] const string ...@@ -4111,12 +4017,14 @@ JointPriorStatement::writeOutput(ostream &output, [[maybe_unused]] const string
for (const auto& joint_parameter : joint_parameters) for (const auto& joint_parameter : joint_parameters)
output << "eifind = get_new_or_existing_ei_index('joint_parameter_prior_index', '" output << "eifind = get_new_or_existing_ei_index('joint_parameter_prior_index', '"
<< joint_parameter << "', '');" << endl << joint_parameter << "', '');" << endl
<< "estimation_info.joint_parameter_prior_index(eifind) = {'" << joint_parameter << "'};" << endl; << "estimation_info.joint_parameter_prior_index(eifind) = {'" << joint_parameter << "'};"
<< endl;
output << "key = {["; output << "key = {[";
for (const auto& joint_parameter : joint_parameters) for (const auto& joint_parameter : joint_parameters)
output << "get_new_or_existing_ei_index('joint_parameter_prior_index', '" << joint_parameter << "', '') ..." output << "get_new_or_existing_ei_index('joint_parameter_prior_index', '" << joint_parameter
<< endl << " "; << "', '') ..." << endl
<< " ";
output << "]};" << endl; output << "]};" << endl;
string lhs_field("estimation_info.joint_parameter_tmp"); string lhs_field("estimation_info.joint_parameter_tmp");
...@@ -4146,24 +4054,25 @@ JointPriorStatement::writeOutput(ostream &output, [[maybe_unused]] const string ...@@ -4146,24 +4054,25 @@ JointPriorStatement::writeOutput(ostream &output, [[maybe_unused]] const string
<< " " << lhs_field << ".stdev , ..." << endl << " " << lhs_field << ".stdev , ..." << endl
<< " " << lhs_field << ".truncate , ..." << endl << " " << lhs_field << ".truncate , ..." << endl
<< " " << lhs_field << ".variance];" << endl << " " << lhs_field << ".variance];" << endl
<< "estimation_info.joint_parameter = [estimation_info.joint_parameter; estimation_info.joint_parameter_tmp];" << endl << "estimation_info.joint_parameter = [estimation_info.joint_parameter; "
"estimation_info.joint_parameter_tmp];"
<< endl
<< "estimation_info=rmfield(estimation_info, 'joint_parameter_tmp');" << endl; << "estimation_info=rmfield(estimation_info, 'joint_parameter_tmp');" << endl;
} }
void void
JointPriorStatement::writeOutputHelper(ostream &output, const string &field, const string &lhs_field) const JointPriorStatement::writeOutputHelper(ostream& output, const string& field,
const string& lhs_field) const
{ {
output << lhs_field << "." << field << " = {"; output << lhs_field << "." << field << " = {";
if (options_list.contains(field)) if (options_list.contains(field))
options_list.visit(field, [&]<class T>(const T &v) options_list.visit(field, [&]<class T>(const T& v) {
{
if constexpr (is_same_v<T, OptionsList::NumVal>) if constexpr (is_same_v<T, OptionsList::NumVal>)
output << v; output << v;
else if constexpr (is_same_v<T, OptionsList::VecValueVal>) else if constexpr (is_same_v<T, OptionsList::VecValueVal>)
{ {
output << "["; output << "[";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& it2 : v)
const auto &it2 : v)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
...@@ -4174,14 +4083,12 @@ JointPriorStatement::writeOutputHelper(ostream &output, const string &field, con ...@@ -4174,14 +4083,12 @@ JointPriorStatement::writeOutputHelper(ostream &output, const string &field, con
else if constexpr (is_same_v<T, vector<vector<string>>>) else if constexpr (is_same_v<T, vector<vector<string>>>)
{ {
output << "{"; output << "{";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& it2 : v)
const auto &it2 : v)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
output << "["; output << "[";
for (bool printed_something2{false}; for (bool printed_something2 {false}; const auto& it3 : it2)
const auto &it3 : it2)
{ {
if (exchange(printed_something2, true)) if (exchange(printed_something2, true))
output << ", "; output << ", ";
...@@ -4207,8 +4114,7 @@ JointPriorStatement::writeJsonOutput(ostream &output) const ...@@ -4207,8 +4114,7 @@ JointPriorStatement::writeJsonOutput(ostream &output) const
{ {
output << R"({"statementName": "joint_prior")" output << R"({"statementName": "joint_prior")"
<< R"(, "key": [)"; << R"(, "key": [)";
for (bool printed_something{false}; for (bool printed_something {false}; const auto& it : joint_parameters)
const auto &it : joint_parameters)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
...@@ -4256,10 +4162,8 @@ JointPriorStatement::writeJsonOutput(ostream &output) const ...@@ -4256,10 +4162,8 @@ JointPriorStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
BasicPriorStatement::BasicPriorStatement(string name_arg, BasicPriorStatement::BasicPriorStatement(string name_arg, string subsample_name_arg,
string subsample_name_arg, PriorDistributions prior_shape_arg, expr_t variance_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg) : OptionsList options_list_arg) :
name {move(name_arg)}, name {move(name_arg)},
subsample_name {move(subsample_name_arg)}, subsample_name {move(subsample_name_arg)},
...@@ -4288,12 +4192,12 @@ BasicPriorStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struc ...@@ -4288,12 +4192,12 @@ BasicPriorStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struc
if (bool has_stdev = options_list.contains("stdev"); if (bool has_stdev = options_list.contains("stdev");
(!has_stdev && !variance) || (has_stdev && variance)) (!has_stdev && !variance) || (has_stdev && variance))
{ {
cerr << "ERROR: You must pass exactly one of stdev and variance to the prior statement." << endl; cerr << "ERROR: You must pass exactly one of stdev and variance to the prior statement."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (auto opt = options_list.get_if<OptionsList::VecValueVal>("domain"); if (auto opt = options_list.get_if<OptionsList::VecValueVal>("domain"); opt && opt->size() != 2)
opt && opt->size() != 2)
{ {
cerr << "ERROR: You must pass exactly two values to the domain option." << endl; cerr << "ERROR: You must pass exactly two values to the domain option." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -4303,18 +4207,13 @@ BasicPriorStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struc ...@@ -4303,18 +4207,13 @@ BasicPriorStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struc
bool bool
BasicPriorStatement::is_structural_innovation(const SymbolType symb_type) const BasicPriorStatement::is_structural_innovation(const SymbolType symb_type) const
{ {
if (symb_type == SymbolType::exogenous) return symb_type == SymbolType::exogenous;
return true;
return false;
} }
void void
BasicPriorStatement::get_base_name(const SymbolType symb_type, string& lhs_field) const BasicPriorStatement::get_base_name(const SymbolType symb_type, string& lhs_field) const
{ {
if (symb_type == SymbolType::exogenous) lhs_field = (symb_type == SymbolType::exogenous ? "structural_innovation" : "measurement_error");
lhs_field = "structural_innovation";
else
lhs_field = "measurement_error";
} }
void void
...@@ -4344,11 +4243,11 @@ BasicPriorStatement::writeCommonOutput(ostream &output, const string &lhs_field) ...@@ -4344,11 +4243,11 @@ BasicPriorStatement::writeCommonOutput(ostream &output, const string &lhs_field)
} }
void void
BasicPriorStatement::writeCommonOutputHelper(ostream &output, const string &field, const string &lhs_field) const BasicPriorStatement::writeCommonOutputHelper(ostream& output, const string& field,
const string& lhs_field) const
{ {
if (options_list.contains(field)) if (options_list.contains(field))
options_list.visit(field, [&]<class T>(const T &v) options_list.visit(field, [&]<class T>(const T& v) {
{
if constexpr (is_same_v<T, OptionsList::NumVal>) if constexpr (is_same_v<T, OptionsList::NumVal>)
output << lhs_field << "." << field << " = " << v << ";" << endl; output << lhs_field << "." << field << " = " << v << ";" << endl;
// TODO: handle other variant types // TODO: handle other variant types
...@@ -4362,8 +4261,10 @@ BasicPriorStatement::writePriorOutput(ostream &output, string &lhs_field, const ...@@ -4362,8 +4261,10 @@ BasicPriorStatement::writePriorOutput(ostream &output, string &lhs_field, const
lhs_field += ".prior(1)"; lhs_field += ".prior(1)";
else else
{ {
output << "subsamples_indx = get_existing_subsamples_indx('" << name << "','" << name2 << "');" << endl output << "subsamples_indx = get_existing_subsamples_indx('" << name << "','" << name2
<< "eisind = get_subsamples_range_indx(subsamples_indx, '" << subsample_name << "');" << endl; << "');" << endl
<< "eisind = get_subsamples_range_indx(subsamples_indx, '" << subsample_name << "');"
<< endl;
lhs_field += ".subsample_prior(eisind)"; lhs_field += ".subsample_prior(eisind)";
} }
writeCommonOutput(output, lhs_field); writeCommonOutput(output, lhs_field);
...@@ -4424,12 +4325,11 @@ BasicPriorStatement::writeJsonShape(ostream &output) const ...@@ -4424,12 +4325,11 @@ BasicPriorStatement::writeJsonShape(ostream &output) const
} }
} }
PriorStatement::PriorStatement(string name_arg, PriorStatement::PriorStatement(string name_arg, string subsample_name_arg,
string subsample_name_arg, PriorDistributions prior_shape_arg, expr_t variance_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg) : OptionsList options_list_arg) :
BasicPriorStatement{move(name_arg), move(subsample_name_arg), prior_shape_arg, variance_arg, move(options_list_arg)} BasicPriorStatement {move(name_arg), move(subsample_name_arg), prior_shape_arg, variance_arg,
move(options_list_arg)}
{ {
} }
...@@ -4438,8 +4338,8 @@ PriorStatement::writeOutput(ostream &output, [[maybe_unused]] const string &base ...@@ -4438,8 +4338,8 @@ PriorStatement::writeOutput(ostream &output, [[maybe_unused]] const string &base
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
string lhs_field = "estimation_info.parameter(eifind)"; string lhs_field = "estimation_info.parameter(eifind)";
output << "eifind = get_new_or_existing_ei_index('parameter_prior_index', '" output << "eifind = get_new_or_existing_ei_index('parameter_prior_index', '" << name << "', '');"
<< name << "', '');" << endl << endl
<< "estimation_info.parameter_prior_index(eifind) = {'" << name << "'};" << endl; << "estimation_info.parameter_prior_index(eifind) = {'" << name << "'};" << endl;
writePriorOutput(output, lhs_field, ""); writePriorOutput(output, lhs_field, "");
} }
...@@ -4452,13 +4352,12 @@ PriorStatement::writeJsonOutput(ostream &output) const ...@@ -4452,13 +4352,12 @@ PriorStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
StdPriorStatement::StdPriorStatement(string name_arg, StdPriorStatement::StdPriorStatement(string name_arg, string subsample_name_arg,
string subsample_name_arg, PriorDistributions prior_shape_arg, expr_t variance_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
BasicPriorStatement{move(name_arg), move(subsample_name_arg), prior_shape_arg, variance_arg, move(options_list_arg)}, BasicPriorStatement {move(name_arg), move(subsample_name_arg), prior_shape_arg, variance_arg,
move(options_list_arg)},
symbol_table {symbol_table_arg} symbol_table {symbol_table_arg}
{ {
} }
...@@ -4469,8 +4368,8 @@ StdPriorStatement::writeOutput(ostream &output, [[maybe_unused]] const string &b ...@@ -4469,8 +4368,8 @@ StdPriorStatement::writeOutput(ostream &output, [[maybe_unused]] const string &b
{ {
string lhs_field; string lhs_field;
get_base_name(symbol_table.getType(name), lhs_field); get_base_name(symbol_table.getType(name), lhs_field);
output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_prior_index', '" output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_prior_index', '" << name
<< name << "', '');" << endl << "', '');" << endl
<< "estimation_info." << lhs_field << "_prior_index(eifind) = {'" << name << "'};" << endl; << "estimation_info." << lhs_field << "_prior_index(eifind) = {'" << name << "'};" << endl;
lhs_field = "estimation_info." + lhs_field + "(eifind)"; lhs_field = "estimation_info." + lhs_field + "(eifind)";
...@@ -4487,11 +4386,11 @@ StdPriorStatement::writeJsonOutput(ostream &output) const ...@@ -4487,11 +4386,11 @@ StdPriorStatement::writeJsonOutput(ostream &output) const
CorrPriorStatement::CorrPriorStatement(string name_arg1, string name_arg2, CorrPriorStatement::CorrPriorStatement(string name_arg1, string name_arg2,
string subsample_name_arg, string subsample_name_arg,
PriorDistributions prior_shape_arg, PriorDistributions prior_shape_arg, expr_t variance_arg,
expr_t variance_arg,
OptionsList options_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
BasicPriorStatement{move(name_arg1), move(subsample_name_arg), prior_shape_arg, variance_arg, move(options_list_arg)}, BasicPriorStatement {move(name_arg1), move(subsample_name_arg), prior_shape_arg, variance_arg,
move(options_list_arg)},
name1 {move(name_arg2)}, name1 {move(name_arg2)},
symbol_table {symbol_table_arg} symbol_table {symbol_table_arg}
{ {
...@@ -4519,8 +4418,8 @@ CorrPriorStatement::writeOutput(ostream &output, [[maybe_unused]] const string & ...@@ -4519,8 +4418,8 @@ CorrPriorStatement::writeOutput(ostream &output, [[maybe_unused]] const string &
output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_corr_prior_index', '" output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_corr_prior_index', '"
<< name << "', '" << name1 << "');" << endl << name << "', '" << name1 << "');" << endl
<< "estimation_info." << lhs_field << "_corr_prior_index(eifind) = {'" << "estimation_info." << lhs_field << "_corr_prior_index(eifind) = {'" << name << ":"
<< name << ":" << name1 << "'};" << endl; << name1 << "'};" << endl;
lhs_field = "estimation_info." + lhs_field + "_corr(eifind)"; lhs_field = "estimation_info." + lhs_field + "_corr(eifind)";
writePriorOutput(output, lhs_field, name1); writePriorOutput(output, lhs_field, name1);
...@@ -4535,14 +4434,10 @@ CorrPriorStatement::writeJsonOutput(ostream &output) const ...@@ -4535,14 +4434,10 @@ CorrPriorStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
PriorEqualStatement::PriorEqualStatement(string to_declaration_type_arg, PriorEqualStatement::PriorEqualStatement(string to_declaration_type_arg, string to_name1_arg,
string to_name1_arg, string to_name2_arg, string to_subsample_name_arg,
string to_name2_arg, string from_declaration_type_arg, string from_name1_arg,
string to_subsample_name_arg, string from_name2_arg, string from_subsample_name_arg,
string from_declaration_type_arg,
string from_name1_arg,
string from_name2_arg,
string from_subsample_name_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
to_declaration_type {move(to_declaration_type_arg)}, to_declaration_type {move(to_declaration_type_arg)},
to_name1 {move(to_name1_arg)}, to_name1 {move(to_name1_arg)},
...@@ -4560,8 +4455,10 @@ void ...@@ -4560,8 +4455,10 @@ void
PriorEqualStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct, PriorEqualStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings) [[maybe_unused]] WarningConsolidation& warnings)
{ {
if ((to_declaration_type != "par" && to_declaration_type != "std" && to_declaration_type != "corr") if ((to_declaration_type != "par" && to_declaration_type != "std"
|| (from_declaration_type != "par" && from_declaration_type != "std" && from_declaration_type != "corr")) && to_declaration_type != "corr")
|| (from_declaration_type != "par" && from_declaration_type != "std"
&& from_declaration_type != "corr"))
{ {
cerr << "Internal Dynare Error" << endl; cerr << "Internal Dynare Error" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -4622,8 +4519,10 @@ PriorEqualStatement::writeOutput(ostream &output, [[maybe_unused]] const string ...@@ -4622,8 +4519,10 @@ PriorEqualStatement::writeOutput(ostream &output, [[maybe_unused]] const string
lhs_field += ".prior"; lhs_field += ".prior";
else else
{ {
output << "subsamples_to_indx = get_existing_subsamples_indx('" << to_name1 << "','" << to_name2 << "');" << endl output << "subsamples_to_indx = get_existing_subsamples_indx('" << to_name1 << "','"
<< "ei_to_ss_ind = get_subsamples_range_indx(subsamples_to_indx, '" << to_subsample_name << "');" << endl; << to_name2 << "');" << endl
<< "ei_to_ss_ind = get_subsamples_range_indx(subsamples_to_indx, '"
<< to_subsample_name << "');" << endl;
lhs_field += ".subsample_prior(ei_to_ss_ind)"; lhs_field += ".subsample_prior(ei_to_ss_ind)";
} }
...@@ -4631,8 +4530,10 @@ PriorEqualStatement::writeOutput(ostream &output, [[maybe_unused]] const string ...@@ -4631,8 +4530,10 @@ PriorEqualStatement::writeOutput(ostream &output, [[maybe_unused]] const string
rhs_field += ".prior"; rhs_field += ".prior";
else else
{ {
output << "subsamples_from_indx = get_existing_subsamples_indx('" << from_name1 << "','" << from_name2 << "');" << endl output << "subsamples_from_indx = get_existing_subsamples_indx('" << from_name1 << "','"
<< "ei_from_ss_ind = get_subsamples_range_indx(subsamples_from_indx, '" << from_subsample_name << "');" << endl; << from_name2 << "');" << endl
<< "ei_from_ss_ind = get_subsamples_range_indx(subsamples_from_indx, '"
<< from_subsample_name << "');" << endl;
rhs_field += ".subsample_prior(ei_from_ss_ind)"; rhs_field += ".subsample_prior(ei_from_ss_ind)";
} }
...@@ -4654,8 +4555,7 @@ PriorEqualStatement::writeJsonOutput(ostream &output) const ...@@ -4654,8 +4555,7 @@ PriorEqualStatement::writeJsonOutput(ostream &output) const
<< "}"; << "}";
} }
BasicOptionsStatement::BasicOptionsStatement(string name_arg, BasicOptionsStatement::BasicOptionsStatement(string name_arg, string subsample_name_arg,
string subsample_name_arg,
OptionsList options_list_arg) : OptionsList options_list_arg) :
name {move(name_arg)}, name {move(name_arg)},
subsample_name {move(subsample_name_arg)}, subsample_name {move(subsample_name_arg)},
...@@ -4672,10 +4572,7 @@ BasicOptionsStatement::is_structural_innovation(const SymbolType symb_type) cons ...@@ -4672,10 +4572,7 @@ BasicOptionsStatement::is_structural_innovation(const SymbolType symb_type) cons
void void
BasicOptionsStatement::get_base_name(const SymbolType symb_type, string& lhs_field) const BasicOptionsStatement::get_base_name(const SymbolType symb_type, string& lhs_field) const
{ {
if (symb_type == SymbolType::exogenous) lhs_field = (symb_type == SymbolType::exogenous ? "structural_innovation" : "measurement_error");
lhs_field = "structural_innovation";
else
lhs_field = "measurement_error";
} }
void void
...@@ -4689,11 +4586,11 @@ BasicOptionsStatement::writeCommonOutput(ostream &output, const string &lhs_fiel ...@@ -4689,11 +4586,11 @@ BasicOptionsStatement::writeCommonOutput(ostream &output, const string &lhs_fiel
} }
void void
BasicOptionsStatement::writeCommonOutputHelper(ostream &output, const string &field, const string &lhs_field) const BasicOptionsStatement::writeCommonOutputHelper(ostream& output, const string& field,
const string& lhs_field) const
{ {
if (options_list.contains(field)) if (options_list.contains(field))
options_list.visit(field, [&]<class T>(const T &v) options_list.visit(field, [&]<class T>(const T& v) {
{
if constexpr (is_same_v<T, OptionsList::NumVal>) if constexpr (is_same_v<T, OptionsList::NumVal>)
output << lhs_field << "." << field << " = " << v << ";" << endl; output << lhs_field << "." << field << " = " << v << ";" << endl;
// TODO: handle other variant types // TODO: handle other variant types
...@@ -4701,14 +4598,17 @@ BasicOptionsStatement::writeCommonOutputHelper(ostream &output, const string &fi ...@@ -4701,14 +4598,17 @@ BasicOptionsStatement::writeCommonOutputHelper(ostream &output, const string &fi
} }
void void
BasicOptionsStatement::writeOptionsOutput(ostream &output, string &lhs_field, const string &name2) const BasicOptionsStatement::writeOptionsOutput(ostream& output, string& lhs_field,
const string& name2) const
{ {
if (subsample_name.empty()) if (subsample_name.empty())
lhs_field += ".options(1)"; lhs_field += ".options(1)";
else else
{ {
output << "subsamples_indx = get_existing_subsamples_indx('" << name << "','" << name2 << "');" << endl output << "subsamples_indx = get_existing_subsamples_indx('" << name << "','" << name2
<< "eisind = get_subsamples_range_indx(subsamples_indx, '" << subsample_name << "');" << endl; << "');" << endl
<< "eisind = get_subsamples_range_indx(subsamples_indx, '" << subsample_name << "');"
<< endl;
lhs_field += ".subsample_options(eisind)"; lhs_field += ".subsample_options(eisind)";
} }
writeCommonOutput(output, lhs_field); writeCommonOutput(output, lhs_field);
...@@ -4727,8 +4627,7 @@ BasicOptionsStatement::writeJsonOptionsOutput(ostream &output) const ...@@ -4727,8 +4627,7 @@ BasicOptionsStatement::writeJsonOptionsOutput(ostream &output) const
} }
} }
OptionsStatement::OptionsStatement(string name_arg, OptionsStatement::OptionsStatement(string name_arg, string subsample_name_arg,
string subsample_name_arg,
OptionsList options_list_arg) : OptionsList options_list_arg) :
BasicOptionsStatement {move(name_arg), move(subsample_name_arg), move(options_list_arg)} BasicOptionsStatement {move(name_arg), move(subsample_name_arg), move(options_list_arg)}
{ {
...@@ -4739,8 +4638,8 @@ OptionsStatement::writeOutput(ostream &output, [[maybe_unused]] const string &ba ...@@ -4739,8 +4638,8 @@ OptionsStatement::writeOutput(ostream &output, [[maybe_unused]] const string &ba
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
string lhs_field = "estimation_info.parameter(eifind)"; string lhs_field = "estimation_info.parameter(eifind)";
output << "eifind = get_new_or_existing_ei_index('parameter_options_index', '" output << "eifind = get_new_or_existing_ei_index('parameter_options_index', '" << name
<< name << "', '');" << endl << "', '');" << endl
<< "estimation_info.parameter_options_index(eifind) = {'" << name << "'};" << endl; << "estimation_info.parameter_options_index(eifind) = {'" << name << "'};" << endl;
writeOptionsOutput(output, lhs_field, ""); writeOptionsOutput(output, lhs_field, "");
} }
...@@ -4753,8 +4652,7 @@ OptionsStatement::writeJsonOutput(ostream &output) const ...@@ -4753,8 +4652,7 @@ OptionsStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
StdOptionsStatement::StdOptionsStatement(string name_arg, StdOptionsStatement::StdOptionsStatement(string name_arg, string subsample_name_arg,
string subsample_name_arg,
OptionsList options_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
BasicOptionsStatement {move(name_arg), move(subsample_name_arg), move(options_list_arg)}, BasicOptionsStatement {move(name_arg), move(subsample_name_arg), move(options_list_arg)},
...@@ -4768,9 +4666,10 @@ StdOptionsStatement::writeOutput(ostream &output, [[maybe_unused]] const string ...@@ -4768,9 +4666,10 @@ StdOptionsStatement::writeOutput(ostream &output, [[maybe_unused]] const string
{ {
string lhs_field; string lhs_field;
get_base_name(symbol_table.getType(name), lhs_field); get_base_name(symbol_table.getType(name), lhs_field);
output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_options_index', '" output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_options_index', '" << name
<< name << "', '');" << endl << "', '');" << endl
<< "estimation_info." << lhs_field << "_options_index(eifind) = {'" << name << "'};" << endl; << "estimation_info." << lhs_field << "_options_index(eifind) = {'" << name << "'};"
<< endl;
lhs_field = "estimation_info." + lhs_field + "(eifind)"; lhs_field = "estimation_info." + lhs_field + "(eifind)";
writeOptionsOutput(output, lhs_field, ""); writeOptionsOutput(output, lhs_field, "");
...@@ -4785,8 +4684,7 @@ StdOptionsStatement::writeJsonOutput(ostream &output) const ...@@ -4785,8 +4684,7 @@ StdOptionsStatement::writeJsonOutput(ostream &output) const
} }
CorrOptionsStatement::CorrOptionsStatement(string name_arg1, string name_arg2, CorrOptionsStatement::CorrOptionsStatement(string name_arg1, string name_arg2,
string subsample_name_arg, string subsample_name_arg, OptionsList options_list_arg,
OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
BasicOptionsStatement {move(name_arg1), move(subsample_name_arg), move(options_list_arg)}, BasicOptionsStatement {move(name_arg1), move(subsample_name_arg), move(options_list_arg)},
name1 {move(name_arg2)}, name1 {move(name_arg2)},
...@@ -4816,8 +4714,8 @@ CorrOptionsStatement::writeOutput(ostream &output, [[maybe_unused]] const string ...@@ -4816,8 +4714,8 @@ CorrOptionsStatement::writeOutput(ostream &output, [[maybe_unused]] const string
output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_corr_options_index', '" output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_corr_options_index', '"
<< name << "', '" << name1 << "');" << endl << name << "', '" << name1 << "');" << endl
<< "estimation_info." << lhs_field << "_corr_options_index(eifind) = {'" << "estimation_info." << lhs_field << "_corr_options_index(eifind) = {'" << name << ":"
<< name << ":" << name1 << "'};" << endl; << name1 << "'};" << endl;
lhs_field = "estimation_info." + lhs_field + "_corr(eifind)"; lhs_field = "estimation_info." + lhs_field + "_corr(eifind)";
writeOptionsOutput(output, lhs_field, name1); writeOptionsOutput(output, lhs_field, name1);
...@@ -4832,13 +4730,10 @@ CorrOptionsStatement::writeJsonOutput(ostream &output) const ...@@ -4832,13 +4730,10 @@ CorrOptionsStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
OptionsEqualStatement::OptionsEqualStatement(string to_declaration_type_arg, OptionsEqualStatement::OptionsEqualStatement(string to_declaration_type_arg, string to_name1_arg,
string to_name1_arg, string to_name2_arg, string to_subsample_name_arg,
string to_name2_arg,
string to_subsample_name_arg,
string from_declaration_type_arg, string from_declaration_type_arg,
string from_name1_arg, string from_name1_arg, string from_name2_arg,
string from_name2_arg,
string from_subsample_name_arg, string from_subsample_name_arg,
const SymbolTable& symbol_table_arg) : const SymbolTable& symbol_table_arg) :
to_declaration_type {move(to_declaration_type_arg)}, to_declaration_type {move(to_declaration_type_arg)},
...@@ -4857,8 +4752,10 @@ void ...@@ -4857,8 +4752,10 @@ void
OptionsEqualStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct, OptionsEqualStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings) [[maybe_unused]] WarningConsolidation& warnings)
{ {
if ((to_declaration_type != "par" && to_declaration_type != "std" && to_declaration_type != "corr") if ((to_declaration_type != "par" && to_declaration_type != "std"
|| (from_declaration_type != "par" && from_declaration_type != "std" && from_declaration_type != "corr")) && to_declaration_type != "corr")
|| (from_declaration_type != "par" && from_declaration_type != "std"
&& from_declaration_type != "corr"))
{ {
cerr << "Internal Dynare Error" << endl; cerr << "Internal Dynare Error" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -4883,10 +4780,7 @@ OptionsEqualStatement::writeJsonOutput(ostream &output) const ...@@ -4883,10 +4780,7 @@ OptionsEqualStatement::writeJsonOutput(ostream &output) const
void void
OptionsEqualStatement::get_base_name(const SymbolType symb_type, string& lhs_field) const OptionsEqualStatement::get_base_name(const SymbolType symb_type, string& lhs_field) const
{ {
if (symb_type == SymbolType::exogenous) lhs_field = (symb_type == SymbolType::exogenous ? "structural_innovation" : "measurement_error");
lhs_field = "structural_innovation";
else
lhs_field = "measurement_error";
} }
void void
...@@ -4934,8 +4828,10 @@ OptionsEqualStatement::writeOutput(ostream &output, [[maybe_unused]] const strin ...@@ -4934,8 +4828,10 @@ OptionsEqualStatement::writeOutput(ostream &output, [[maybe_unused]] const strin
lhs_field += ".options"; lhs_field += ".options";
else else
{ {
output << "subsamples_to_indx = get_existing_subsamples_indx('" << to_name1 << "','" << to_name2 << "');" << endl output << "subsamples_to_indx = get_existing_subsamples_indx('" << to_name1 << "','"
<< "ei_to_ss_ind = get_subsamples_range_indx(subsamples_to_indx, '" << to_subsample_name << "');" << endl; << to_name2 << "');" << endl
<< "ei_to_ss_ind = get_subsamples_range_indx(subsamples_to_indx, '"
<< to_subsample_name << "');" << endl;
lhs_field += ".subsample_options(ei_to_ss_ind)"; lhs_field += ".subsample_options(ei_to_ss_ind)";
} }
...@@ -4943,8 +4839,10 @@ OptionsEqualStatement::writeOutput(ostream &output, [[maybe_unused]] const strin ...@@ -4943,8 +4839,10 @@ OptionsEqualStatement::writeOutput(ostream &output, [[maybe_unused]] const strin
rhs_field += ".options"; rhs_field += ".options";
else else
{ {
output << "subsamples_from_indx = get_existing_subsamples_indx('" << from_name1 << "','" << from_name2 << "');" << endl output << "subsamples_from_indx = get_existing_subsamples_indx('" << from_name1 << "','"
<< "ei_from_ss_ind = get_subsamples_range_indx(subsamples_from_indx, '" << from_subsample_name << "');" << endl; << from_name2 << "');" << endl
<< "ei_from_ss_ind = get_subsamples_range_indx(subsamples_from_indx, '"
<< from_subsample_name << "');" << endl;
rhs_field += ".subsample_options(ei_from_ss_ind)"; rhs_field += ".subsample_options(ei_from_ss_ind)";
} }
...@@ -4985,7 +4883,9 @@ CalibSmootherStatement::writeOutput(ostream &output, [[maybe_unused]] const stri ...@@ -4985,7 +4883,9 @@ CalibSmootherStatement::writeOutput(ostream &output, [[maybe_unused]] const stri
symbol_list.writeOutput("var_list_", output); symbol_list.writeOutput("var_list_", output);
output << "options_.smoother = true;" << endl output << "options_.smoother = true;" << endl
<< "options_.order = 1;" << endl << "options_.order = 1;" << endl
<< "[oo_, M_, options_, bayestopt_] = evaluate_smoother(options_.parameter_set, var_list_, M_, oo_, options_, bayestopt_, estim_params_);" << endl; << "[oo_, M_, options_, bayestopt_] = evaluate_smoother(options_.parameter_set, "
"var_list_, M_, oo_, options_, bayestopt_, estim_params_);"
<< endl;
} }
void void
...@@ -5005,8 +4905,8 @@ CalibSmootherStatement::writeJsonOutput(ostream &output) const ...@@ -5005,8 +4905,8 @@ CalibSmootherStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
ExtendedPathStatement::ExtendedPathStatement(OptionsList options_list_arg) ExtendedPathStatement::ExtendedPathStatement(OptionsList options_list_arg) :
: options_list{move(options_list_arg)} options_list {move(options_list_arg)}
{ {
} }
...@@ -5034,7 +4934,8 @@ ExtendedPathStatement::writeOutput(ostream &output, [[maybe_unused]] const strin ...@@ -5034,7 +4934,8 @@ ExtendedPathStatement::writeOutput(ostream &output, [[maybe_unused]] const strin
options_list_new.erase("periods"); options_list_new.erase("periods");
options_list_new.writeOutput(output); options_list_new.writeOutput(output);
output << "extended_path([], " << periods << ", [], options_, M_, oo_);" << endl; output << "[Simulated_time_series, oo_] = extended_path([], " << periods
<< ", [], options_, M_, oo_);" << endl;
} }
void void
...@@ -5111,14 +5012,19 @@ MethodOfMomentsStatement::checkPass(ModFileStructure &mod_file_struct, ...@@ -5111,14 +5012,19 @@ MethodOfMomentsStatement::checkPass(ModFileStructure &mod_file_struct,
if (!options_list.contains("mom.mom_method")) if (!options_list.contains("mom.mom_method"))
{ {
cerr << "ERROR: The 'method_of_moments' statement requires a method to be supplied via the 'mom_method' option. Possible values are 'GMM', 'SMM', or 'IRF_MATCHING'." << endl; cerr << "ERROR: The 'method_of_moments' statement requires a method to be supplied via the "
"'mom_method' option. Possible values are 'GMM', 'SMM', or 'IRF_MATCHING'."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
auto mom_method_value = options_list.get_if<OptionsList::StringVal>("mom.mom_method"); auto mom_method_value = options_list.get_if<OptionsList::StringVal>("mom.mom_method");
if ((mom_method_value == "GMM" || mom_method_value == "SMM") && !options_list.contains("datafile")) if ((mom_method_value == "GMM" || mom_method_value == "SMM")
&& !options_list.contains("datafile"))
{ {
cerr << "ERROR: The 'method_of_moments' statement requires a data file to be supplied via the 'datafile' option." << endl; cerr << "ERROR: The 'method_of_moments' statement requires a data file to be supplied via "
"the 'datafile' option."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -5153,7 +5059,9 @@ MethodOfMomentsStatement::writeOutput(ostream &output, [[maybe_unused]] const st ...@@ -5153,7 +5059,9 @@ MethodOfMomentsStatement::writeOutput(ostream &output, [[maybe_unused]] const st
{ {
options_list.writeOutput(output, "options_mom_"); options_list.writeOutput(output, "options_mom_");
output << "[oo_, options_mom_, M_] = mom.run(bayestopt_, options_, oo_, estim_params_, M_, options_mom_);" << endl; output << "[oo_, options_mom_, M_] = mom.run(bayestopt_, options_, oo_, estim_params_, M_, "
"options_mom_);"
<< endl;
} }
void void
...@@ -5168,9 +5076,8 @@ MethodOfMomentsStatement::writeJsonOutput(ostream &output) const ...@@ -5168,9 +5076,8 @@ MethodOfMomentsStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
GenerateIRFsStatement::GenerateIRFsStatement(
GenerateIRFsStatement::GenerateIRFsStatement(OptionsList options_list_arg, OptionsList options_list_arg, vector<string> generate_irf_names_arg,
vector<string> generate_irf_names_arg,
vector<map<string, double>> generate_irf_elements_arg) : vector<map<string, double>> generate_irf_elements_arg) :
options_list {move(options_list_arg)}, options_list {move(options_list_arg)},
generate_irf_names {move(generate_irf_names_arg)}, generate_irf_names {move(generate_irf_names_arg)},
...@@ -5192,14 +5099,13 @@ GenerateIRFsStatement::writeOutput(ostream &output, [[maybe_unused]] const strin ...@@ -5192,14 +5099,13 @@ GenerateIRFsStatement::writeOutput(ostream &output, [[maybe_unused]] const strin
output << "'" << generate_irf_name << "'; "; output << "'" << generate_irf_name << "'; ";
output << "};" << endl; output << "};" << endl;
output << "options_.irf_opt.irf_shocks = zeros(M_.exo_nbr, " output << "options_.irf_opt.irf_shocks = zeros(M_.exo_nbr, " << generate_irf_names.size() << ");"
<< generate_irf_names.size() << ");" << endl; << endl;
for (size_t i = 0; i < generate_irf_names.size(); i++) for (size_t i = 0; i < generate_irf_names.size(); i++)
for (auto& [exo_name, exo_value] : generate_irf_elements[i]) for (auto& [exo_name, exo_value] : generate_irf_elements[i])
output << "options_.irf_opt.irf_shocks(M_.exo_names == '" output << "options_.irf_opt.irf_shocks(M_.exo_names == '" << exo_name << "', " << i + 1
<< exo_name << "', " << i + 1 << ") = " << ") = " << exo_value << ";" << endl;
<< exo_value << ";" << endl;
} }
void void
...@@ -5235,7 +5141,8 @@ GenerateIRFsStatement::writeJsonOutput(ostream &output) const ...@@ -5235,7 +5141,8 @@ GenerateIRFsStatement::writeJsonOutput(ostream &output) const
output << "}"; output << "}";
} }
MatchedMomentsStatement::MatchedMomentsStatement(const SymbolTable &symbol_table_arg, MatchedMomentsStatement::MatchedMomentsStatement(
const SymbolTable& symbol_table_arg,
vector<tuple<vector<int>, vector<int>, vector<int>>> moments_arg) : vector<tuple<vector<int>, vector<int>, vector<int>>> moments_arg) :
symbol_table {symbol_table_arg}, moments {move(moments_arg)} symbol_table {symbol_table_arg}, moments {move(moments_arg)}
{ {
...@@ -5266,30 +5173,26 @@ void ...@@ -5266,30 +5173,26 @@ void
MatchedMomentsStatement::writeJsonOutput(ostream& output) const MatchedMomentsStatement::writeJsonOutput(ostream& output) const
{ {
output << R"({"statementName": "matched_moments", "moments": [)" << endl; output << R"({"statementName": "matched_moments", "moments": [)" << endl;
for (bool printed_something{false}; for (bool printed_something {false}; const auto& [symb_ids, lags, powers] : moments)
const auto &[symb_ids, lags, powers] : moments)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ','; output << ',';
output << R"( { "endos": [)"; output << R"( { "endos": [)";
for (bool printed_something2{false}; for (bool printed_something2 {false}; int s : symb_ids)
int s : symb_ids)
{ {
if (exchange(printed_something2, true)) if (exchange(printed_something2, true))
output << ','; output << ',';
output << symbol_table.getTypeSpecificID(s) + 1; output << symbol_table.getTypeSpecificID(s) + 1;
} }
output << R"(], "lags": [)"; output << R"(], "lags": [)";
for (bool printed_something2{false}; for (bool printed_something2 {false}; int l : lags)
int l : lags)
{ {
if (exchange(printed_something2, true)) if (exchange(printed_something2, true))
output << ','; output << ',';
output << l; output << l;
} }
output << R"(], "powers": [)"; output << R"(], "powers": [)";
for (bool printed_something2{false}; for (bool printed_something2 {false}; int p : powers)
int p : powers)
{ {
if (exchange(printed_something2, true)) if (exchange(printed_something2, true))
output << ','; output << ',';
...@@ -5300,9 +5203,10 @@ MatchedMomentsStatement::writeJsonOutput(ostream &output) const ...@@ -5300,9 +5203,10 @@ MatchedMomentsStatement::writeJsonOutput(ostream &output) const
output << "]}" << endl; output << "]}" << endl;
} }
OccbinConstraintsStatement::OccbinConstraintsStatement(const DataTree &data_tree_arg, OccbinConstraintsStatement::OccbinConstraintsStatement(
vector<tuple<string, BinaryOpNode *, BinaryOpNode *, expr_t, expr_t>> constraints_arg) const DataTree& data_tree_arg,
: data_tree{data_tree_arg}, constraints{move(constraints_arg)} vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> constraints_arg) :
data_tree {data_tree_arg}, constraints {move(constraints_arg)}
{ {
} }
...@@ -5317,7 +5221,8 @@ OccbinConstraintsStatement::checkPass(ModFileStructure &mod_file_struct, ...@@ -5317,7 +5221,8 @@ OccbinConstraintsStatement::checkPass(ModFileStructure &mod_file_struct,
} }
if (constraints.size() > 2) if (constraints.size() > 2)
{ {
cerr << "ERROR: only up to two constraints are supported in 'occbin_constraints' block" << endl; cerr << "ERROR: only up to two constraints are supported in 'occbin_constraints' block"
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
mod_file_struct.occbin_constraints_present = true; mod_file_struct.occbin_constraints_present = true;
...@@ -5330,7 +5235,10 @@ OccbinConstraintsStatement::writeOutput(ostream &output, const string &basename, ...@@ -5330,7 +5235,10 @@ OccbinConstraintsStatement::writeOutput(ostream &output, const string &basename,
output << "M_.occbin.constraint_nbr = " << constraints.size() << ';' << endl output << "M_.occbin.constraint_nbr = " << constraints.size() << ';' << endl
<< "M_.occbin.pswitch = [" << endl; << "M_.occbin.pswitch = [" << endl;
for (const auto& [name, bind, relax, error_bind, error_relax] : constraints) for (const auto& [name, bind, relax, error_bind, error_relax] : constraints)
output << data_tree.symbol_table.getTypeSpecificID(ParsingDriver::buildOccbinBindParamName(name)) + 1 << ' '; output << data_tree.symbol_table.getTypeSpecificID(
ParsingDriver::buildOccbinBindParamName(name))
+ 1
<< ' ';
output << "];" << endl output << "];" << endl
<< "options_.occbin = struct();" << endl << "options_.occbin = struct();" << endl
<< "options_.occbin = occbin.set_default_options(options_.occbin, M_);" << endl << "options_.occbin = occbin.set_default_options(options_.occbin, M_);" << endl
...@@ -5343,20 +5251,21 @@ OccbinConstraintsStatement::writeOutput(ostream &output, const string &basename, ...@@ -5343,20 +5251,21 @@ OccbinConstraintsStatement::writeOutput(ostream &output, const string &basename,
cerr << "Error: Can't open file " << filename.string() << " for writing" << endl; cerr << "Error: Can't open file " << filename.string() << " for writing" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
diff_output << "function [binding, relax, err] = occbin_difference(zdatalinear, params, steady_state)" << endl; diff_output
for (int idx{1}; << "function [binding, relax, err] = occbin_difference(zdatalinear, params, steady_state)"
const auto &[name, bind, relax, error_bind, error_relax] : constraints) << endl;
for (int idx {1}; const auto& [name, bind, relax, error_bind, error_relax] : constraints)
{ {
diff_output << "binding.constraint_" << idx << " = "; diff_output << "binding.constraint_" << idx << " = ";
dynamic_cast<ExprNode *>(bind)->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile); dynamic_cast<ExprNode*>(bind)->writeOutput(diff_output,
diff_output << ';' << endl ExprNodeOutputType::occbinDifferenceFile);
<< "relax.constraint_" << idx << " = "; diff_output << ';' << endl << "relax.constraint_" << idx << " = ";
if (relax) if (relax)
dynamic_cast<ExprNode *>(relax)->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile); dynamic_cast<ExprNode*>(relax)->writeOutput(diff_output,
ExprNodeOutputType::occbinDifferenceFile);
else else
diff_output << "~binding.constraint_" << idx; diff_output << "~binding.constraint_" << idx;
diff_output << ';' << endl diff_output << ';' << endl << "err.binding_constraint_" << idx << " = ";
<< "err.binding_constraint_" << idx << " = ";
if (error_bind) if (error_bind)
error_bind->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile); error_bind->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile);
else else
...@@ -5367,8 +5276,7 @@ OccbinConstraintsStatement::writeOutput(ostream &output, const string &basename, ...@@ -5367,8 +5276,7 @@ OccbinConstraintsStatement::writeOutput(ostream &output, const string &basename,
bind->arg2->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile); bind->arg2->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile);
diff_output << "))"; diff_output << "))";
} }
diff_output << ';' << endl diff_output << ';' << endl << "err.relax_constraint_" << idx << " = ";
<< "err.relax_constraint_" << idx << " = ";
if (error_relax) if (error_relax)
error_relax->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile); error_relax->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile);
else if (relax) else if (relax)
...@@ -5426,8 +5334,7 @@ OccbinConstraintsStatement::writeJsonOutput(ostream &output) const ...@@ -5426,8 +5334,7 @@ OccbinConstraintsStatement::writeJsonOutput(ostream &output) const
output << "]}" << endl; output << "]}" << endl;
} }
ResidStatement::ResidStatement(OptionsList options_list_arg) : ResidStatement::ResidStatement(OptionsList options_list_arg) : options_list {move(options_list_arg)}
options_list{move(options_list_arg)}
{ {
} }
...@@ -5435,8 +5342,8 @@ void ...@@ -5435,8 +5342,8 @@ void
ResidStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename, ResidStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output, "options_resid_"); options_list.writeOutput(output);
output << "display_static_residuals(M_, options_, oo_, options_resid_);" << endl; output << "display_static_residuals(M_, options_, oo_);" << endl;
} }
void void
...@@ -5450,3 +5357,103 @@ ResidStatement::writeJsonOutput(ostream &output) const ...@@ -5450,3 +5357,103 @@ ResidStatement::writeJsonOutput(ostream &output) const
} }
output << "}"; output << "}";
} }
MatchedIrfsStatement::MatchedIrfsStatement(matched_irfs_t values_weights_arg, bool overwrite_arg) :
values_weights {move(values_weights_arg)}, overwrite {overwrite_arg}
{
}
void
MatchedIrfsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
if (overwrite)
output << "M_.matched_irfs = {};" << endl;
for (const auto& [key, vec] : values_weights)
{
const auto& [endo, exo] = key;
output << "M_.matched_irfs = [M_.matched_irfs; {'" << endo << "', '" << exo << "', {";
for (const auto& [p1, p2, value, weight] : vec)
{
output << p1 << ":" << p2 << ", ";
value->writeOutput(output);
output << ", ";
weight->writeOutput(output);
output << "; ";
}
output << "}}];" << endl;
}
}
void
MatchedIrfsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "matched_irfs")"
<< R"(, "overwrite": )" << boolalpha << overwrite << R"(, "contents": [)";
for (bool printed_something {false}; const auto& [key, vec] : values_weights)
{
if (exchange(printed_something, true))
output << ", ";
const auto& [endo, exo] = key;
output << R"({"var": ")" << endo << R"(", "varexo": ")" << exo
<< R"(", "periods_values_weights": [)";
for (bool printed_something2 {false}; const auto& [p1, p2, value, weight] : vec)
{
if (exchange(printed_something2, true))
output << ", ";
output << R"({"period1": )" << p1 << ", "
<< R"("period2": })" << p2 << ", "
<< R"("value": ")";
value->writeJsonOutput(output, {}, {});
output << R"(", "weight": ")";
weight->writeJsonOutput(output, {}, {});
output << R"("})";
}
output << "]}";
}
output << "]}";
}
MatchedIrfsWeightsStatement::MatchedIrfsWeightsStatement(matched_irfs_weights_t weights_arg,
bool overwrite_arg) :
weights {move(weights_arg)}, overwrite {overwrite_arg}
{
}
void
MatchedIrfsWeightsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
if (overwrite)
output << "M_.matched_irfs_weights = {};" << endl;
for (const auto& [key, val] : weights)
{
const auto& [endo1, periods1, exo1, endo2, periods2, exo2] = key;
output << "M_.matched_irfs_weights = [M_.matched_irfs_weights; {'" << endo1 << "', "
<< periods1 << ", '" << exo1 << "', '" << endo2 << "', " << periods2 << ", '" << exo2
<< "', ";
val->writeOutput(output);
output << "}];" << endl;
}
}
void
MatchedIrfsWeightsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "matched_irfs_weights")"
<< R"(, "overwrite": )" << boolalpha << overwrite << R"(, "contents": [)";
for (bool printed_something {false}; const auto& [key, val] : weights)
{
const auto& [endo1, periods1, exo1, endo2, periods2, exo2] = key;
if (exchange(printed_something, true))
output << ", ";
output << R"({"endo1": ")" << endo1 << R"(", "periods1": ")" << periods1 << R"(", "exo1": )"
<< exo1 << R"(", "endo2": ")" << endo2 << R"(", "periods2": ")" << periods2
<< R"(", "exo2": )" << exo2 << R"(", "weight": ")";
val->writeJsonOutput(output, {}, {});
output << R"("})";
}
output << "]}";
}
/* /*
* Copyright © 2003-2023 Dynare Team * Copyright © 2003-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -17,23 +17,25 @@ ...@@ -17,23 +17,25 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef _COMPUTINGTASKS_HH #ifndef COMPUTING_TASKS_HH
#define _COMPUTINGTASKS_HH #define COMPUTING_TASKS_HH
#include <ostream> #include <memory>
#include <optional> #include <optional>
#include <ostream>
#include "SymbolList.hh"
#include "SymbolTable.hh"
#include "Statement.hh"
#include "StaticModel.hh"
#include "DynamicModel.hh" #include "DynamicModel.hh"
#include "ModelEquationBlock.hh" #include "ModelEquationBlock.hh"
#include "Statement.hh"
#include "StaticModel.hh"
#include "SymbolList.hh"
#include "SymbolTable.hh"
class SteadyStatement : public Statement class SteadyStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit SteadyStatement(OptionsList options_list_arg); explicit SteadyStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -45,6 +47,7 @@ class CheckStatement : public Statement ...@@ -45,6 +47,7 @@ class CheckStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit CheckStatement(OptionsList options_list_arg); explicit CheckStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -56,6 +59,7 @@ class SimulStatement : public Statement ...@@ -56,6 +59,7 @@ class SimulStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit SimulStatement(OptionsList options_list_arg); explicit SimulStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -67,6 +71,7 @@ class PerfectForesightSetupStatement : public Statement ...@@ -67,6 +71,7 @@ class PerfectForesightSetupStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit PerfectForesightSetupStatement(OptionsList options_list_arg); explicit PerfectForesightSetupStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -77,6 +82,7 @@ class PerfectForesightSolverStatement : public Statement ...@@ -77,6 +82,7 @@ class PerfectForesightSolverStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit PerfectForesightSolverStatement(OptionsList options_list_arg); explicit PerfectForesightSolverStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -88,6 +94,7 @@ class PerfectForesightWithExpectationErrorsSetupStatement : public Statement ...@@ -88,6 +94,7 @@ class PerfectForesightWithExpectationErrorsSetupStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit PerfectForesightWithExpectationErrorsSetupStatement(OptionsList options_list_arg); explicit PerfectForesightWithExpectationErrorsSetupStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -98,6 +105,7 @@ class PerfectForesightWithExpectationErrorsSolverStatement : public Statement ...@@ -98,6 +105,7 @@ class PerfectForesightWithExpectationErrorsSolverStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit PerfectForesightWithExpectationErrorsSolverStatement(OptionsList options_list_arg); explicit PerfectForesightWithExpectationErrorsSolverStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -110,6 +118,7 @@ class PriorPosteriorFunctionStatement : public Statement ...@@ -110,6 +118,7 @@ class PriorPosteriorFunctionStatement : public Statement
private: private:
const bool prior_func; const bool prior_func;
const OptionsList options_list; const OptionsList options_list;
public: public:
PriorPosteriorFunctionStatement(const bool prior_func_arg, OptionsList options_list_arg); PriorPosteriorFunctionStatement(const bool prior_func_arg, OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -121,6 +130,7 @@ class ModelInfoStatement : public Statement ...@@ -121,6 +130,7 @@ class ModelInfoStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit ModelInfoStatement(OptionsList options_list_arg); explicit ModelInfoStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -133,6 +143,7 @@ private: ...@@ -133,6 +143,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
StochSimulStatement(SymbolList symbol_list_arg, OptionsList options_list_arg, StochSimulStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -147,6 +158,7 @@ private: ...@@ -147,6 +158,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
ForecastStatement(SymbolList symbol_list_arg, OptionsList options_list_arg, ForecastStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -159,28 +171,9 @@ class RamseyModelStatement : public Statement ...@@ -159,28 +171,9 @@ class RamseyModelStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public:
explicit RamseyModelStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
};
class RamseyConstraintsStatement : public Statement
{
public: public:
struct Constraint explicit RamseyModelStatement(OptionsList options_list_arg);
{
int endo;
BinaryOpcode code;
expr_t expression;
};
using constraints_t = vector<Constraint>;
private:
const SymbolTable &symbol_table;
const constraints_t constraints;
public:
RamseyConstraintsStatement(const SymbolTable &symbol_table_arg, constraints_t constraints_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -192,6 +185,7 @@ private: ...@@ -192,6 +185,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
RamseyPolicyStatement(SymbolList symbol_list_arg, OptionsList options_list_arg, RamseyPolicyStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -204,6 +198,7 @@ class EvaluatePlannerObjectiveStatement : public Statement ...@@ -204,6 +198,7 @@ class EvaluatePlannerObjectiveStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit EvaluatePlannerObjectiveStatement(OptionsList options_list_arg); explicit EvaluatePlannerObjectiveStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -214,6 +209,7 @@ class OccbinSetupStatement : public Statement ...@@ -214,6 +209,7 @@ class OccbinSetupStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit OccbinSetupStatement(OptionsList options_list_arg); explicit OccbinSetupStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -224,6 +220,7 @@ class OccbinSolverStatement : public Statement ...@@ -224,6 +220,7 @@ class OccbinSolverStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit OccbinSolverStatement(OptionsList options_list_arg); explicit OccbinSolverStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -234,6 +231,7 @@ class OccbinWriteRegimesStatement : public Statement ...@@ -234,6 +231,7 @@ class OccbinWriteRegimesStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit OccbinWriteRegimesStatement(OptionsList options_list_arg); explicit OccbinWriteRegimesStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -245,9 +243,9 @@ class OccbinGraphStatement : public Statement ...@@ -245,9 +243,9 @@ class OccbinGraphStatement : public Statement
private: private:
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
public: public:
OccbinGraphStatement(SymbolList symbol_list_arg, OccbinGraphStatement(SymbolList symbol_list_arg, OptionsList options_list_arg);
OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
}; };
...@@ -258,6 +256,7 @@ private: ...@@ -258,6 +256,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
DiscretionaryPolicyStatement(SymbolList symbol_list_arg, OptionsList options_list_arg, DiscretionaryPolicyStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -271,6 +270,7 @@ class RplotStatement : public Statement ...@@ -271,6 +270,7 @@ class RplotStatement : public Statement
private: private:
const SymbolList symbol_list; const SymbolList symbol_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
RplotStatement(SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg); RplotStatement(SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -289,6 +289,7 @@ class DsampleStatement : public Statement ...@@ -289,6 +289,7 @@ class DsampleStatement : public Statement
{ {
private: private:
const int val1, val2; const int val1, val2;
public: public:
explicit DsampleStatement(int val1_arg); explicit DsampleStatement(int val1_arg);
DsampleStatement(int val1_arg, int val2_arg); DsampleStatement(int val1_arg, int val2_arg);
...@@ -302,21 +303,22 @@ private: ...@@ -302,21 +303,22 @@ private:
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
public: public:
EstimationStatement(const SymbolTable &symbol_table_arg, EstimationStatement(const SymbolTable& symbol_table_arg, SymbolList symbol_list_arg,
SymbolList symbol_list_arg,
OptionsList options_list_arg); OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
}; };
class DynareSensitivityStatement : public Statement class SensitivityStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit DynareSensitivityStatement(OptionsList options_list_arg); explicit SensitivityStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -326,9 +328,11 @@ class ObservationTrendsStatement : public Statement ...@@ -326,9 +328,11 @@ class ObservationTrendsStatement : public Statement
{ {
public: public:
using trend_elements_t = map<string, expr_t>; using trend_elements_t = map<string, expr_t>;
private: private:
const trend_elements_t trend_elements; const trend_elements_t trend_elements;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
ObservationTrendsStatement(trend_elements_t trend_elements_arg, ObservationTrendsStatement(trend_elements_t trend_elements_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -340,9 +344,11 @@ class DeterministicTrendsStatement : public Statement ...@@ -340,9 +344,11 @@ class DeterministicTrendsStatement : public Statement
{ {
public: public:
using trend_elements_t = map<string, expr_t>; using trend_elements_t = map<string, expr_t>;
private: private:
const trend_elements_t trend_elements; const trend_elements_t trend_elements;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
DeterministicTrendsStatement(trend_elements_t trend_elements_arg, DeterministicTrendsStatement(trend_elements_t trend_elements_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -354,9 +360,11 @@ class FilterInitialStateStatement : public Statement ...@@ -354,9 +360,11 @@ class FilterInitialStateStatement : public Statement
{ {
public: public:
using filter_initial_state_elements_t = map<pair<int, int>, expr_t>; using filter_initial_state_elements_t = map<pair<int, int>, expr_t>;
private: private:
const filter_initial_state_elements_t filter_initial_state_elements; const filter_initial_state_elements_t filter_initial_state_elements;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
FilterInitialStateStatement(filter_initial_state_elements_t filter_initial_state_elements_arg, FilterInitialStateStatement(filter_initial_state_elements_t filter_initial_state_elements_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -369,6 +377,7 @@ class OsrParamsStatement : public Statement ...@@ -369,6 +377,7 @@ class OsrParamsStatement : public Statement
private: private:
const SymbolList symbol_list; const SymbolList symbol_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
OsrParamsStatement(SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg); OsrParamsStatement(SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -382,6 +391,7 @@ private: ...@@ -382,6 +391,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
OsrStatement(SymbolList symbol_list_arg, OptionsList options_list_arg, OsrStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -410,6 +420,7 @@ class OsrParamsBoundsStatement : public Statement ...@@ -410,6 +420,7 @@ class OsrParamsBoundsStatement : public Statement
{ {
private: private:
const vector<OsrParams> osr_params_list; const vector<OsrParams> osr_params_list;
public: public:
explicit OsrParamsBoundsStatement(vector<OsrParams> osr_params_list_arg); explicit OsrParamsBoundsStatement(vector<OsrParams> osr_params_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -423,6 +434,7 @@ private: ...@@ -423,6 +434,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const string filename; const string filename;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
DynaTypeStatement(SymbolList symbol_list_arg, string filename_arg, DynaTypeStatement(SymbolList symbol_list_arg, string filename_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -437,6 +449,7 @@ private: ...@@ -437,6 +449,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const string filename; const string filename;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
DynaSaveStatement(SymbolList symbol_list_arg, string filename_arg, DynaSaveStatement(SymbolList symbol_list_arg, string filename_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -449,12 +462,13 @@ class ModelComparisonStatement : public Statement ...@@ -449,12 +462,13 @@ class ModelComparisonStatement : public Statement
{ {
public: public:
using filename_list_t = vector<pair<string, string>>; using filename_list_t = vector<pair<string, string>>;
private: private:
filename_list_t filename_list; filename_list_t filename_list;
OptionsList options_list; OptionsList options_list;
public: public:
ModelComparisonStatement(filename_list_t filename_list_arg, ModelComparisonStatement(filename_list_t filename_list_arg, OptionsList options_list_arg);
OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
}; };
...@@ -493,7 +507,7 @@ protected: ...@@ -493,7 +507,7 @@ protected:
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
AbstractEstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg, AbstractEstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
virtual string blockName() const = 0; [[nodiscard]] virtual string blockName() const = 0;
// Part of the check pass that is common to the three estimated_params{,_init,bounds} blocks // Part of the check pass that is common to the three estimated_params{,_init,bounds} blocks
void commonCheckPass() const; void commonCheckPass() const;
}; };
...@@ -502,11 +516,15 @@ class EstimatedParamsStatement : public AbstractEstimatedParamsStatement ...@@ -502,11 +516,15 @@ class EstimatedParamsStatement : public AbstractEstimatedParamsStatement
{ {
private: private:
const bool overwrite; const bool overwrite;
public: public:
EstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg, EstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg, const SymbolTable& symbol_table_arg, bool overwrite_arg);
bool overwrite_arg); [[nodiscard]] string
string blockName() const override { return "estimated_params"; }; blockName() const override
{
return "estimated_params";
}
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -516,11 +534,15 @@ class EstimatedParamsInitStatement : public AbstractEstimatedParamsStatement ...@@ -516,11 +534,15 @@ class EstimatedParamsInitStatement : public AbstractEstimatedParamsStatement
{ {
private: private:
const bool use_calibration; const bool use_calibration;
public: public:
EstimatedParamsInitStatement(vector<EstimationParams> estim_params_list_arg, EstimatedParamsInitStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg, const SymbolTable& symbol_table_arg, const bool use_calibration_arg);
const bool use_calibration_arg); [[nodiscard]] string
string blockName() const override { return "estimated_params_init"; }; blockName() const override
{
return "estimated_params_init";
}
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -531,7 +553,11 @@ class EstimatedParamsBoundsStatement : public AbstractEstimatedParamsStatement ...@@ -531,7 +553,11 @@ class EstimatedParamsBoundsStatement : public AbstractEstimatedParamsStatement
public: public:
EstimatedParamsBoundsStatement(vector<EstimationParams> estim_params_list_arg, EstimatedParamsBoundsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
string blockName() const override { return "estimated_params_bounds"; }; [[nodiscard]] string
blockName() const override
{
return "estimated_params_bounds";
}
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -554,13 +580,14 @@ class OptimWeightsStatement : public Statement ...@@ -554,13 +580,14 @@ class OptimWeightsStatement : public Statement
public: public:
using var_weights_t = map<string, expr_t>; using var_weights_t = map<string, expr_t>;
using covar_weights_t = map<pair<string, string>, expr_t>; using covar_weights_t = map<pair<string, string>, expr_t>;
private: private:
const var_weights_t var_weights; const var_weights_t var_weights;
const covar_weights_t covar_weights; const covar_weights_t covar_weights;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
OptimWeightsStatement(var_weights_t var_weights_arg, OptimWeightsStatement(var_weights_t var_weights_arg, covar_weights_t covar_weights_arg,
covar_weights_t covar_weights_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -570,10 +597,11 @@ public: ...@@ -570,10 +597,11 @@ public:
class PlannerObjectiveStatement : public Statement class PlannerObjectiveStatement : public Statement
{ {
private: private:
PlannerObjective model_tree; unique_ptr<PlannerObjective> model_tree;
bool computing_pass_called {false}; bool computing_pass_called {false};
public: public:
explicit PlannerObjectiveStatement(const PlannerObjective &model_tree_arg); explicit PlannerObjectiveStatement(unique_ptr<PlannerObjective> model_tree_arg);
/*! \todo check there are only endogenous variables at the current period in the objective /*! \todo check there are only endogenous variables at the current period in the objective
(no exogenous, no lead/lag) */ (no exogenous, no lead/lag) */
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -582,7 +610,7 @@ public: ...@@ -582,7 +610,7 @@ public:
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
//! Return a reference the Planner Objective model tree //! Return a reference the Planner Objective model tree
const PlannerObjective &getPlannerObjective() const; [[nodiscard]] const PlannerObjective& getPlannerObjective() const;
}; };
class BVARDensityStatement : public Statement class BVARDensityStatement : public Statement
...@@ -590,6 +618,7 @@ class BVARDensityStatement : public Statement ...@@ -590,6 +618,7 @@ class BVARDensityStatement : public Statement
private: private:
const int maxnlags; const int maxnlags;
const OptionsList options_list; const OptionsList options_list;
public: public:
BVARDensityStatement(int maxnlags_arg, OptionsList options_list_arg); BVARDensityStatement(int maxnlags_arg, OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -602,6 +631,7 @@ class BVARForecastStatement : public Statement ...@@ -602,6 +631,7 @@ class BVARForecastStatement : public Statement
private: private:
const int nlags; const int nlags;
const OptionsList options_list; const OptionsList options_list;
public: public:
BVARForecastStatement(int nlags_arg, OptionsList options_list_arg); BVARForecastStatement(int nlags_arg, OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -614,6 +644,7 @@ class BVARIRFStatement : public Statement ...@@ -614,6 +644,7 @@ class BVARIRFStatement : public Statement
private: private:
const int nirf; const int nirf;
const string identificationname; const string identificationname;
public: public:
BVARIRFStatement(int nirf_arg, string identificationname_arg); BVARIRFStatement(int nirf_arg, string identificationname_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -625,6 +656,7 @@ class SBVARStatement : public Statement ...@@ -625,6 +656,7 @@ class SBVARStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit SBVARStatement(OptionsList options_list_arg); explicit SBVARStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -636,6 +668,7 @@ class MSSBVAREstimationStatement : public Statement ...@@ -636,6 +668,7 @@ class MSSBVAREstimationStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit MSSBVAREstimationStatement(OptionsList options_list_arg); explicit MSSBVAREstimationStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -647,6 +680,7 @@ class MSSBVARSimulationStatement : public Statement ...@@ -647,6 +680,7 @@ class MSSBVARSimulationStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit MSSBVARSimulationStatement(OptionsList options_list_arg); explicit MSSBVARSimulationStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -658,6 +692,7 @@ class MSSBVARComputeMDDStatement : public Statement ...@@ -658,6 +692,7 @@ class MSSBVARComputeMDDStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit MSSBVARComputeMDDStatement(OptionsList options_list_arg); explicit MSSBVARComputeMDDStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -669,6 +704,7 @@ class MSSBVARComputeProbabilitiesStatement : public Statement ...@@ -669,6 +704,7 @@ class MSSBVARComputeProbabilitiesStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit MSSBVARComputeProbabilitiesStatement(OptionsList options_list_arg); explicit MSSBVARComputeProbabilitiesStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -682,6 +718,7 @@ private: ...@@ -682,6 +718,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
MSSBVARIrfStatement(SymbolList symbol_list_arg, OptionsList options_list_arg, MSSBVARIrfStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -694,6 +731,7 @@ class MSSBVARForecastStatement : public Statement ...@@ -694,6 +731,7 @@ class MSSBVARForecastStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit MSSBVARForecastStatement(OptionsList options_list_arg); explicit MSSBVARForecastStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -705,6 +743,7 @@ class MSSBVARVarianceDecompositionStatement : public Statement ...@@ -705,6 +743,7 @@ class MSSBVARVarianceDecompositionStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit MSSBVARVarianceDecompositionStatement(OptionsList options_list_arg); explicit MSSBVARVarianceDecompositionStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -716,6 +755,7 @@ class IdentificationStatement : public Statement ...@@ -716,6 +755,7 @@ class IdentificationStatement : public Statement
{ {
private: private:
OptionsList options_list; OptionsList options_list;
public: public:
explicit IdentificationStatement(OptionsList options_list_arg); explicit IdentificationStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -728,8 +768,10 @@ class WriteLatexDynamicModelStatement : public Statement ...@@ -728,8 +768,10 @@ class WriteLatexDynamicModelStatement : public Statement
private: private:
const DynamicModel& dynamic_model; const DynamicModel& dynamic_model;
const bool write_equation_tags; const bool write_equation_tags;
public: public:
WriteLatexDynamicModelStatement(const DynamicModel &dynamic_model_arg, bool write_equation_tags_arg); WriteLatexDynamicModelStatement(const DynamicModel& dynamic_model_arg,
bool write_equation_tags_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
}; };
...@@ -739,6 +781,7 @@ class WriteLatexStaticModelStatement : public Statement ...@@ -739,6 +781,7 @@ class WriteLatexStaticModelStatement : public Statement
private: private:
const StaticModel& static_model; const StaticModel& static_model;
const bool write_equation_tags; const bool write_equation_tags;
public: public:
WriteLatexStaticModelStatement(const StaticModel& static_model_arg, bool write_equation_tags_arg); WriteLatexStaticModelStatement(const StaticModel& static_model_arg, bool write_equation_tags_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -750,8 +793,10 @@ class WriteLatexOriginalModelStatement : public Statement ...@@ -750,8 +793,10 @@ class WriteLatexOriginalModelStatement : public Statement
private: private:
const DynamicModel& original_model; const DynamicModel& original_model;
const bool write_equation_tags; const bool write_equation_tags;
public: public:
WriteLatexOriginalModelStatement(const DynamicModel &original_model_arg, bool write_equation_tags_arg); WriteLatexOriginalModelStatement(const DynamicModel& original_model_arg,
bool write_equation_tags_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
}; };
...@@ -760,6 +805,7 @@ class WriteLatexSteadyStateModelStatement : public Statement ...@@ -760,6 +805,7 @@ class WriteLatexSteadyStateModelStatement : public Statement
{ {
private: private:
const SteadyStateModel& steady_state_model; const SteadyStateModel& steady_state_model;
public: public:
explicit WriteLatexSteadyStateModelStatement(const SteadyStateModel& steady_state_model_arg); explicit WriteLatexSteadyStateModelStatement(const SteadyStateModel& steady_state_model_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -773,6 +819,7 @@ private: ...@@ -773,6 +819,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
ShockDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg, ShockDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -787,6 +834,7 @@ private: ...@@ -787,6 +834,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
RealtimeShockDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg, RealtimeShockDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -801,6 +849,7 @@ private: ...@@ -801,6 +849,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
PlotShockDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg, PlotShockDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -815,6 +864,7 @@ private: ...@@ -815,6 +864,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
InitialConditionDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg, InitialConditionDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -828,6 +878,7 @@ class SqueezeShockDecompositionStatement : public Statement ...@@ -828,6 +878,7 @@ class SqueezeShockDecompositionStatement : public Statement
private: private:
const SymbolList symbol_list; const SymbolList symbol_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
SqueezeShockDecompositionStatement(SymbolList symbol_list_arg, SqueezeShockDecompositionStatement(SymbolList symbol_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -840,6 +891,7 @@ class ConditionalForecastStatement : public Statement ...@@ -840,6 +891,7 @@ class ConditionalForecastStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit ConditionalForecastStatement(OptionsList options_list_arg); explicit ConditionalForecastStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -853,8 +905,9 @@ private: ...@@ -853,8 +905,9 @@ private:
const optional<int> periods; // The user is allowed not to declare periods const optional<int> periods; // The user is allowed not to declare periods
const SymbolList symbol_list; const SymbolList symbol_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
PlotConditionalForecastStatement(optional<int> periods_arg, SymbolList symbol_list_arg, PlotConditionalForecastStatement(const optional<int>& periods_arg, SymbolList symbol_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -867,6 +920,7 @@ private: ...@@ -867,6 +920,7 @@ private:
const SymbolList symbol_list; const SymbolList symbol_list;
const OptionsList options_list; const OptionsList options_list;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
CalibSmootherStatement(SymbolList symbol_list_arg, OptionsList options_list_arg, CalibSmootherStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
...@@ -879,6 +933,7 @@ class ExtendedPathStatement : public Statement ...@@ -879,6 +933,7 @@ class ExtendedPathStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit ExtendedPathStatement(OptionsList options_list_arg); explicit ExtendedPathStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -900,15 +955,16 @@ public: ...@@ -900,15 +955,16 @@ public:
}; };
using svar_identification_restrictions_t = vector<svar_identification_restriction>; using svar_identification_restrictions_t = vector<svar_identification_restriction>;
private: private:
const svar_identification_restrictions_t restrictions; const svar_identification_restrictions_t restrictions;
const bool upper_cholesky_present, lower_cholesky_present, constants_exclusion_present; const bool upper_cholesky_present, lower_cholesky_present, constants_exclusion_present;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
int getMaxLag() const; [[nodiscard]] int getMaxLag() const;
public: public:
SvarIdentificationStatement(svar_identification_restrictions_t restrictions_arg, SvarIdentificationStatement(svar_identification_restrictions_t restrictions_arg,
bool upper_cholesky_present_arg, bool upper_cholesky_present_arg, bool lower_cholesky_present_arg,
bool lower_cholesky_present_arg,
bool constants_exclusion_present_arg, bool constants_exclusion_present_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -921,6 +977,7 @@ class MarkovSwitchingStatement : public Statement ...@@ -921,6 +977,7 @@ class MarkovSwitchingStatement : public Statement
private: private:
const OptionsList options_list; const OptionsList options_list;
map<pair<int, int>, double> restriction_map; map<pair<int, int>, double> restriction_map;
public: public:
explicit MarkovSwitchingStatement(OptionsList options_list_arg); explicit MarkovSwitchingStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -932,6 +989,7 @@ class SvarStatement : public Statement ...@@ -932,6 +989,7 @@ class SvarStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit SvarStatement(OptionsList options_list_arg); explicit SvarStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -949,9 +1007,10 @@ public: ...@@ -949,9 +1007,10 @@ public:
class SetTimeStatement : public Statement class SetTimeStatement : public Statement
{ {
private: private:
const OptionsList options_list; const string period;
public: public:
explicit SetTimeStatement(OptionsList options_list_arg); explicit SetTimeStatement(string period_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
}; };
...@@ -960,6 +1019,7 @@ class EstimationDataStatement : public Statement ...@@ -960,6 +1019,7 @@ class EstimationDataStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit EstimationDataStatement(OptionsList options_list_arg); explicit EstimationDataStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -972,13 +1032,14 @@ class SubsamplesStatement : public Statement ...@@ -972,13 +1032,14 @@ class SubsamplesStatement : public Statement
public: public:
//! Storage for declaring subsamples: map<subsample_name, <date1, date2 > //! Storage for declaring subsamples: map<subsample_name, <date1, date2 >
using subsample_declaration_map_t = map<string, pair<string, string>>; using subsample_declaration_map_t = map<string, pair<string, string>>;
private: private:
const string name1, name2; const string name1, name2;
const subsample_declaration_map_t subsample_declaration_map; const subsample_declaration_map_t subsample_declaration_map;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
SubsamplesStatement(string name1_arg, SubsamplesStatement(string name1_arg, string name2_arg,
string name2_arg,
subsample_declaration_map_t subsample_declaration_map_arg, subsample_declaration_map_t subsample_declaration_map_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -990,12 +1051,10 @@ class SubsamplesEqualStatement : public Statement ...@@ -990,12 +1051,10 @@ class SubsamplesEqualStatement : public Statement
private: private:
const string to_name1, to_name2, from_name1, from_name2; const string to_name1, to_name2, from_name1, from_name2;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
SubsamplesEqualStatement(string to_name1_arg, SubsamplesEqualStatement(string to_name1_arg, string to_name2_arg, string from_name1_arg,
string to_name2_arg, string from_name2_arg, const SymbolTable& symbol_table_arg);
string from_name1_arg,
string from_name2_arg,
const SymbolTable &symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
}; };
...@@ -1007,9 +1066,9 @@ private: ...@@ -1007,9 +1066,9 @@ private:
const PriorDistributions prior_shape; const PriorDistributions prior_shape;
const OptionsList options_list; const OptionsList options_list;
void writeOutputHelper(ostream& output, const string& field, const string& lhs_field) const; void writeOutputHelper(ostream& output, const string& field, const string& lhs_field) const;
public: public:
JointPriorStatement(vector<string> joint_parameters_arg, JointPriorStatement(vector<string> joint_parameters_arg, PriorDistributions prior_shape_arg,
PriorDistributions prior_shape_arg,
OptionsList options_list_arg); OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -1023,17 +1082,15 @@ protected: ...@@ -1023,17 +1082,15 @@ protected:
const PriorDistributions prior_shape; const PriorDistributions prior_shape;
const expr_t variance; const expr_t variance;
const OptionsList options_list; const OptionsList options_list;
BasicPriorStatement(string name_arg, BasicPriorStatement(string name_arg, string subsample_name_arg,
string subsample_name_arg, PriorDistributions prior_shape_arg, expr_t variance_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg); OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void get_base_name(const SymbolType symb_type, string& lhs_field) const; void get_base_name(const SymbolType symb_type, string& lhs_field) const;
void writeCommonOutput(ostream& output, const string& lhs_field) const; void writeCommonOutput(ostream& output, const string& lhs_field) const;
void writeCommonOutputHelper(ostream& output, const string& field, const string& lhs_field) const; void writeCommonOutputHelper(ostream& output, const string& field, const string& lhs_field) const;
void writePriorOutput(ostream& output, string& lhs_field, const string& name2) const; void writePriorOutput(ostream& output, string& lhs_field, const string& name2) const;
bool is_structural_innovation(const SymbolType symb_type) const; [[nodiscard]] bool is_structural_innovation(const SymbolType symb_type) const;
void writePriorIndex(ostream& output, const string& lhs_field) const; void writePriorIndex(ostream& output, const string& lhs_field) const;
void writeVarianceOption(ostream& output, const string& lhs_field) const; void writeVarianceOption(ostream& output, const string& lhs_field) const;
void writeOutputHelper(ostream& output, const string& field, const string& lhs_field) const; void writeOutputHelper(ostream& output, const string& field, const string& lhs_field) const;
...@@ -1045,11 +1102,8 @@ protected: ...@@ -1045,11 +1102,8 @@ protected:
class PriorStatement : public BasicPriorStatement class PriorStatement : public BasicPriorStatement
{ {
public: public:
PriorStatement(string name_arg, PriorStatement(string name_arg, string subsample_name_arg, PriorDistributions prior_shape_arg,
string subsample_name_arg, expr_t variance_arg, OptionsList options_list_arg);
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
}; };
...@@ -1058,12 +1112,10 @@ class StdPriorStatement : public BasicPriorStatement ...@@ -1058,12 +1112,10 @@ class StdPriorStatement : public BasicPriorStatement
{ {
private: private:
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
StdPriorStatement(string name_arg, StdPriorStatement(string name_arg, string subsample_name_arg, PriorDistributions prior_shape_arg,
string subsample_name_arg, expr_t variance_arg, OptionsList options_list_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -1074,14 +1126,11 @@ class CorrPriorStatement : public BasicPriorStatement ...@@ -1074,14 +1126,11 @@ class CorrPriorStatement : public BasicPriorStatement
private: private:
const string name1; const string name1;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
CorrPriorStatement(string name_arg1, CorrPriorStatement(string name_arg1, string name_arg2, string subsample_name_arg,
string name_arg2, PriorDistributions prior_shape_arg, expr_t variance_arg,
string subsample_name_arg, OptionsList options_list_arg, const SymbolTable& symbol_table_arg);
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg,
const SymbolTable &symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -1093,15 +1142,11 @@ private: ...@@ -1093,15 +1142,11 @@ private:
const string to_declaration_type, to_name1, to_name2, to_subsample_name; const string to_declaration_type, to_name1, to_name2, to_subsample_name;
const string from_declaration_type, from_name1, from_name2, from_subsample_name; const string from_declaration_type, from_name1, from_name2, from_subsample_name;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
PriorEqualStatement(string to_declaration_type_arg, PriorEqualStatement(string to_declaration_type_arg, string to_name1_arg, string to_name2_arg,
string to_name1_arg, string to_subsample_name_arg, string from_declaration_type_arg,
string to_name2_arg, string from_name1_arg, string from_name2_arg, string from_subsample_name_arg,
string to_subsample_name_arg,
string from_declaration_type_arg,
string from_name1_arg,
string from_name2_arg,
string from_subsample_name_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
void get_base_name(const SymbolType symb_type, string& lhs_field) const; void get_base_name(const SymbolType symb_type, string& lhs_field) const;
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -1114,14 +1159,12 @@ class BasicOptionsStatement : public Statement ...@@ -1114,14 +1159,12 @@ class BasicOptionsStatement : public Statement
protected: protected:
const string name, subsample_name; const string name, subsample_name;
const OptionsList options_list; const OptionsList options_list;
BasicOptionsStatement(string name_arg, BasicOptionsStatement(string name_arg, string subsample_name_arg, OptionsList options_list_arg);
string subsample_name_arg,
OptionsList options_list_arg);
void get_base_name(const SymbolType symb_type, string& lhs_field) const; void get_base_name(const SymbolType symb_type, string& lhs_field) const;
void writeOptionsOutput(ostream& output, string& lhs_field, const string& name2) const; void writeOptionsOutput(ostream& output, string& lhs_field, const string& name2) const;
void writeCommonOutput(ostream& output, const string& lhs_field) const; void writeCommonOutput(ostream& output, const string& lhs_field) const;
void writeCommonOutputHelper(ostream& output, const string& field, const string& lhs_field) const; void writeCommonOutputHelper(ostream& output, const string& field, const string& lhs_field) const;
bool is_structural_innovation(const SymbolType symb_type) const; [[nodiscard]] bool is_structural_innovation(const SymbolType symb_type) const;
void writeOptionsIndex(ostream& output, const string& lhs_field) const; void writeOptionsIndex(ostream& output, const string& lhs_field) const;
void writeOutputHelper(ostream& output, const string& field, const string& lhs_field) const; void writeOutputHelper(ostream& output, const string& field, const string& lhs_field) const;
void writeJsonOptionsOutput(ostream& output) const; void writeJsonOptionsOutput(ostream& output) const;
...@@ -1139,10 +1182,9 @@ class StdOptionsStatement : public BasicOptionsStatement ...@@ -1139,10 +1182,9 @@ class StdOptionsStatement : public BasicOptionsStatement
{ {
private: private:
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
StdOptionsStatement(string name_arg, StdOptionsStatement(string name_arg, string subsample_name_arg, OptionsList options_list_arg,
string subsample_name_arg,
OptionsList options_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -1153,11 +1195,10 @@ class CorrOptionsStatement : public BasicOptionsStatement ...@@ -1153,11 +1195,10 @@ class CorrOptionsStatement : public BasicOptionsStatement
private: private:
const string name1; const string name1;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
CorrOptionsStatement(string name_arg1, string name_arg2, CorrOptionsStatement(string name_arg1, string name_arg2, string subsample_name_arg,
string subsample_name_arg, OptionsList options_list_arg, const SymbolTable& symbol_table_arg);
OptionsList options_list_arg,
const SymbolTable &symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -1169,16 +1210,12 @@ private: ...@@ -1169,16 +1210,12 @@ private:
const string to_declaration_type, to_name1, to_name2, to_subsample_name; const string to_declaration_type, to_name1, to_name2, to_subsample_name;
const string from_declaration_type, from_name1, from_name2, from_subsample_name; const string from_declaration_type, from_name1, from_name2, from_subsample_name;
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
OptionsEqualStatement(string to_declaration_type_arg, OptionsEqualStatement(string to_declaration_type_arg, string to_name1_arg, string to_name2_arg,
string to_name1_arg, string to_subsample_name_arg, string from_declaration_type_arg,
string to_name2_arg, string from_name1_arg, string from_name2_arg,
string to_subsample_name_arg, string from_subsample_name_arg, const SymbolTable& symbol_table_arg);
string from_declaration_type_arg,
string from_name1_arg,
string from_name2_arg,
string from_subsample_name_arg,
const SymbolTable &symbol_table_arg);
void get_base_name(const SymbolType symb_type, string& lhs_field) const; void get_base_name(const SymbolType symb_type, string& lhs_field) const;
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -1196,6 +1233,7 @@ class Smoother2histvalStatement : public Statement ...@@ -1196,6 +1233,7 @@ class Smoother2histvalStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit Smoother2histvalStatement(OptionsList options_list_arg); explicit Smoother2histvalStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -1206,6 +1244,7 @@ class MethodOfMomentsStatement : public Statement ...@@ -1206,6 +1244,7 @@ class MethodOfMomentsStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit MethodOfMomentsStatement(OptionsList options_list_arg); explicit MethodOfMomentsStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
...@@ -1220,9 +1259,9 @@ private: ...@@ -1220,9 +1259,9 @@ private:
const OptionsList options_list; const OptionsList options_list;
const vector<string> generate_irf_names; const vector<string> generate_irf_names;
const vector<map<string, double>> generate_irf_elements; const vector<map<string, double>> generate_irf_elements;
public: public:
GenerateIRFsStatement(OptionsList options_list_arg, GenerateIRFsStatement(OptionsList options_list_arg, vector<string> generate_irf_names_arg,
vector<string> generate_irf_names_arg,
vector<map<string, double>> generate_irf_elements_arg); vector<map<string, double>> generate_irf_elements_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -1232,6 +1271,7 @@ class MatchedMomentsStatement : public Statement ...@@ -1232,6 +1271,7 @@ class MatchedMomentsStatement : public Statement
{ {
private: private:
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
/* Each moment is represented by a three vectors: symb_ids, lags, powers. /* Each moment is represented by a three vectors: symb_ids, lags, powers.
See the definition of ExprNode::matchMatchedMoment() for more details */ See the definition of ExprNode::matchMatchedMoment() for more details */
...@@ -1246,10 +1286,13 @@ class OccbinConstraintsStatement : public Statement ...@@ -1246,10 +1286,13 @@ class OccbinConstraintsStatement : public Statement
{ {
private: private:
DataTree data_tree; DataTree data_tree;
public: public:
// The tuple is (name, bind, relax, error_bind, error_relax) (where relax and error_{bind,relax} can be nullptr) // The tuple is (name, bind, relax, error_bind, error_relax) (where relax and error_{bind,relax}
// can be nullptr)
const vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> constraints; const vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> constraints;
OccbinConstraintsStatement(const DataTree &data_tree_arg, OccbinConstraintsStatement(
const DataTree& data_tree_arg,
vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> constraints_arg); vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> constraints_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
...@@ -1260,10 +1303,40 @@ class ResidStatement : public Statement ...@@ -1260,10 +1303,40 @@ class ResidStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit ResidStatement(OptionsList options_list_arg); explicit ResidStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
}; };
class MatchedIrfsStatement : public Statement
{
public:
// (endo name, exo name) → vector of (period start, period end, value, weight)
using matched_irfs_t = map<pair<string, string>, vector<tuple<int, int, expr_t, expr_t>>>;
MatchedIrfsStatement(matched_irfs_t values_weights_arg, bool overwrite_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
private:
const matched_irfs_t values_weights;
const bool overwrite;
};
class MatchedIrfsWeightsStatement : public Statement
{
public:
/* (endo1 name, period index or range for endo1, exo1 name, endo2 name, period index or range for
endo2, exo2 name) → weight */
using matched_irfs_weights_t = map<tuple<string, string, string, string, string, string>, expr_t>;
MatchedIrfsWeightsStatement(matched_irfs_weights_t weights_arg, bool overwrite_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
private:
const matched_irfs_weights_t weights;
const bool overwrite;
};
#endif #endif
/* /*
* Copyright © 2010-2023 Dynare Team * Copyright © 2010-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -17,33 +17,25 @@ ...@@ -17,33 +17,25 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <iostream>
#include <fstream> #include <fstream>
#include <iostream>
#include <utility> #include <utility>
#include <vector>
#include "ConfigFile.hh" #ifdef _WIN32
# include <shlobj.h>
#endif
#include "Configuration.hh"
#include "DataTree.hh" // For strsplit()
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wold-style-cast"
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/tokenizer.hpp> #include <boost/tokenizer.hpp>
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
using namespace std; Configuration::Path::Path(vector<string> includepath_arg)
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"] = move(global_init_file_arg);
}
Path::Path(vector<string> includepath_arg)
{ {
if (includepath_arg.empty()) if (includepath_arg.empty())
{ {
...@@ -53,10 +45,13 @@ Path::Path(vector<string> includepath_arg) ...@@ -53,10 +45,13 @@ Path::Path(vector<string> includepath_arg)
paths["include"] = move(includepath_arg); paths["include"] = move(includepath_arg);
} }
FollowerNode::FollowerNode(string computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string userName_arg, Configuration::FollowerNode::FollowerNode(string computerName_arg, string port_arg,
string password_arg, string remoteDrive_arg, string remoteDirectory_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string userName_arg,
string programPath_arg, string programConfig_arg, string matlabOctavePath_arg, bool singleCompThread_arg, string password_arg, string remoteDrive_arg,
int numberOfThreadsPerJob_arg, string operatingSystem_arg) : string remoteDirectory_arg, string programPath_arg,
string programConfig_arg, string matlabOctavePath_arg,
bool singleCompThread_arg, int numberOfThreadsPerJob_arg,
string operatingSystem_arg) :
computerName {move(computerName_arg)}, computerName {move(computerName_arg)},
port {move(port_arg)}, port {move(port_arg)},
minCpuNbr {minCpuNbr_arg}, minCpuNbr {minCpuNbr_arg},
...@@ -81,12 +76,13 @@ FollowerNode::FollowerNode(string computerName_arg, string port_arg, int minCpuN ...@@ -81,12 +76,13 @@ FollowerNode::FollowerNode(string computerName_arg, string port_arg, int minCpuN
if (!operatingSystem.empty()) if (!operatingSystem.empty())
if (operatingSystem != "windows" && operatingSystem != "unix") if (operatingSystem != "windows" && operatingSystem != "unix")
{ {
cerr << "ERROR: The OperatingSystem must be either 'unix' or 'windows' (Case Sensitive)." << endl; cerr << "ERROR: The OperatingSystem must be either 'unix' or 'windows' (Case Sensitive)."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
Cluster::Cluster(member_nodes_t member_nodes_arg) : Configuration::Cluster::Cluster(member_nodes_t member_nodes_arg) :
member_nodes {move(member_nodes_arg)} member_nodes {move(member_nodes_arg)}
{ {
if (member_nodes.empty()) if (member_nodes.empty())
...@@ -96,10 +92,11 @@ Cluster::Cluster(member_nodes_t member_nodes_arg) : ...@@ -96,10 +92,11 @@ Cluster::Cluster(member_nodes_t member_nodes_arg) :
} }
} }
ConfigFile::ConfigFile(bool parallel_arg, bool parallel_test_arg, Configuration::Configuration(bool parallel_arg, bool parallel_test_arg,
bool parallel_follower_open_mode_arg, bool parallel_use_psexec_arg, bool parallel_follower_open_mode_arg, bool parallel_use_psexec_arg,
string cluster_name_arg) : string cluster_name_arg) :
parallel{parallel_arg}, parallel_test{parallel_test_arg}, parallel {parallel_arg},
parallel_test {parallel_test_arg},
parallel_follower_open_mode {parallel_follower_open_mode_arg}, parallel_follower_open_mode {parallel_follower_open_mode_arg},
parallel_use_psexec {parallel_use_psexec_arg}, parallel_use_psexec {parallel_use_psexec_arg},
cluster_name {move(cluster_name_arg)} cluster_name {move(cluster_name_arg)}
...@@ -107,70 +104,63 @@ ConfigFile::ConfigFile(bool parallel_arg, bool parallel_test_arg, ...@@ -107,70 +104,63 @@ ConfigFile::ConfigFile(bool parallel_arg, bool parallel_test_arg,
} }
void void
ConfigFile::getConfigFileInfo(const filesystem::path &config_file) Configuration::getConfigFileInfo(const filesystem::path& conffile_option,
WarningConsolidation& warnings)
{ {
using namespace boost; using namespace boost;
ifstream configFile;
filesystem::path config_file {conffile_option};
if (config_file.empty()) if (config_file.empty())
{ {
filesystem::path defaultConfigFile; config_file = findConfigFile("dynare.ini");
// Test OS and try to open default file
#if defined(_WIN32) || defined(__CYGWIN32__)
if (auto appdata = getenv("APPDATA");
appdata)
defaultConfigFile = filesystem::path{appdata} / "dynare.ini";
else
{
if (parallel || parallel_test)
cerr << "ERROR: ";
else
cerr << "WARNING: ";
cerr << "APPDATA environment variable not found." << endl;
if (parallel || parallel_test) if (config_file.empty()) // Try old default location (Dynare ⩽ 5) for backward compatibility
exit(EXIT_FAILURE); {
} filesystem::path old_default_config_file;
#ifdef _WIN32
array<wchar_t, MAX_PATH + 1> appdata;
if (SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_DONT_VERIFY, nullptr,
SHGFP_TYPE_CURRENT, appdata.data())
== S_OK)
old_default_config_file = filesystem::path {appdata.data()} / "dynare.ini";
#else #else
if (auto home = getenv("HOME"); if (auto home = getenv("HOME"); home)
home) old_default_config_file = filesystem::path {home} / ".dynare";
defaultConfigFile = filesystem::path{home} / ".dynare"; #endif
else if (!old_default_config_file.empty() && exists(old_default_config_file))
{ {
if (parallel || parallel_test) warnings << "WARNING: the location " << old_default_config_file.string()
cerr << "ERROR: "; << " for the configuration file is obsolete; please see the reference"
else << " manual for the new location." << endl;
cerr << "WARNING: "; config_file = old_default_config_file;
cerr << "HOME environment variable not found." << endl;
if (parallel || parallel_test)
exit(EXIT_FAILURE);
} }
#endif }
configFile.open(defaultConfigFile, fstream::in); }
if (!configFile.is_open())
if (config_file.empty())
{ {
if (parallel || parallel_test) if (parallel || parallel_test)
{ {
cerr << "ERROR: Could not open the default config file (" << defaultConfigFile.string() << ")" << endl; cerr << "ERROR: the parallel or parallel_test option was passed but no configuration "
<< "file was found" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else else
return; return;
} }
}
else ifstream configFile;
{
configFile.open(config_file, fstream::in); configFile.open(config_file, fstream::in);
if (!configFile.is_open()) if (!configFile.is_open())
{ {
cerr << "ERROR: Couldn't open file " << config_file.string() << endl;; cerr << "ERROR: Couldn't open configuration file " << config_file.string() << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
}
string name, computerName, port, userName, password, remoteDrive, string name, computerName, port, userName, password, remoteDrive, remoteDirectory, programPath,
remoteDirectory, programPath, programConfig, matlabOctavePath, programConfig, matlabOctavePath, operatingSystem;
operatingSystem, global_init_file;
vector<string> includepath; vector<string> includepath;
int minCpuNbr {0}, maxCpuNbr {0}; int minCpuNbr {0}, maxCpuNbr {0};
int numberOfThreadsPerJob {1}; int numberOfThreadsPerJob {1};
...@@ -187,24 +177,17 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -187,24 +177,17 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
if (line.empty() || !line.compare(0, 1, "#")) if (line.empty() || !line.compare(0, 1, "#"))
continue; continue;
if (line == "[node]" if (line == "[node]" || line == "[cluster]" || line == "[hooks]" || line == "[paths]")
|| line == "[cluster]"
|| line == "[hooks]"
|| line == "[paths]")
{ {
if (!global_init_file.empty()) if (!includepath.empty())
// we were just in [hooks]
addHooksConfFileElement(global_init_file);
else if (!includepath.empty())
// we were just in [paths] // we were just in [paths]
addPathsConfFileElement(includepath); addPathsConfFileElement(includepath);
else else
// we were just in [node] or [cluster] // we were just in [node] or [cluster]
addParallelConfFileElement(inNode, inCluster, member_nodes, name, addParallelConfFileElement(
computerName, port, minCpuNbr, maxCpuNbr, userName, inNode, inCluster, member_nodes, name, computerName, port, minCpuNbr, maxCpuNbr,
password, remoteDrive, remoteDirectory, userName, password, remoteDrive, remoteDirectory, programPath, programConfig,
programPath, programConfig, matlabOctavePath, singleCompThread, matlabOctavePath, singleCompThread, numberOfThreadsPerJob, operatingSystem);
numberOfThreadsPerJob, operatingSystem);
//! Reset communication vars / option defaults //! Reset communication vars / option defaults
if (line == "[hooks]") if (line == "[hooks]")
...@@ -236,9 +219,8 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -236,9 +219,8 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
inPaths = false; inPaths = false;
} }
name = userName = computerName = port = password = remoteDrive name = userName = computerName = port = password = remoteDrive = remoteDirectory
= remoteDirectory = programPath = programConfig = matlabOctavePath = programPath = programConfig = matlabOctavePath = operatingSystem = "";
= operatingSystem = global_init_file = "";
includepath.clear(); includepath.clear();
minCpuNbr = maxCpuNbr = 0; minCpuNbr = maxCpuNbr = 0;
numberOfThreadsPerJob = 1; numberOfThreadsPerJob = 1;
...@@ -251,7 +233,8 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -251,7 +233,8 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
split(tokenizedLine, line, is_any_of("=")); split(tokenizedLine, line, is_any_of("="));
if (tokenizedLine.size() != 2) if (tokenizedLine.size() != 2)
{ {
cerr << "ERROR (in config file): Options should be formatted as 'option = value'." << endl; cerr << "ERROR (in config file): Options should be formatted as 'option = value'."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
trim(tokenizedLine.front()); trim(tokenizedLine.front());
...@@ -263,12 +246,15 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -263,12 +246,15 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
global_init_file = tokenizedLine.back(); global_init_file = tokenizedLine.back();
else else
{ {
cerr << "ERROR: May not have more than one GlobalInitFile option in [hooks] block." << endl; cerr
<< "ERROR: May not have more than one GlobalInitFile option in [hooks] block."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else else
{ {
cerr << "ERROR: Unrecognized option " << tokenizedLine.front() << " in [hooks] block." << endl; cerr << "ERROR: Unrecognized option " << tokenizedLine.front()
<< " in [hooks] block." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else if (inPaths) else if (inPaths)
...@@ -286,16 +272,17 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -286,16 +272,17 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
} }
else else
{ {
cerr << "ERROR: May not have more than one Include option in [paths] block." << endl; cerr << "ERROR: May not have more than one Include option in [paths] block."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else else
{ {
cerr << "ERROR: Unrecognized option " << tokenizedLine.front() << " in [paths] block." << endl; cerr << "ERROR: Unrecognized option " << tokenizedLine.front()
<< " in [paths] block." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else else if (tokenizedLine.front() == "Name")
if (tokenizedLine.front() == "Name")
name = tokenizedLine.back(); name = tokenizedLine.back();
else if (tokenizedLine.front() == "CPUnbr") else if (tokenizedLine.front() == "CPUnbr")
{ {
...@@ -308,8 +295,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -308,8 +295,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
minCpuNbr = 1; minCpuNbr = 1;
maxCpuNbr = stoi(tokenizedCpuNbr.front()); maxCpuNbr = stoi(tokenizedCpuNbr.front());
} }
else if (tokenizedCpuNbr.size() == 2 else if (tokenizedCpuNbr.size() == 2 && tokenizedCpuNbr[0].at(0) == '['
&& tokenizedCpuNbr[0].at(0) == '['
&& tokenizedCpuNbr[1].at(tokenizedCpuNbr[1].size() - 1) == ']') && tokenizedCpuNbr[1].at(tokenizedCpuNbr[1].size() - 1) == ']')
{ {
tokenizedCpuNbr[0].erase(0, 1); tokenizedCpuNbr[0].erase(0, 1);
...@@ -354,8 +340,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -354,8 +340,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
remoteDrive = tokenizedLine.back(); remoteDrive = tokenizedLine.back();
else if (tokenizedLine.front() == "RemoteDirectory") else if (tokenizedLine.front() == "RemoteDirectory")
remoteDirectory = tokenizedLine.back(); remoteDirectory = tokenizedLine.back();
else if (tokenizedLine.front() == "DynarePath" else if (tokenizedLine.front() == "DynarePath" || tokenizedLine.front() == "ProgramPath")
|| tokenizedLine.front() == "ProgramPath")
programPath = tokenizedLine.back(); programPath = tokenizedLine.back();
else if (tokenizedLine.front() == "ProgramConfig") else if (tokenizedLine.front() == "ProgramConfig")
programConfig = tokenizedLine.back(); programConfig = tokenizedLine.back();
...@@ -370,7 +355,9 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -370,7 +355,9 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
singleCompThread = false; singleCompThread = false;
else else
{ {
cerr << "ERROR (in config file): The value passed to SingleCompThread may only be 'true' or 'false'." << endl; cerr << "ERROR (in config file): The value passed to SingleCompThread may only be "
"'true' or 'false'."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else if (tokenizedLine.front() == "OperatingSystem") else if (tokenizedLine.front() == "OperatingSystem")
...@@ -380,8 +367,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -380,8 +367,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
char_separator sep(" ,;", "()", drop_empty_tokens); char_separator sep(" ,;", "()", drop_empty_tokens);
tokenizer tokens(tokenizedLine.back(), sep); tokenizer tokens(tokenizedLine.back(), sep);
string node_name; string node_name;
for (bool begin_weight{false}; for (bool begin_weight {false}; const auto& token : tokens)
const auto &token : tokens)
{ {
if (token == "(") if (token == "(")
{ {
...@@ -401,7 +387,9 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -401,7 +387,9 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
{ {
if (member_nodes.contains(node_name)) if (member_nodes.contains(node_name))
{ {
cerr << "ERROR (in config file): Node entered twice in specification of cluster." << endl; cerr << "ERROR (in config file): Node entered twice in specification "
"of cluster."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else else
...@@ -415,14 +403,18 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -415,14 +403,18 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
auto weight = stod(token); auto weight = stod(token);
if (weight <= 0) if (weight <= 0)
{ {
cerr << "ERROR (in config file): Misspecification of weights passed to Members option." << endl; cerr << "ERROR (in config file): Misspecification of weights passed to "
"Members option."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
member_nodes[node_name] = weight; member_nodes[node_name] = weight;
} }
catch (const invalid_argument&) catch (const invalid_argument&)
{ {
cerr << "ERROR (in config file): Misspecification of weights passed to Members option." << endl; cerr << "ERROR (in config file): Misspecification of weights passed to "
"Members option."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -432,27 +424,27 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -432,27 +424,27 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
member_nodes[node_name] = 1.0; member_nodes[node_name] = 1.0;
else else
{ {
cerr << "ERROR (in config file): Node entered twice in specification of cluster." << endl; cerr << "ERROR (in config file): Node entered twice in specification of "
"cluster."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
} }
else else
{ {
cerr << "ERROR (in config file): Option " << tokenizedLine.front() << " is invalid." << endl; cerr << "ERROR (in config file): Option " << tokenizedLine.front() << " is invalid."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
} }
if (!global_init_file.empty()) if (!includepath.empty())
addHooksConfFileElement(global_init_file);
else if (!includepath.empty())
addPathsConfFileElement(includepath); addPathsConfFileElement(includepath);
else else
addParallelConfFileElement(inNode, inCluster, member_nodes, name, addParallelConfFileElement(inNode, inCluster, member_nodes, name, computerName, port, minCpuNbr,
computerName, port, minCpuNbr, maxCpuNbr, userName, maxCpuNbr, userName, password, remoteDrive, remoteDirectory,
password, remoteDrive, remoteDirectory,
programPath, programConfig, matlabOctavePath, singleCompThread, programPath, programConfig, matlabOctavePath, singleCompThread,
numberOfThreadsPerJob, operatingSystem); numberOfThreadsPerJob, operatingSystem);
...@@ -460,19 +452,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file) ...@@ -460,19 +452,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
} }
void void
ConfigFile::addHooksConfFileElement(string global_init_file) Configuration::addPathsConfFileElement(vector<string> includepath)
{
if (global_init_file.empty())
{
cerr << "ERROR: The global initialization file must be passed to the GlobalInitFile option." << endl;
exit(EXIT_FAILURE);
}
else
hooks.emplace_back(move(global_init_file));
}
void
ConfigFile::addPathsConfFileElement(vector<string> includepath)
{ {
if (includepath.empty()) if (includepath.empty())
{ {
...@@ -484,12 +464,15 @@ ConfigFile::addPathsConfFileElement(vector<string> includepath) ...@@ -484,12 +464,15 @@ ConfigFile::addPathsConfFileElement(vector<string> includepath)
} }
void void
ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, const member_nodes_t &member_nodes, const string &name, Configuration::addParallelConfFileElement(bool inNode, bool inCluster,
const string &computerName, const string &port, int minCpuNbr, int maxCpuNbr, const member_nodes_t& member_nodes, const string& name,
const string &userName, const string &password, const string &remoteDrive, const string& computerName, const string& port,
const string &remoteDirectory, const string &programPath, const string &programConfig, int minCpuNbr, int maxCpuNbr, const string& userName,
const string &matlabOctavePath, bool singleCompThread, int numberOfThreadsPerJob, const string& password, const string& remoteDrive,
const string &operatingSystem) const string& remoteDirectory, const string& programPath,
const string& programConfig,
const string& matlabOctavePath, bool singleCompThread,
int numberOfThreadsPerJob, const string& operatingSystem)
{ {
//! ADD NODE //! ADD NODE
if (inNode) if (inNode)
...@@ -498,24 +481,22 @@ ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, const member ...@@ -498,24 +481,22 @@ ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, const member
cerr << "Invalid option passed to [node]." << endl; cerr << "Invalid option passed to [node]." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else else if (name.empty() || follower_nodes.contains(name))
if (name.empty() || follower_nodes.contains(name))
{ {
cerr << "ERROR: Every node must be assigned a unique name." << endl; cerr << "ERROR: Every node must be assigned a unique name." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else else
follower_nodes.try_emplace(name, computerName, port, minCpuNbr, maxCpuNbr, userName, follower_nodes.try_emplace(name, computerName, port, minCpuNbr, maxCpuNbr, userName, password,
password, remoteDrive, remoteDirectory, programPath, programConfig, remoteDrive, remoteDirectory, programPath, programConfig,
matlabOctavePath, singleCompThread, numberOfThreadsPerJob, matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
operatingSystem); operatingSystem);
//! ADD CLUSTER //! ADD CLUSTER
else if (inCluster) else if (inCluster)
{ {
if (minCpuNbr > 0 || maxCpuNbr > 0 || !userName.empty() if (minCpuNbr > 0 || maxCpuNbr > 0 || !userName.empty() || !password.empty()
|| !password.empty() || !remoteDrive.empty() || !remoteDirectory.empty() || !remoteDrive.empty() || !remoteDirectory.empty() || !programPath.empty()
|| !programPath.empty() || !programConfig.empty() || !programConfig.empty() || !matlabOctavePath.empty() || !operatingSystem.empty())
|| !matlabOctavePath.empty() || !operatingSystem.empty())
{ {
cerr << "Invalid option passed to [cluster]." << endl; cerr << "Invalid option passed to [cluster]." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -535,18 +516,8 @@ ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, const member ...@@ -535,18 +516,8 @@ ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, const member
} }
void void
ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const Configuration::checkPass([[maybe_unused]] WarningConsolidation& warnings) const
{
for (bool global_init_file_declared{false};
const auto &hook : hooks)
for (const auto &mapit : hook.get_hooks())
if (mapit.first == "global_init_file")
if (exchange(global_init_file_declared, true))
{ {
cerr << "ERROR: Only one global initialization file may be provided." << endl;
exit(EXIT_FAILURE);
}
if (!parallel && !parallel_test) if (!parallel && !parallel_test)
return; return;
...@@ -573,19 +544,22 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const ...@@ -573,19 +544,22 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
} }
catch (const invalid_argument&) catch (const invalid_argument&)
{ {
cerr << "ERROR (node " << follower_node.first << "): the port must be an integer." << endl; cerr << "ERROR (node " << follower_node.first << "): the port must be an integer."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (follower_node.second.computerName == "localhost") // We are working locally if (follower_node.second.computerName == "localhost") // We are working locally
{ {
if (!follower_node.second.remoteDrive.empty()) if (!follower_node.second.remoteDrive.empty())
{ {
cerr << "ERROR (node " << follower_node.first << "): the RemoteDrive option may not be passed for a local node." << endl; cerr << "ERROR (node " << follower_node.first
<< "): the RemoteDrive option may not be passed for a local node." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!follower_node.second.remoteDirectory.empty()) if (!follower_node.second.remoteDirectory.empty())
{ {
cerr << "ERROR (node " << follower_node.first << "): the RemoteDirectory option may not be passed for a local node." << endl; cerr << "ERROR (node " << follower_node.first
<< "): the RemoteDirectory option may not be passed for a local node." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -593,19 +567,26 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const ...@@ -593,19 +567,26 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
{ {
if (follower_node.second.userName.empty()) if (follower_node.second.userName.empty())
{ {
cerr << "ERROR (node " << follower_node.first << "): the UserName option must be passed for every remote node." << endl; cerr << "ERROR (node " << follower_node.first
<< "): the UserName option must be passed for every remote node." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (follower_node.second.operatingSystem == "windows") if (follower_node.second.operatingSystem == "windows")
{ {
if (follower_node.second.password.empty()) if (follower_node.second.password.empty())
{ {
cerr << "ERROR (node " << follower_node.first << "): the Password option must be passed under Windows for every remote node." << endl; cerr << "ERROR (node " << follower_node.first
<< "): the Password option must be passed under Windows for every remote "
"node."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (follower_node.second.remoteDrive.empty()) if (follower_node.second.remoteDrive.empty())
{ {
cerr << "ERROR (node " << follower_node.first << "): the RemoteDrive option must be passed under Windows for every remote node." << endl; cerr << "ERROR (node " << follower_node.first
<< "): the RemoteDrive option must be passed under Windows for every remote "
"node."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -614,19 +595,26 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const ...@@ -614,19 +595,26 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
{ {
if (follower_node.second.password.empty()) if (follower_node.second.password.empty())
{ {
cerr << "ERROR (node " << follower_node.first << "): the Password option must be passed under Windows for every remote node." << endl; cerr << "ERROR (node " << follower_node.first
<< "): the Password option must be passed under Windows for every remote "
"node."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (follower_node.second.remoteDrive.empty()) if (follower_node.second.remoteDrive.empty())
{ {
cerr << "ERROR (node " << follower_node.first << "): the RemoteDrive option must be passed under Windows for every remote node." << endl; cerr << "ERROR (node " << follower_node.first
<< "): the RemoteDrive option must be passed under Windows for every remote "
"node."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
#endif #endif
if (follower_node.second.remoteDirectory.empty()) if (follower_node.second.remoteDirectory.empty())
{ {
cerr << "ERROR (node " << follower_node.first << "): the RemoteDirectory must be specified for every remote node." << endl; cerr << "ERROR (node " << follower_node.first
<< "): the RemoteDirectory must be specified for every remote node." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -641,7 +629,8 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const ...@@ -641,7 +629,8 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
if (!cluster_name.empty() && !clusters.contains(cluster_name)) if (!cluster_name.empty() && !clusters.contains(cluster_name))
{ {
cerr << "ERROR: Cluster Name " << cluster_name << " was not found in the config file." << endl; cerr << "ERROR: Cluster Name " << cluster_name << " was not found in the config file."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -649,14 +638,21 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const ...@@ -649,14 +638,21 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
for (const auto& itmn : cluster.second.member_nodes) for (const auto& itmn : cluster.second.member_nodes)
if (!follower_nodes.contains(itmn.first)) if (!follower_nodes.contains(itmn.first))
{ {
cerr << "Error: node " << itmn.first << " specified in cluster " << cluster.first << " was not found" << endl; cerr << "Error: node " << itmn.first << " specified in cluster " << cluster.first
<< " was not found" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
void void
ConfigFile::transformPass() Configuration::transformPass()
{ {
/* If the user did not specify the GlobalInitFile option, use global_init.m in configuration
directory if it exists */
if (auto default_global_init_file = findConfigFile("global_init.m");
global_init_file.empty() && !default_global_init_file.empty())
global_init_file = default_global_init_file.string();
if (!parallel && !parallel_test) if (!parallel && !parallel_test)
return; return;
...@@ -670,21 +666,21 @@ ConfigFile::transformPass() ...@@ -670,21 +666,21 @@ ConfigFile::transformPass()
} }
#endif #endif
auto cluster_it = cluster_name.empty() ? clusters.find(firstClusterName) : clusters.find(cluster_name); auto& cluster = cluster_name.empty() ? clusters.at(firstClusterName) : clusters.at(cluster_name);
double weight_denominator {0.0}; double weight_denominator {0.0};
for (const auto &it : cluster_it->second.member_nodes) for (const auto& [name, weight] : cluster.member_nodes)
weight_denominator += it.second; weight_denominator += weight;
for (auto &member_node : cluster_it->second.member_nodes) for (auto& [name, weight] : cluster.member_nodes)
member_node.second /= weight_denominator; weight /= weight_denominator;
} }
vector<filesystem::path> vector<filesystem::path>
ConfigFile::getIncludePaths() const Configuration::getIncludePaths() const
{ {
vector<filesystem::path> include_paths; vector<filesystem::path> include_paths;
for (auto path : paths) for (const auto& path : paths)
for (const auto& mapit : path.get_paths()) for (const auto& mapit : path.get_paths())
for (const auto& vecit : mapit.second) for (const auto& vecit : mapit.second)
include_paths.emplace_back(vecit); include_paths.emplace_back(vecit);
...@@ -692,64 +688,51 @@ ConfigFile::getIncludePaths() const ...@@ -692,64 +688,51 @@ ConfigFile::getIncludePaths() const
} }
void void
ConfigFile::writeHooks(ostream &output) const Configuration::writeHooks(ostream& output) const
{ {
for (auto hook : hooks) if (!global_init_file.empty())
for (const auto &mapit : hook.get_hooks()) output << "options_.global_init_file = '" << global_init_file << "';" << endl;
output << "options_." << mapit.first << " = '" << mapit.second << "';" << endl;
} }
void void
ConfigFile::writeCluster(ostream &output) const Configuration::writeCluster(ostream& output) const
{ {
if (!parallel && !parallel_test) if (!parallel && !parallel_test)
return; return;
auto cluster_it = cluster_name.empty() ? clusters.find(firstClusterName) : clusters.find(cluster_name); const auto& cluster
= cluster_name.empty() ? clusters.at(firstClusterName) : clusters.at(cluster_name);
for (int i{1}; for (int i {1}; const auto& [name, node] : follower_nodes)
const auto &follower_node : follower_nodes)
{ {
bool follower_node_in_member_nodes = false; if (!cluster.member_nodes.contains(name))
for (const auto &itmn : cluster_it->second.member_nodes) continue; // Skip nodes not in the selected cluster
if (follower_node.first == itmn.first)
follower_node_in_member_nodes = true;
if (!follower_node_in_member_nodes)
continue;
output << "options_.parallel"; output << "options_.parallel";
if (i > 1) if (i > 1)
output << "(" << i << ")"; output << "(" << i << ")";
i++; i++;
output << " = struct('Local', "; output << " = struct('Local', " << noboolalpha << (node.computerName == "localhost") << ", "
if (follower_node.second.computerName == "localhost") << "'ComputerName', '" << node.computerName << "', "
output << "1, "; << "'Port', '" << node.port << "', "
else << "'CPUnbr', [" << node.minCpuNbr << ":" << node.maxCpuNbr << "], "
output << "0, "; << "'UserName', '" << node.userName << "', "
<< "'Password', '" << node.password << "', "
output << "'ComputerName', '" << follower_node.second.computerName << "', " << "'RemoteDrive', '" << node.remoteDrive << "', "
<< "'Port', '" << follower_node.second.port << "', " << "'RemoteDirectory', '" << node.remoteDirectory
<< "'CPUnbr', [" << follower_node.second.minCpuNbr << ":" << follower_node.second.maxCpuNbr << "], " << "', "
<< "'UserName', '" << follower_node.second.userName << "', "
<< "'Password', '" << follower_node.second.password << "', "
<< "'RemoteDrive', '" << follower_node.second.remoteDrive << "', "
<< "'RemoteDirectory', '" << follower_node.second.remoteDirectory << "', "
// The following should be switched back to “ProgramPath” once we move to Dragonfly // The following should be switched back to “ProgramPath” once we move to Dragonfly
<< "'DynarePath', '" << follower_node.second.programPath << "', " << "'DynarePath', '" << node.programPath << "', "
<< "'ProgramConfig', '" << follower_node.second.programConfig << "', " << "'ProgramConfig', '" << node.programConfig << "', "
<< "'MatlabOctavePath', '" << follower_node.second.matlabOctavePath << "', " << "'MatlabOctavePath', '" << node.matlabOctavePath << "', "
<< "'OperatingSystem', '" << follower_node.second.operatingSystem << "', " << "'OperatingSystem', '" << node.operatingSystem << "', "
<< "'NodeWeight', '" << cluster_it->second.member_nodes.at(follower_node.first) << "', " << "'NodeWeight', '" << cluster.member_nodes.at(name) << "', "
<< "'NumberOfThreadsPerJob', " << follower_node.second.numberOfThreadsPerJob << ", "; << "'NumberOfThreadsPerJob', " << node.numberOfThreadsPerJob << ", "
<< "'SingleCompThread', '" << boolalpha << node.singleCompThread << "');" << endl;
if (follower_node.second.singleCompThread)
output << "'SingleCompThread', 'true');" << endl;
else
output << "'SingleCompThread', 'false');" << endl;
} }
// Default values for the following two are both in DynareMain.cc and matlab/default_option_values.m // Default values for the following two are both in DynareMain.cc and
// matlab/default_option_values.m
if (parallel_follower_open_mode) if (parallel_follower_open_mode)
output << "options_.parallel_info.leaveSlaveOpen = 1;" << endl; output << "options_.parallel_info.leaveSlaveOpen = 1;" << endl;
if (!parallel_use_psexec) if (!parallel_use_psexec)
...@@ -759,14 +742,18 @@ ConfigFile::writeCluster(ostream &output) const ...@@ -759,14 +742,18 @@ ConfigFile::writeCluster(ostream &output) const
output << "InitializeComputationalEnvironment();" << endl; output << "InitializeComputationalEnvironment();" << endl;
if (parallel_test) if (parallel_test)
output << "ErrorCode = AnalyseComputationalEnvironment(options_.parallel, options_.parallel_info);" << endl output
<< "disp(['AnalyseComputationalEnvironment returned with Error Code: ' num2str(ErrorCode)]);" << endl << "ErrorCode = AnalyseComputationalEnvironment(options_.parallel, options_.parallel_info);"
<< endl
<< "disp(['AnalyseComputationalEnvironment returned with Error Code: ' "
"num2str(ErrorCode)]);"
<< endl
<< "diary off;" << endl << "diary off;" << endl
<< "return;" << endl; << "return;" << endl;
} }
void void
ConfigFile::writeEndParallel(ostream &output) const Configuration::writeEndParallel(ostream& output) const
{ {
if ((!parallel && !parallel_test) || !parallel_follower_open_mode) if ((!parallel && !parallel_test) || !parallel_follower_open_mode)
return; return;
...@@ -775,3 +762,46 @@ ConfigFile::writeEndParallel(ostream &output) const ...@@ -775,3 +762,46 @@ ConfigFile::writeEndParallel(ostream &output) const
<< " closeSlave(options_.parallel,options_.parallel_info.RemoteTmpFolder);" << endl << " closeSlave(options_.parallel,options_.parallel_info.RemoteTmpFolder);" << endl
<< "end" << endl; << "end" << endl;
} }
filesystem::path
Configuration::findConfigFile(const string& filename)
{
#ifdef _WIN32
array<wchar_t, MAX_PATH + 1> appdata;
if (SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_DONT_VERIFY, nullptr, SHGFP_TYPE_CURRENT,
appdata.data())
== S_OK)
{
filesystem::path candidate {filesystem::path {appdata.data()} / "dynare" / filename};
if (exists(candidate))
return candidate;
}
#else
filesystem::path xdg_config_home;
if (auto xdg_config_home_env = getenv("XDG_CONFIG_HOME"); xdg_config_home_env)
xdg_config_home = xdg_config_home_env;
if (auto home = getenv("HOME"); xdg_config_home.empty() && home)
xdg_config_home = filesystem::path {home} / ".config";
if (!xdg_config_home.empty())
{
filesystem::path candidate {xdg_config_home / "dynare" / filename};
if (exists(candidate))
return candidate;
}
string xdg_config_dirs;
if (auto xdg_config_dirs_env = getenv("XDG_CONFIG_DIRS"); xdg_config_dirs_env)
xdg_config_dirs = xdg_config_dirs_env;
if (xdg_config_dirs.empty())
xdg_config_dirs = "/etc/xdg";
for (const auto& dir : DataTree::strsplit(xdg_config_dirs, ':'))
{
filesystem::path candidate {filesystem::path {dir} / "dynare" / filename};
if (exists(candidate))
return candidate;
}
#endif
return {};
}
...@@ -17,57 +17,49 @@ ...@@ -17,57 +17,49 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef _CONFIG_FILE_HH #ifndef CONFIGURATION_HH
#define _CONFIG_FILE_HH #define CONFIGURATION_HH
#include <filesystem>
#include <map> #include <map>
#include <vector> #include <vector>
#include <filesystem>
#include "WarningConsolidation.hh" #include "WarningConsolidation.hh"
using namespace std; using namespace std;
using member_nodes_t = map<string, double>; /* The abstract representation of the configuration.
Merges information from the command-line and from the configuration file. */
class Hook class Configuration
{ {
public: public:
explicit Hook(string global_init_file_arg); Configuration(bool parallel_arg, bool parallel_test_arg, bool parallel_follower_open_mode_arg,
bool parallel_use_psexec_arg, string cluster_name);
private: private:
map<string, string> hooks; using member_nodes_t = map<string, double>;
public:
map<string, string>
get_hooks() const
{
return hooks;
};
};
class Path class Path
{ {
public: public:
explicit Path(vector<string> includepath_arg); explicit Path(vector<string> includepath_arg);
private: [[nodiscard]] map<string, vector<string>>
map<string, vector<string>> paths;
public:
map<string, vector<string>>
get_paths() const get_paths() const
{ {
return paths; return paths;
}; }
private:
map<string, vector<string>> paths;
}; };
class FollowerNode struct FollowerNode
{ {
friend class ConfigFile; FollowerNode(string computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg,
public: string userName_arg, string password_arg, string remoteDrive_arg,
FollowerNode(string computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string userName_arg, string remoteDirectory_arg, string programPath_arg, string programConfig_arg,
string password_arg, string remoteDrive_arg, string remoteDirectory_arg, string matlabOctavePath_arg, bool singleCompThread_arg,
string programPath_arg, string programConfig_arg, string matlabOctavePath_arg, bool singleCompThread_arg,
int numberOfThreadsPerJob_arg, string operatingSystem_arg); int numberOfThreadsPerJob_arg, string operatingSystem_arg);
protected:
const string computerName, port; const string computerName, port;
int minCpuNbr, maxCpuNbr; int minCpuNbr, maxCpuNbr;
const string userName, password; const string userName, password;
...@@ -78,55 +70,51 @@ protected: ...@@ -78,55 +70,51 @@ protected:
const string operatingSystem; const string operatingSystem;
}; };
class Cluster struct Cluster
{ {
friend class ConfigFile;
public:
explicit Cluster(member_nodes_t member_nodes_arg); explicit Cluster(member_nodes_t member_nodes_arg);
protected:
member_nodes_t member_nodes; 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_follower_open_mode_arg,
bool parallel_use_psexec_arg, string cluster_name);
private:
const bool parallel, parallel_test, parallel_follower_open_mode, parallel_use_psexec; const bool parallel, parallel_test, parallel_follower_open_mode, parallel_use_psexec;
const string cluster_name; const string cluster_name;
string firstClusterName; string firstClusterName;
//! Hooks //! Hooks
vector<Hook> hooks; string global_init_file;
//! Paths //! Paths
vector<Path> paths; vector<Path> paths;
//! Cluster Table //! Cluster Table
map<string, Cluster> clusters; map<string, Cluster> clusters;
//! Node Map //! Node Map
map<string, FollowerNode> follower_nodes; map<string, FollowerNode> follower_nodes;
//! Add Hooks
void addHooksConfFileElement(string global_init_file);
//! Add Paths //! Add Paths
void addPathsConfFileElement(vector<string> includepath); void addPathsConfFileElement(vector<string> includepath);
//! Add a FollowerNode or a Cluster object //! Add a FollowerNode or a Cluster object
void addParallelConfFileElement(bool inNode, bool inCluster, const member_nodes_t &member_nodes, const string &name, void addParallelConfFileElement(bool inNode, bool inCluster, const member_nodes_t& member_nodes,
const string &computerName, const string &port, int minCpuNbr, int maxCpuNbr, const string& name, const string& computerName,
const string &userName, const string &password, const string &remoteDrive, const string& port, int minCpuNbr, int maxCpuNbr,
const string &remoteDirectory, const string &programPath, const string &programConfig, const string& userName, const string& password,
const string &matlabOctavePath, bool singleCompThread, int numberOfThreadsPerJob, const string& remoteDrive, const string& remoteDirectory,
const string &operatingSystem); const string& programPath, const string& programConfig,
const string& matlabOctavePath, bool singleCompThread,
int numberOfThreadsPerJob, const string& operatingSystem);
/* Given a filename (e.g. dynare.ini), looks for it in the configuration directory:
– if under Linux or macOS, look into the “dynare” subdirectory of the XDG
configuration directories (following the default values and the precedence order specified in
the XDG specification)
– if under Windows, look into %APPDATA%\dynare\
The returned path will be empty if the file is not found. */
[[nodiscard]] static filesystem::path findConfigFile(const string& filename);
public: public:
//! Parse config file //! Parse config file
void getConfigFileInfo(const filesystem::path &parallel_config_file); void getConfigFileInfo(const filesystem::path& conffile_option, WarningConsolidation& warnings);
//! Check Pass //! Check Pass
void checkPass(WarningConsolidation& warnings) const; void checkPass(WarningConsolidation& warnings) const;
//! Check Pass //! Check Pass
void transformPass(); void transformPass();
//! Get Path Info //! Get Path Info
vector<filesystem::path> getIncludePaths() const; [[nodiscard]] vector<filesystem::path> getIncludePaths() const;
//! Write any hooks //! Write any hooks
void writeHooks(ostream& output) const; void writeHooks(ostream& output) const;
//! Create options_.parallel structure, write options //! Create options_.parallel structure, write options
...@@ -135,4 +123,4 @@ public: ...@@ -135,4 +123,4 @@ public:
void writeEndParallel(ostream& output) const; void writeEndParallel(ostream& output) const;
}; };
#endif // ! CONFIG_FILE_HH #endif
/* /*
* Copyright © 2003-2023 Dynare Team * Copyright © 2003-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -17,13 +17,14 @@ ...@@ -17,13 +17,14 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <algorithm> #include <algorithm>
#include <iterator> #include <cassert>
#include <cstdlib>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <iostream>
#include <iterator>
#include <ranges>
#include "DataTree.hh" #include "DataTree.hh"
...@@ -46,13 +47,13 @@ DataTree::initConstants() ...@@ -46,13 +47,13 @@ DataTree::initConstants()
Pi = AddNonNegativeConstant("3.141592653589793"); Pi = AddNonNegativeConstant("3.141592653589793");
} }
DataTree::DataTree(SymbolTable &symbol_table_arg, DataTree::DataTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, ExternalFunctionsTable& external_functions_table_arg,
bool is_dynamic_arg) : HeterogeneityTable& heterogeneity_table_arg, bool is_dynamic_arg) :
symbol_table {symbol_table_arg}, symbol_table {symbol_table_arg},
num_constants {num_constants_arg}, num_constants {num_constants_arg},
external_functions_table {external_functions_table_arg}, external_functions_table {external_functions_table_arg},
heterogeneity_table {heterogeneity_table_arg},
is_dynamic {is_dynamic_arg} is_dynamic {is_dynamic_arg}
{ {
initConstants(); initConstants();
...@@ -62,19 +63,21 @@ DataTree::DataTree(const DataTree &d) : ...@@ -62,19 +63,21 @@ DataTree::DataTree(const DataTree &d) :
symbol_table {d.symbol_table}, symbol_table {d.symbol_table},
num_constants {d.num_constants}, num_constants {d.num_constants},
external_functions_table {d.external_functions_table}, external_functions_table {d.external_functions_table},
heterogeneity_table {d.heterogeneity_table},
is_dynamic {d.is_dynamic}, is_dynamic {d.is_dynamic},
local_variables_vector {d.local_variables_vector} local_variables_vector {d.local_variables_vector}
{ {
// Constants must be initialized first because they are used in some Add* methods // Constants must be initialized first because they are used in some Add* methods
initConstants(); initConstants();
// See commment in DataTree::operator=() for the rationale
for (int symb_id : d.local_variables_vector)
local_variables_table[symb_id] = d.local_variables_table.at(symb_id)->clone(*this);
for (const auto& it : d.node_list) for (const auto& it : d.node_list)
it->clone(*this); it->clone(*this);
assert(node_list.size() == d.node_list.size()); assert(node_list.size() == d.node_list.size());
for (const auto &[symb_id, value] : d.local_variables_table)
local_variables_table[symb_id] = value->clone(*this);
} }
DataTree& DataTree&
...@@ -83,6 +86,7 @@ DataTree::operator=(const DataTree &d) ...@@ -83,6 +86,7 @@ DataTree::operator=(const DataTree &d)
assert(&symbol_table == &d.symbol_table); assert(&symbol_table == &d.symbol_table);
assert(&num_constants == &d.num_constants); assert(&num_constants == &d.num_constants);
assert(&external_functions_table == &d.external_functions_table); assert(&external_functions_table == &d.external_functions_table);
assert(&heterogeneity_table == &d.heterogeneity_table);
assert(is_dynamic == d.is_dynamic); assert(is_dynamic == d.is_dynamic);
num_const_node_map.clear(); num_const_node_map.clear();
...@@ -125,8 +129,7 @@ DataTree::AddNonNegativeConstant(const string &value) ...@@ -125,8 +129,7 @@ DataTree::AddNonNegativeConstant(const string &value)
{ {
int id = num_constants.AddNonNegativeConstant(value); int id = num_constants.AddNonNegativeConstant(value);
if (auto it = num_const_node_map.find(id); if (auto it = num_const_node_map.find(id); it != num_const_node_map.end())
it != num_const_node_map.end())
return it->second; return it->second;
auto sp = make_unique<NumConstNode>(*this, node_list.size(), id); auto sp = make_unique<NumConstNode>(*this, node_list.size(), id);
...@@ -145,8 +148,7 @@ DataTree::AddVariable(int symb_id, int lag) ...@@ -145,8 +148,7 @@ DataTree::AddVariable(int symb_id, int lag)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (auto it = variable_node_map.find({ symb_id, lag }); if (auto it = variable_node_map.find({symb_id, lag}); it != variable_node_map.end())
it != variable_node_map.end())
return it->second; return it->second;
auto sp = make_unique<VariableNode>(*this, node_list.size(), symb_id, lag); auto sp = make_unique<VariableNode>(*this, node_list.size(), symb_id, lag);
...@@ -162,7 +164,8 @@ DataTree::getVariable(int symb_id, int lag) const ...@@ -162,7 +164,8 @@ DataTree::getVariable(int symb_id, int lag) const
auto it = variable_node_map.find({symb_id, lag}); auto it = variable_node_map.find({symb_id, lag});
if (it == variable_node_map.end()) if (it == variable_node_map.end())
{ {
cerr << "DataTree::getVariable: unknown variable node for symb_id=" << symb_id << " and lag=" << lag << endl; cerr << "DataTree::getVariable: unknown variable node for symb_id=" << symb_id
<< " and lag=" << lag << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
return it->second; return it->second;
...@@ -208,7 +211,7 @@ DataTree::AddPlus(expr_t iArg1, expr_t iArg2) ...@@ -208,7 +211,7 @@ DataTree::AddPlus(expr_t iArg1, expr_t iArg2)
// To treat commutativity of "+" // To treat commutativity of "+"
// Nodes iArg1 and iArg2 are sorted by index // Nodes iArg1 and iArg2 are sorted by index
if (iArg1->idx > iArg2->idx && !no_commutativity) if (iArg1->idx > iArg2->idx && !no_commutativity) // NOLINT(clang-analyzer-core.NullDereference)
swap(iArg1, iArg2); swap(iArg1, iArg2);
return AddBinaryOp(iArg1, BinaryOpcode::plus, iArg2); return AddBinaryOp(iArg1, BinaryOpcode::plus, iArg2);
} }
...@@ -250,8 +253,7 @@ DataTree::AddUMinus(expr_t iArg1) ...@@ -250,8 +253,7 @@ DataTree::AddUMinus(expr_t iArg1)
return Zero; return Zero;
// Simplify -(-x) in x // Simplify -(-x) in x
if (auto uarg = dynamic_cast<UnaryOpNode *>(iArg1); if (auto uarg = dynamic_cast<UnaryOpNode*>(iArg1); uarg && uarg->op_code == UnaryOpcode::uminus)
uarg && uarg->op_code == UnaryOpcode::uminus)
return uarg->arg; return uarg->arg;
return AddUnaryOp(UnaryOpcode::uminus, iArg1); return AddUnaryOp(UnaryOpcode::uminus, iArg1);
...@@ -287,7 +289,7 @@ DataTree::AddTimes(expr_t iArg1, expr_t iArg2) ...@@ -287,7 +289,7 @@ DataTree::AddTimes(expr_t iArg1, expr_t iArg2)
// To treat commutativity of "*" // To treat commutativity of "*"
// Nodes iArg1 and iArg2 are sorted by index // Nodes iArg1 and iArg2 are sorted by index
if (iArg1->idx > iArg2->idx && !no_commutativity) if (iArg1->idx > iArg2->idx && !no_commutativity) // NOLINT(clang-analyzer-core.NullDereference)
swap(iArg1, iArg2); swap(iArg1, iArg2);
return AddBinaryOp(iArg1, BinaryOpcode::times, iArg2); return AddBinaryOp(iArg1, BinaryOpcode::times, iArg2);
} }
...@@ -668,7 +670,8 @@ DataTree::AddSteadyStateParamDeriv(expr_t iArg1, int param_symb_id) ...@@ -668,7 +670,8 @@ DataTree::AddSteadyStateParamDeriv(expr_t iArg1, int param_symb_id)
expr_t expr_t
DataTree::AddSteadyStateParam2ndDeriv(expr_t iArg1, int param1_symb_id, int param2_symb_id) DataTree::AddSteadyStateParam2ndDeriv(expr_t iArg1, int param1_symb_id, int param2_symb_id)
{ {
return AddUnaryOp(UnaryOpcode::steadyStateParam2ndDeriv, iArg1, 0, param1_symb_id, param2_symb_id); return AddUnaryOp(UnaryOpcode::steadyStateParam2ndDeriv, iArg1, 0, param1_symb_id,
param2_symb_id);
} }
expr_t expr_t
...@@ -680,8 +683,7 @@ DataTree::AddExpectation(int iArg1, expr_t iArg2) ...@@ -680,8 +683,7 @@ DataTree::AddExpectation(int iArg1, expr_t iArg2)
expr_t expr_t
DataTree::AddVarExpectation(const string& model_name) DataTree::AddVarExpectation(const string& model_name)
{ {
if (auto it = var_expectation_node_map.find(model_name); if (auto it = var_expectation_node_map.find(model_name); it != var_expectation_node_map.end())
it != var_expectation_node_map.end())
return it->second; return it->second;
auto sp = make_unique<VarExpectationNode>(*this, node_list.size(), model_name); auto sp = make_unique<VarExpectationNode>(*this, node_list.size(), model_name);
...@@ -694,8 +696,7 @@ DataTree::AddVarExpectation(const string &model_name) ...@@ -694,8 +696,7 @@ DataTree::AddVarExpectation(const string &model_name)
expr_t expr_t
DataTree::AddPacExpectation(const string& model_name) DataTree::AddPacExpectation(const string& model_name)
{ {
if (auto it = pac_expectation_node_map.find(model_name); if (auto it = pac_expectation_node_map.find(model_name); it != pac_expectation_node_map.end())
it != pac_expectation_node_map.end())
return it->second; return it->second;
auto sp = make_unique<PacExpectationNode>(*this, node_list.size(), model_name); auto sp = make_unique<PacExpectationNode>(*this, node_list.size(), model_name);
...@@ -757,43 +758,56 @@ DataTree::AddExternalFunction(int symb_id, const vector<expr_t> &arguments) ...@@ -757,43 +758,56 @@ DataTree::AddExternalFunction(int symb_id, const vector<expr_t> &arguments)
} }
expr_t expr_t
DataTree::AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index) DataTree::AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index)
{ {
assert(symbol_table.getType(top_level_symb_id) == SymbolType::externalFunction); assert(symbol_table.getType(top_level_symb_id) == SymbolType::externalFunction);
if (auto it = first_deriv_external_function_node_map.find({ arguments, input_index, top_level_symb_id }); if (auto it
= first_deriv_external_function_node_map.find({arguments, input_index, top_level_symb_id});
it != first_deriv_external_function_node_map.end()) it != first_deriv_external_function_node_map.end())
return it->second; return it->second;
auto sp = make_unique<FirstDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id, arguments, input_index); auto sp = make_unique<FirstDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id,
arguments, input_index);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
first_deriv_external_function_node_map.try_emplace({ arguments, input_index, top_level_symb_id }, p); first_deriv_external_function_node_map.try_emplace({arguments, input_index, top_level_symb_id},
p);
return p; return p;
} }
expr_t expr_t
DataTree::AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index1, int input_index2) 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) == SymbolType::externalFunction); assert(symbol_table.getType(top_level_symb_id) == SymbolType::externalFunction);
if (auto it = second_deriv_external_function_node_map.find({ arguments, input_index1, input_index2, if (auto it = second_deriv_external_function_node_map.find(
top_level_symb_id }); {arguments, input_index1, input_index2, top_level_symb_id});
it != second_deriv_external_function_node_map.end()) it != second_deriv_external_function_node_map.end())
return it->second; return it->second;
auto sp = make_unique<SecondDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id, arguments, input_index1, input_index2); auto sp = make_unique<SecondDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id,
arguments, input_index1, input_index2);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
second_deriv_external_function_node_map.try_emplace({ arguments, input_index1, input_index2, top_level_symb_id }, p); second_deriv_external_function_node_map.try_emplace(
{arguments, input_index1, input_index2, top_level_symb_id}, p);
return p; return p;
} }
expr_t
DataTree::AddSum(expr_t arg)
{
return AddUnaryOp(UnaryOpcode::sum, arg);
}
bool bool
DataTree::isSymbolUsed(int symb_id) const DataTree::isSymbolUsed(int symb_id) const
{ {
for (const auto &[symb_lag, expr] : variable_node_map) if (ranges::any_of(views::keys(variable_node_map),
if (symb_lag.first == symb_id) [=](const auto& symb_lag) { return symb_lag.first == symb_id; }))
return true; return true;
if (local_variables_table.contains(symb_id)) if (local_variables_table.contains(symb_id))
...@@ -840,18 +854,18 @@ DataTree::addAllParamDerivId([[maybe_unused]] set<int> &deriv_id_set) ...@@ -840,18 +854,18 @@ DataTree::addAllParamDerivId([[maybe_unused]] set<int> &deriv_id_set)
bool bool
DataTree::isUnaryOpUsed(UnaryOpcode opcode) const DataTree::isUnaryOpUsed(UnaryOpcode opcode) const
{ {
return any_of(unary_op_node_map.begin(), unary_op_node_map.end(), return ranges::any_of(views::keys(unary_op_node_map),
[=](const auto &it) { return get<1>(it.first) == opcode; }); [=](const auto& key) { return get<1>(key) == opcode; });
} }
bool bool
DataTree::isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const DataTree::isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const
{ {
set<int> var; set<int> var;
for (const auto &it : unary_op_node_map) for (const auto& [key, value] : unary_op_node_map)
if (get<1>(it.first) == opcode) if (get<1>(key) == opcode)
{ {
it.second->collectVariables(type, var); value->collectVariables(type, var);
if (!var.empty()) if (!var.empty())
return true; return true;
} }
...@@ -861,18 +875,18 @@ DataTree::isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const ...@@ -861,18 +875,18 @@ DataTree::isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const
bool bool
DataTree::isBinaryOpUsed(BinaryOpcode opcode) const DataTree::isBinaryOpUsed(BinaryOpcode opcode) const
{ {
return any_of(binary_op_node_map.begin(), binary_op_node_map.end(), return ranges::any_of(views::keys(binary_op_node_map),
[=](const auto &it) { return get<2>(it.first) == opcode; }); [=](const auto& key) { return get<2>(key) == opcode; });
} }
bool bool
DataTree::isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) const DataTree::isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) const
{ {
set<int> var; set<int> var;
for (const auto &it : binary_op_node_map) for (const auto& [key, value] : binary_op_node_map)
if (get<2>(it.first) == opcode) if (get<2>(key) == opcode)
{ {
it.second->collectVariables(type, var); value->collectVariables(type, var);
if (!var.empty()) if (!var.empty())
return true; return true;
} }
...@@ -897,7 +911,9 @@ DataTree::writeCHelpersDefinition(ostream &output) const ...@@ -897,7 +911,9 @@ DataTree::writeCHelpersDefinition(ostream &output) const
<< "inline double" << endl << "inline double" << endl
<< "getPowerDeriv(double x, double p, int k)" << endl << "getPowerDeriv(double x, double p, int k)" << endl
<< "{" << endl << "{" << endl
<< " if (fabs(x) < " << power_deriv_near_zero << " && p > 0 && k > p && fabs(p-nearbyint(p)) < " << power_deriv_near_zero << ')' << endl << " if (fabs(x) < " << power_deriv_near_zero
<< " && p >= 0 && k > p && fabs(p-nearbyint(p)) < " << power_deriv_near_zero << ')'
<< endl
<< " return 0.0;" << endl << " return 0.0;" << endl
<< " else" << endl << " else" << endl
<< " {" << endl << " {" << endl
...@@ -932,8 +948,7 @@ DataTree::strsplit(string_view str, char delim) ...@@ -932,8 +948,7 @@ DataTree::strsplit(string_view str, char delim)
while (true) while (true)
{ {
size_t idx {str.find(delim)}; size_t idx {str.find(delim)};
if (auto sub {str.substr(0, idx)}; if (auto sub {str.substr(0, idx)}; !sub.empty())
!sub.empty())
result.emplace_back(sub); result.emplace_back(sub);
if (idx == string_view::npos) if (idx == string_view::npos)
break; break;
...@@ -943,10 +958,10 @@ DataTree::strsplit(string_view str, char delim) ...@@ -943,10 +958,10 @@ DataTree::strsplit(string_view str, char delim)
} }
filesystem::path filesystem::path
DataTree::packageDir(string_view package) DataTree::packageDir(const string_view& package)
{ {
filesystem::path d; filesystem::path d;
for (const auto &it : strsplit(move(package), '.')) for (const auto& it : strsplit(package, '.'))
d /= "+" + it; d /= "+" + it;
return d; return d;
} }
...@@ -956,7 +971,7 @@ DataTree::writeToFileIfModified(stringstream &new_contents, const filesystem::pa ...@@ -956,7 +971,7 @@ DataTree::writeToFileIfModified(stringstream &new_contents, const filesystem::pa
{ {
ifstream old_file {filename, ios::in | ios::binary}; ifstream old_file {filename, ios::in | ios::binary};
if (old_file.is_open() if (old_file.is_open()
&& equal(istreambuf_iterator<char>{old_file}, istreambuf_iterator<char>{}, && ranges::equal(istreambuf_iterator<char> {old_file}, istreambuf_iterator<char> {},
istreambuf_iterator<char> {new_contents}, istreambuf_iterator<char> {})) istreambuf_iterator<char> {new_contents}, istreambuf_iterator<char> {}))
return; return;
old_file.close(); old_file.close();
...@@ -969,7 +984,7 @@ DataTree::writeToFileIfModified(stringstream &new_contents, const filesystem::pa ...@@ -969,7 +984,7 @@ DataTree::writeToFileIfModified(stringstream &new_contents, const filesystem::pa
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
copy(istreambuf_iterator<char>{new_contents}, istreambuf_iterator<char>{}, ranges::copy(istreambuf_iterator<char> {new_contents}, istreambuf_iterator<char> {},
ostreambuf_iterator<char> {new_file}); ostreambuf_iterator<char> {new_file});
new_file.close(); new_file.close();
} }
/* /*
* Copyright © 2003-2023 Dynare Team * Copyright © 2003-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -17,25 +17,26 @@ ...@@ -17,25 +17,26 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef _DATATREE_HH #ifndef DATA_TREE_HH
#define _DATATREE_HH #define DATA_TREE_HH
#include <string>
#include <map>
#include <vector>
#include <sstream>
#include <iomanip>
#include <cmath> #include <cmath>
#include <utility>
#include <memory>
#include <filesystem> #include <filesystem>
#include <iomanip>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <string_view> #include <string_view>
#include <utility>
#include <vector>
#include "SymbolTable.hh"
#include "NumericalConstants.hh"
#include "ExternalFunctionsTable.hh"
#include "ExprNode.hh" #include "ExprNode.hh"
#include "ExternalFunctionsTable.hh"
#include "HeterogeneityTable.hh"
#include "NumericalConstants.hh"
#include "SubModel.hh" #include "SubModel.hh"
#include "SymbolTable.hh"
using namespace std; using namespace std;
...@@ -48,7 +49,11 @@ public: ...@@ -48,7 +49,11 @@ public:
NumericalConstants& num_constants; NumericalConstants& num_constants;
//! A reference to the external functions table //! A reference to the external functions table
ExternalFunctionsTable& external_functions_table; ExternalFunctionsTable& external_functions_table;
// A reference to the heterogeneity table
HeterogeneityTable& heterogeneity_table;
//! Is it possible to use leads/lags on variable nodes? //! Is it possible to use leads/lags on variable nodes?
/* NB: This data member cannot be replaced by a virtual method, because this information is needed
in AddVariable(), which itself can be called from the copy constructor. */
const bool is_dynamic; const bool is_dynamic;
private: private:
...@@ -60,8 +65,10 @@ private: ...@@ -60,8 +65,10 @@ private:
using variable_node_map_t = map<pair<int, int>, VariableNode*>; using variable_node_map_t = map<pair<int, int>, VariableNode*>;
variable_node_map_t variable_node_map; variable_node_map_t variable_node_map;
//! (arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags) -> UnaryOpNode //! (arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags) ->
using unary_op_node_map_t = map<tuple<expr_t, UnaryOpcode, int, int, int, string, vector<int>>, UnaryOpNode *>; //! UnaryOpNode
using unary_op_node_map_t
= map<tuple<expr_t, UnaryOpcode, int, int, int, string, vector<int>>, UnaryOpNode*>;
unary_op_node_map_t unary_op_node_map; unary_op_node_map_t unary_op_node_map;
//! ( arg1, arg2, opCode, order of Power Derivative) -> BinaryOpNode //! ( arg1, arg2, opCode, order of Power Derivative) -> BinaryOpNode
...@@ -89,11 +96,13 @@ private: ...@@ -89,11 +96,13 @@ private:
pac_target_nonstationary_node_map_t pac_target_nonstationary_node_map; pac_target_nonstationary_node_map_t pac_target_nonstationary_node_map;
// (arguments, deriv_idx, symb_id) -> FirstDerivExternalFunctionNode // (arguments, deriv_idx, symb_id) -> FirstDerivExternalFunctionNode
using first_deriv_external_function_node_map_t = map<tuple<vector<expr_t>, int, int>, FirstDerivExternalFunctionNode *>; using first_deriv_external_function_node_map_t
= map<tuple<vector<expr_t>, int, int>, FirstDerivExternalFunctionNode*>;
first_deriv_external_function_node_map_t first_deriv_external_function_node_map; first_deriv_external_function_node_map_t first_deriv_external_function_node_map;
// (arguments, deriv_idx1, deriv_idx2, symb_id) -> SecondDerivExternalFunctionNode // (arguments, deriv_idx1, deriv_idx2, symb_id) -> SecondDerivExternalFunctionNode
using second_deriv_external_function_node_map_t = map<tuple<vector<expr_t>, int, int, int>, SecondDerivExternalFunctionNode *>; using second_deriv_external_function_node_map_t
= map<tuple<vector<expr_t>, int, int, int>, SecondDerivExternalFunctionNode*>;
second_deriv_external_function_node_map_t second_deriv_external_function_node_map; second_deriv_external_function_node_map_t second_deriv_external_function_node_map;
// Flag to disable simplifications related to commutativity of addition and multiplication // Flag to disable simplifications related to commutativity of addition and multiplication
...@@ -102,11 +111,12 @@ private: ...@@ -102,11 +111,12 @@ private:
protected: protected:
//! Stores local variables value (maps symbol ID to corresponding node) //! Stores local variables value (maps symbol ID to corresponding node)
map<int, expr_t> local_variables_table; map<int, expr_t> local_variables_table;
//! Stores the order of appearance of local variables in the model block. Needed following change in #563 //! Stores the order of appearance of local variables in the model block. Needed following change
//! in #563
vector<int> local_variables_vector; vector<int> local_variables_vector;
//! Internal implementation of ParamUsedWithLeadLag() //! Internal implementation of ParamUsedWithLeadLag()
bool ParamUsedWithLeadLagInternal() const; [[nodiscard]] bool ParamUsedWithLeadLagInternal() const;
/* Writes the contents of “new_contents” to the file “filename”. However, if /* Writes the contents of “new_contents” to the file “filename”. However, if
the file already exists and would not be modified by this operation, then do the file already exists and would not be modified by this operation, then do
...@@ -119,18 +129,21 @@ private: ...@@ -119,18 +129,21 @@ private:
//! The list of nodes //! The list of nodes
vector<unique_ptr<ExprNode>> node_list; vector<unique_ptr<ExprNode>> node_list;
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 = "", const vector<int> &adl_lags = vector<int>()); inline expr_t AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set = 0,
inline expr_t AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder = 0); int param1_symb_id = 0, int param2_symb_id = 0,
const string& adl_param_name = "",
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); inline expr_t AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3);
//! Initializes the predefined constants, used only from the constructors //! Initializes the predefined constants, used only from the constructors
void initConstants(); void initConstants();
public: public:
DataTree(SymbolTable &symbol_table_arg, DataTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, ExternalFunctionsTable& external_functions_table_arg,
bool is_static_args = false); HeterogeneityTable& heterogeneity_table_arg, bool is_dynamic_arg = false);
virtual ~DataTree() = default; virtual ~DataTree() = default;
...@@ -159,7 +172,7 @@ public: ...@@ -159,7 +172,7 @@ public:
//! Gets a variable //! Gets a variable
/*! Same as AddVariable, except that it fails if the variable node has not /*! Same as AddVariable, except that it fails if the variable node has not
already been created */ already been created */
VariableNode *getVariable(int symb_id, int lag = 0) const; [[nodiscard]] VariableNode* getVariable(int symb_id, int lag = 0) const;
//! Adds "arg1+arg2" to model tree //! Adds "arg1+arg2" to model tree
expr_t AddPlus(expr_t iArg1, expr_t iArg2); expr_t AddPlus(expr_t iArg1, expr_t iArg2);
//! Adds "arg1-arg2" to model tree //! Adds "arg1-arg2" to model tree
...@@ -261,22 +274,28 @@ public: ...@@ -261,22 +274,28 @@ public:
//! Adds an external function node //! Adds an external function node
expr_t AddExternalFunction(int symb_id, const vector<expr_t>& arguments); expr_t AddExternalFunction(int symb_id, const vector<expr_t>& arguments);
//! Adds an external function node for the first derivative of an external function //! 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); 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 //! 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); expr_t AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index1, int input_index2);
// Adds "SUM(arg)" to model tree
expr_t AddSum(expr_t arg);
//! Checks if a given symbol is used somewhere in the data tree //! Checks if a given symbol is used somewhere in the data tree
bool isSymbolUsed(int symb_id) const; [[nodiscard]] bool isSymbolUsed(int symb_id) const;
//! Checks if a given unary op is used somewhere in the data tree //! Checks if a given unary op is used somewhere in the data tree
bool isUnaryOpUsed(UnaryOpcode opcode) const; [[nodiscard]] bool isUnaryOpUsed(UnaryOpcode opcode) const;
//! Checks if a given unary op is used somewhere in the data tree on an endogenous variable //! Checks if a given unary op is used somewhere in the data tree on an endogenous variable
bool isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const; [[nodiscard]] bool isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const;
//! Checks if a given binary op is used somewhere in the data tree //! Checks if a given binary op is used somewhere in the data tree
bool isBinaryOpUsed(BinaryOpcode opcode) const; [[nodiscard]] bool isBinaryOpUsed(BinaryOpcode opcode) const;
//! Checks if a given binary op is used somewhere in the data tree on an endogenous variable //! Checks if a given binary op is used somewhere in the data tree on an endogenous variable
bool isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) const; [[nodiscard]] bool isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) 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 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 */ /*! Returns 0 if the symbol is not used */
int minLagForSymbol(int symb_id) const; [[nodiscard]] int minLagForSymbol(int symb_id) const;
/* Writes definitions of C function helpers (getPowerDeriv(), sign()) as /* Writes definitions of C function helpers (getPowerDeriv(), sign()) as
inline functions */ inline functions */
void writeCHelpersDefinition(ostream& output) const; void writeCHelpersDefinition(ostream& output) const;
...@@ -298,17 +317,17 @@ public: ...@@ -298,17 +317,17 @@ public:
}; };
// Returns the derivation ID, or throws an exception if the derivation ID does not exist // Returns the derivation ID, or throws an exception if the derivation ID does not exist
virtual int getDerivID(int symb_id, int lag) const noexcept(false); [[nodiscard]] virtual int getDerivID(int symb_id, int lag) const noexcept(false);
// Get the type corresponding to a derivation ID // Get the type corresponding to a derivation ID
virtual SymbolType getTypeByDerivID(int deriv_id) const noexcept(false); [[nodiscard]] virtual SymbolType getTypeByDerivID(int deriv_id) const noexcept(false);
// Get the lag corresponding to a derivation ID // Get the lag corresponding to a derivation ID
virtual int getLagByDerivID(int deriv_id) const noexcept(false); [[nodiscard]] virtual int getLagByDerivID(int deriv_id) const noexcept(false);
// Get the symbol ID corresponding to a derivation ID // Get the symbol ID corresponding to a derivation ID
virtual int getSymbIDByDerivID(int deriv_id) const noexcept(false); [[nodiscard]] virtual int getSymbIDByDerivID(int deriv_id) const noexcept(false);
// Get the type-specific ID corresponding to a derivation ID // Get the type-specific ID corresponding to a derivation ID
virtual int getTypeSpecificIDByDerivID(int deriv_id) const; [[nodiscard]] virtual int getTypeSpecificIDByDerivID(int deriv_id) const;
// Get the symbol name corresponding to a derivation ID // Get the symbol name corresponding to a derivation ID
string [[nodiscard]] string
getNameByDerivID(int deriv_id) const getNameByDerivID(int deriv_id) const
{ {
return symbol_table.getName(getSymbIDByDerivID(deriv_id)); return symbol_table.getName(getSymbIDByDerivID(deriv_id));
...@@ -317,7 +336,7 @@ public: ...@@ -317,7 +336,7 @@ public:
/* Returns the column of the Jacobian associated to a derivation ID. /* Returns the column of the Jacobian associated to a derivation ID.
The “sparse” argument selects between the legacy representation and the The “sparse” argument selects between the legacy representation and the
sparse representation. */ sparse representation. */
virtual int [[nodiscard]] virtual int
getJacobianCol([[maybe_unused]] int deriv_id, [[maybe_unused]] bool sparse) const getJacobianCol([[maybe_unused]] int deriv_id, [[maybe_unused]] bool sparse) const
{ {
throw UnknownDerivIDException(); throw UnknownDerivIDException();
...@@ -326,7 +345,7 @@ public: ...@@ -326,7 +345,7 @@ public:
/* Returns the number of columns of the Jacobian /* Returns the number of columns of the Jacobian
The “sparse” argument selects between the legacy representation and the The “sparse” argument selects between the legacy representation and the
sparse representation. */ sparse representation. */
virtual int [[nodiscard]] virtual int
getJacobianColsNbr([[maybe_unused]] bool sparse) const getJacobianColsNbr([[maybe_unused]] bool sparse) const
{ {
throw UnknownDerivIDException(); throw UnknownDerivIDException();
...@@ -335,27 +354,26 @@ public: ...@@ -335,27 +354,26 @@ public:
//! Adds to the set all the deriv IDs corresponding to parameters //! Adds to the set all the deriv IDs corresponding to parameters
virtual void addAllParamDerivId(set<int>& deriv_id_set); 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;
};
struct UnknownLocalVariableException struct UnknownLocalVariableException
{ {
//! Symbol ID //! Symbol ID
int id; int id;
}; };
expr_t [[nodiscard]] expr_t
getLocalVariable(int symb_id) const getLocalVariable(int symb_id, int lead_lag) const
{ {
auto it = local_variables_table.find(symb_id); auto it = local_variables_table.find(symb_id);
if (it == local_variables_table.end()) if (it == local_variables_table.end())
throw UnknownLocalVariableException {symb_id}; throw UnknownLocalVariableException {symb_id};
/* In the following, the case without lead/lag is optimized. It makes a difference on models
with many nested model-local variables, see e.g.
https://forum.dynare.org/t/pre-processing-takes-very-long/26865 */
if (lead_lag == 0)
return it->second; return it->second;
else
return it->second->decreaseLeadsLags(-lead_lag);
} }
static void static void
...@@ -373,7 +391,7 @@ public: ...@@ -373,7 +391,7 @@ public:
and returns the path to the corresponding filesystem directory. and returns the path to the corresponding filesystem directory.
In practice the package nesting is used for the planner_objective (stored In practice the package nesting is used for the planner_objective (stored
inside +objective subdir). */ inside +objective subdir). */
static filesystem::path packageDir(string_view package); static filesystem::path packageDir(const string_view& package);
}; };
inline expr_t inline expr_t
...@@ -384,7 +402,7 @@ DataTree::AddPossiblyNegativeConstant(double v) ...@@ -384,7 +402,7 @@ DataTree::AddPossiblyNegativeConstant(double v)
if (isnan(v)) if (isnan(v))
return NaN; return NaN;
if (isinf(v)) if (isinf(v))
return (v < 0 ? MinusInfinity : Infinity); return v < 0 ? MinusInfinity : Infinity;
bool neg = false; bool neg = false;
if (v < 0) if (v < 0)
...@@ -404,21 +422,23 @@ DataTree::AddPossiblyNegativeConstant(double v) ...@@ -404,21 +422,23 @@ DataTree::AddPossiblyNegativeConstant(double v)
} }
inline expr_t 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, const vector<int> &adl_lags) 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, const vector<int>& adl_lags)
{ {
// If the node already exists in tree, share it // If the node already exists in tree, share it
if (auto it = unary_op_node_map.find({ arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags }); if (auto it = unary_op_node_map.find({arg, op_code, arg_exp_info_set, param1_symb_id,
param2_symb_id, adl_param_name, adl_lags});
it != unary_op_node_map.end()) it != unary_op_node_map.end())
return it->second; return it->second;
// Try to reduce to a constant // Try to reduce to a constant
// Case where arg is a constant and op_code == UnaryOpcode::uminus (i.e. we're adding a negative constant) is skipped // Case where arg is a constant and op_code == UnaryOpcode::uminus (i.e. we're adding a negative
if (auto carg = dynamic_cast<NumConstNode *>(arg); // constant) is skipped
op_code != UnaryOpcode::uminus || !carg) if (auto carg = dynamic_cast<NumConstNode*>(arg); op_code != UnaryOpcode::uminus || !carg)
{ {
try try
{ {
double argval = arg->eval({}); double argval = arg->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage)
double val = UnaryOpNode::eval_opcode(op_code, argval); double val = UnaryOpNode::eval_opcode(op_code, argval);
return AddPossiblyNegativeConstant(val); return AddPossiblyNegativeConstant(val);
} }
...@@ -427,10 +447,13 @@ DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int ...@@ -427,10 +447,13 @@ DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int
} }
} }
auto sp = make_unique<UnaryOpNode>(*this, node_list.size(), op_code, arg, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags); auto sp = make_unique<UnaryOpNode>(*this, node_list.size(), op_code, arg, arg_exp_info_set,
param1_symb_id, param2_symb_id, adl_param_name, adl_lags);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
unary_op_node_map.try_emplace({ arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags }, p); unary_op_node_map.try_emplace(
{arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags},
p);
return p; return p;
} }
...@@ -444,8 +467,8 @@ DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerD ...@@ -444,8 +467,8 @@ DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerD
// Try to reduce to a constant // Try to reduce to a constant
try try
{ {
double argval1 = arg1->eval({}); double argval1 = arg1->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage)
double argval2 = arg2->eval({}); double argval2 = arg2->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage)
double val = BinaryOpNode::eval_opcode(argval1, op_code, argval2, powerDerivOrder); double val = BinaryOpNode::eval_opcode(argval1, op_code, argval2, powerDerivOrder);
return AddPossiblyNegativeConstant(val); return AddPossiblyNegativeConstant(val);
} }
...@@ -453,7 +476,8 @@ DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerD ...@@ -453,7 +476,8 @@ DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerD
{ {
} }
auto sp = make_unique<BinaryOpNode>(*this, node_list.size(), arg1, op_code, arg2, powerDerivOrder); auto sp
= make_unique<BinaryOpNode>(*this, node_list.size(), arg1, op_code, arg2, powerDerivOrder);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
binary_op_node_map.try_emplace({arg1, arg2, op_code, powerDerivOrder}, p); binary_op_node_map.try_emplace({arg1, arg2, op_code, powerDerivOrder}, p);
......
/* /*
* Copyright © 2003-2023 Dynare Team * Copyright © 2003-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -17,12 +17,13 @@ ...@@ -17,12 +17,13 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <iostream> #include <algorithm>
#include <cassert>
#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
#include <cassert> #include <iostream>
#include <algorithm>
#include <numeric> #include <numeric>
#include <ranges>
#include <regex> #include <regex>
#include <sstream> #include <sstream>
#include <string_view> #include <string_view>
...@@ -33,18 +34,27 @@ ...@@ -33,18 +34,27 @@
void void
DynamicModel::copyHelper(const DynamicModel& m) DynamicModel::copyHelper(const DynamicModel& m)
{ {
auto f = [this](const ExprNode *e) { return e->clone(*this); }; auto f = [this](const ExprNode* e) { return e ? e->clone(*this) : nullptr; };
for (const auto& it : m.static_only_equations) for (const auto& it : m.static_only_equations)
static_only_equations.push_back(dynamic_cast<BinaryOpNode*>(f(it))); static_only_equations.push_back(dynamic_cast<BinaryOpNode*>(f(it)));
for (const auto& it : m.static_only_complementarity_conditions)
if (it)
{
const auto& [symb_id, lb, ub] = *it;
static_only_complementarity_conditions.emplace_back(in_place, symb_id, f(lb), f(ub));
}
else
static_only_complementarity_conditions.emplace_back(nullopt);
} }
DynamicModel::DynamicModel(SymbolTable &symbol_table_arg, DynamicModel::DynamicModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg,
TrendComponentModelTable& trend_component_model_table_arg, TrendComponentModelTable& trend_component_model_table_arg,
VarModelTable& var_model_table_arg) : VarModelTable& var_model_table_arg) :
ModelTree{symbol_table_arg, num_constants_arg, external_functions_table_arg, true}, ModelTree {symbol_table_arg, num_constants_arg, external_functions_table_arg,
heterogeneity_table_arg, true},
trend_component_model_table {trend_component_model_table_arg}, trend_component_model_table {trend_component_model_table_arg},
var_model_table {var_model_table_arg} var_model_table {var_model_table_arg}
{ {
...@@ -104,6 +114,7 @@ DynamicModel::operator=(const DynamicModel &m) ...@@ -104,6 +114,7 @@ DynamicModel::operator=(const DynamicModel &m)
static_only_equations_lineno = m.static_only_equations_lineno; static_only_equations_lineno = m.static_only_equations_lineno;
static_only_equations_equation_tags = m.static_only_equations_equation_tags; static_only_equations_equation_tags = m.static_only_equations_equation_tags;
static_only_complementarity_conditions.clear();
deriv_id_table = m.deriv_id_table; deriv_id_table = m.deriv_id_table;
inv_deriv_id_table = m.inv_deriv_id_table; inv_deriv_id_table = m.inv_deriv_id_table;
dyn_jacobian_cols_table = m.dyn_jacobian_cols_table; dyn_jacobian_cols_table = m.dyn_jacobian_cols_table;
...@@ -160,43 +171,40 @@ DynamicModel::writeDynamicBytecode(const string &basename) const ...@@ -160,43 +171,40 @@ DynamicModel::writeDynamicBytecode(const string &basename) const
simulation_type = BlockSimulationType::solveBackwardComplete; simulation_type = BlockSimulationType::solveBackwardComplete;
// First write the .bin file // First write the .bin file
int u_count_int { writeBytecodeBinFile(basename + "/model/bytecode/dynamic.bin", int u_count_int {
writeBytecodeBinFile(basename + "/model/bytecode/dynamic.bin",
simulation_type == BlockSimulationType::solveTwoBoundariesComplete)}; simulation_type == BlockSimulationType::solveTwoBoundariesComplete)};
BytecodeWriter code_file {basename + "/model/bytecode/dynamic.cod"}; Bytecode::Writer code_file {basename + "/model/bytecode/dynamic.cod"};
// Declare temporary terms // Declare temporary terms
code_file << FDIMT_{static_cast<int>(temporary_terms_derivatives[0].size() code_file << Bytecode::FDIMT {static_cast<int>(temporary_terms_derivatives[0].size()
+ temporary_terms_derivatives[1].size())}; + temporary_terms_derivatives[1].size())};
// Declare the (single) block // Declare the (single) block
vector<int> exo(symbol_table.exo_nbr()), exo_det(symbol_table.exo_det_nbr()); auto exo = views::iota(0, symbol_table.exo_nbr());
iota(exo.begin(), exo.end(), 0); auto exo_det = views::iota(0, symbol_table.exo_det_nbr());
iota(exo_det.begin(), exo_det.end(), 0); auto eq_idx = views::iota(0, static_cast<int>(equations.size()));
auto endo_idx = views::iota(0, symbol_table.endo_nbr());
int jacobian_ncols_endo
{ static_cast<int>(count_if(dyn_jacobian_cols_table.begin(), dyn_jacobian_cols_table.end(),
[this](const auto &v)
{ return getTypeByDerivID(v.first) == SymbolType::endogenous; }))
};
vector<int> eq_idx(equations.size());
iota(eq_idx.begin(), eq_idx.end(), 0);
vector<int> endo_idx(symbol_table.endo_nbr());
iota(endo_idx.begin(), endo_idx.end(), 0);
code_file << FBEGINBLOCK_{symbol_table.endo_nbr(), int jacobian_ncols_endo {
static_cast<int>(ranges::count_if(dyn_jacobian_cols_table, [this](const auto& v) {
return getTypeByDerivID(v.first) == SymbolType::endogenous;
}))};
code_file << Bytecode::FBEGINBLOCK {symbol_table.endo_nbr(),
simulation_type, simulation_type,
0, 0,
symbol_table.endo_nbr(), symbol_table.endo_nbr(),
endo_idx, {endo_idx.begin(), endo_idx.end()},
eq_idx, {eq_idx.begin(), eq_idx.end()},
false, false,
u_count_int, u_count_int,
jacobian_ncols_endo, jacobian_ncols_endo,
symbol_table.exo_det_nbr(), symbol_table.exo_det_nbr(),
symbol_table.exo_nbr(), symbol_table.exo_nbr(),
exo_det, {exo_det.begin(), exo_det.end()},
exo}; {exo.begin(), exo.end()}};
writeBytecodeHelper<true>(code_file); writeBytecodeHelper<true>(code_file);
} }
...@@ -204,7 +212,7 @@ DynamicModel::writeDynamicBytecode(const string &basename) const ...@@ -204,7 +212,7 @@ DynamicModel::writeDynamicBytecode(const string &basename) const
void void
DynamicModel::writeDynamicBlockBytecode(const string& basename) const DynamicModel::writeDynamicBlockBytecode(const string& basename) const
{ {
BytecodeWriter code_file {basename + "/model/bytecode/block/dynamic.cod"}; Bytecode::Writer code_file {basename + "/model/bytecode/block/dynamic.cod"};
const filesystem::path bin_filename {basename + "/model/bytecode/block/dynamic.bin"}; const filesystem::path bin_filename {basename + "/model/bytecode/block/dynamic.bin"};
ofstream bin_file {bin_filename, ios::out | ios::binary}; ofstream bin_file {bin_filename, ios::out | ios::binary};
...@@ -215,7 +223,7 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const ...@@ -215,7 +223,7 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
} }
// Temporary variables declaration // Temporary variables declaration
code_file << FDIMT_{static_cast<int>(blocks_temporary_terms_idxs.size())}; code_file << Bytecode::FDIMT {static_cast<int>(blocks_temporary_terms_idxs.size())};
temporary_terms_t temporary_terms_written; temporary_terms_t temporary_terms_written;
...@@ -225,13 +233,14 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const ...@@ -225,13 +233,14 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
// Write section of .bin file except for evaluate blocks and solve simple blocks // Write section of .bin file except for evaluate blocks and solve simple blocks
const int u_count {simulation_type == BlockSimulationType::solveTwoBoundariesSimple const int u_count {simulation_type == BlockSimulationType::solveTwoBoundariesSimple
|| simulation_type == BlockSimulationType::solveTwoBoundariesComplete || simulation_type
== BlockSimulationType::solveTwoBoundariesComplete
|| simulation_type == BlockSimulationType::solveBackwardComplete || simulation_type == BlockSimulationType::solveBackwardComplete
|| simulation_type == BlockSimulationType::solveForwardComplete || simulation_type == BlockSimulationType::solveForwardComplete
? writeBlockBytecodeBinFile(bin_file, block) ? writeBlockBytecodeBinFile(bin_file, block)
: 0}; : 0};
code_file << FBEGINBLOCK_{blocks[block].mfs_size, code_file << Bytecode::FBEGINBLOCK {blocks[block].mfs_size,
simulation_type, simulation_type,
blocks[block].first_equation, blocks[block].first_equation,
blocks[block].size, blocks[block].size,
...@@ -243,7 +252,7 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const ...@@ -243,7 +252,7 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
writeBlockBytecodeHelper<true>(code_file, block, temporary_terms_written); writeBlockBytecodeHelper<true>(code_file, block, temporary_terms_written);
} }
code_file << FEND_{}; code_file << Bytecode::FEND {};
} }
void void
...@@ -254,19 +263,21 @@ DynamicModel::writeDynamicMFile(const string &basename) const ...@@ -254,19 +263,21 @@ DynamicModel::writeDynamicMFile(const string &basename) const
ostringstream init_output, end_output; ostringstream init_output, end_output;
init_output << "residual = zeros(" << equations.size() << ", 1);"; init_output << "residual = zeros(" << equations.size() << ", 1);";
writeDynamicMFileHelper(basename, "dynamic_resid", "residual", "dynamic_resid_tt", writeDynamicMFileHelper(basename, "dynamic_resid", "residual", "dynamic_resid_tt",
temporary_terms_derivatives[0].size(), temporary_terms_derivatives[0].size(), "", init_output, end_output,
"", init_output, end_output, d_output[0], tt_output[0]); d_output[0], tt_output[0]);
init_output.str(""); init_output.str("");
init_output << "g1 = zeros(" << equations.size() << ", " << getJacobianColsNbr(false) << ");"; init_output << "g1 = zeros(" << equations.size() << ", " << getJacobianColsNbr(false) << ");";
writeDynamicMFileHelper(basename, "dynamic_g1", "g1", "dynamic_g1_tt", writeDynamicMFileHelper(basename, "dynamic_g1", "g1", "dynamic_g1_tt",
temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size(), temporary_terms_derivatives[0].size()
+ temporary_terms_derivatives[1].size(),
"dynamic_resid_tt", init_output, end_output, d_output[1], tt_output[1]); "dynamic_resid_tt", init_output, end_output, d_output[1], tt_output[1]);
writeDynamicMWrapperFunction(basename, "g1"); writeDynamicMWrapperFunction(basename, "g1");
// For order ≥ 2 // For order ≥ 2
int ncols {getJacobianColsNbr(false)}; int ncols {getJacobianColsNbr(false)};
int ntt { static_cast<int>(temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size())}; int ntt {static_cast<int>(temporary_terms_derivatives[0].size()
+ temporary_terms_derivatives[1].size())};
for (size_t i {2}; i < derivatives.size(); i++) for (size_t i {2}; i < derivatives.size(); i++)
{ {
ncols *= getJacobianColsNbr(false); ncols *= getJacobianColsNbr(false);
...@@ -281,15 +292,14 @@ DynamicModel::writeDynamicMFile(const string &basename) const ...@@ -281,15 +292,14 @@ DynamicModel::writeDynamicMFile(const string &basename) const
init_output << gname << "_i = zeros(" << NNZDerivatives[i] << ",1);" << endl init_output << gname << "_i = zeros(" << NNZDerivatives[i] << ",1);" << endl
<< gname << "_j = zeros(" << NNZDerivatives[i] << ",1);" << endl << gname << "_j = zeros(" << NNZDerivatives[i] << ",1);" << endl
<< gname << "_v = zeros(" << NNZDerivatives[i] << ",1);" << endl; << gname << "_v = zeros(" << NNZDerivatives[i] << ",1);" << endl;
end_output << gname << " = sparse(" end_output << gname << " = sparse(" << gname << "_i," << gname << "_j," << gname << "_v,"
<< gname << "_i," << gname << "_j," << gname << "_v,"
<< equations.size() << "," << ncols << ");"; << equations.size() << "," << ncols << ");";
} }
else else
init_output << gname << " = sparse([],[],[]," << equations.size() << "," << ncols << ");"; init_output << gname << " = sparse([],[],[]," << equations.size() << "," << ncols << ");";
writeDynamicMFileHelper(basename, "dynamic_" + gname, gname, "dynamic_" + gname + "_tt", ntt, writeDynamicMFileHelper(basename, "dynamic_" + gname, gname, "dynamic_" + gname + "_tt", ntt,
"dynamic_" + gprevname + "_tt", init_output, end_output, "dynamic_" + gprevname + "_tt", init_output, end_output, d_output[i],
d_output[i], tt_output[i]); tt_output[i]);
if (i <= 3) if (i <= 3)
writeDynamicMWrapperFunction(basename, gname); writeDynamicMWrapperFunction(basename, gname);
} }
...@@ -301,7 +311,7 @@ string ...@@ -301,7 +311,7 @@ string
DynamicModel::reform(const string& name1) const DynamicModel::reform(const string& name1) const
{ {
string name = name1; string name = name1;
int pos = name.find(R"(\)", 0); int pos = name.find('\\', 0);
while (pos >= 0) while (pos >= 0)
{ {
if (name.substr(pos + 1, 1) != R"(\)") if (name.substr(pos + 1, 1) != R"(\)")
...@@ -310,7 +320,7 @@ DynamicModel::reform(const string &name1) const ...@@ -310,7 +320,7 @@ DynamicModel::reform(const string &name1) const
pos++; pos++;
} }
pos++; pos++;
pos = name.find(R"(\)", pos); pos = name.find('\\', pos);
} }
return name; return name;
} }
...@@ -320,8 +330,7 @@ DynamicModel::printNonZeroHessianEquations(ostream &output) const ...@@ -320,8 +330,7 @@ DynamicModel::printNonZeroHessianEquations(ostream &output) const
{ {
if (nonzero_hessian_eqs.size() != 1) if (nonzero_hessian_eqs.size() != 1)
output << "["; output << "[";
for (bool printed_something{false}; for (bool printed_something {false}; int it : nonzero_hessian_eqs)
int it : nonzero_hessian_eqs)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << " "; output << " ";
...@@ -351,44 +360,56 @@ DynamicModel::writeDynamicMWrapperFunction(const string &basename, const string ...@@ -351,44 +360,56 @@ DynamicModel::writeDynamicMWrapperFunction(const string &basename, const string
} }
if (ending == "g1") if (ending == "g1")
output << "function [residual, g1] = " << name << "(T, y, x, params, steady_state, it_, T_flag)" << endl output << "function [residual, g1] = " << name << "(T, y, x, params, steady_state, it_, T_flag)"
<< "% function [residual, g1] = " << name << "(T, y, x, params, steady_state, it_, T_flag)" << endl; << endl
<< "% function [residual, g1] = " << name
<< "(T, y, x, params, steady_state, it_, T_flag)" << endl;
else if (ending == "g2") else if (ending == "g2")
output << "function [residual, g1, g2] = " << name << "(T, y, x, params, steady_state, it_, T_flag)" << endl output << "function [residual, g1, g2] = " << name
<< "% function [residual, g1, g2] = " << name << "(T, y, x, params, steady_state, it_, T_flag)" << endl; << "(T, y, x, params, steady_state, it_, T_flag)" << endl
<< "% function [residual, g1, g2] = " << name
<< "(T, y, x, params, steady_state, it_, T_flag)" << endl;
else if (ending == "g3") else if (ending == "g3")
output << "function [residual, g1, g2, g3] = " << name << "(T, y, x, params, steady_state, it_, T_flag)" << endl output << "function [residual, g1, g2, g3] = " << name
<< "% function [residual, g1, g2, g3] = " << name << "(T, y, x, params, steady_state, it_, T_flag)" << endl; << "(T, y, x, params, steady_state, it_, T_flag)" << endl
<< "% function [residual, g1, g2, g3] = " << name
<< "(T, y, x, params, steady_state, it_, T_flag)" << endl;
output << "%" << endl output << "%" << endl
<< "% Wrapper function automatically created by Dynare" << endl << "% Wrapper function automatically created by Dynare" << endl
<< "%" << endl << "%" << endl
<< endl << endl
<< " if T_flag" << endl << " if T_flag" << endl
<< " T = " << basename << ".dynamic_" << ending << "_tt(T, y, x, params, steady_state, it_);" << endl << " T = " << basename << ".dynamic_" << ending
<< "_tt(T, y, x, params, steady_state, it_);" << endl
<< " end" << endl; << " end" << endl;
if (ending == "g1") if (ending == "g1")
output << " residual = " << basename << ".dynamic_resid(T, y, x, params, steady_state, it_, false);" << endl output << " residual = " << basename
<< " g1 = " << basename << ".dynamic_g1(T, y, x, params, steady_state, it_, false);" << endl; << ".dynamic_resid(T, y, x, params, steady_state, it_, false);" << endl
<< " g1 = " << basename
<< ".dynamic_g1(T, y, x, params, steady_state, it_, false);" << endl;
else if (ending == "g2") else if (ending == "g2")
output << " [residual, g1] = " << basename << ".dynamic_resid_g1(T, y, x, params, steady_state, it_, false);" << endl output << " [residual, g1] = " << basename
<< " g2 = " << basename << ".dynamic_g2(T, y, x, params, steady_state, it_, false);" << endl; << ".dynamic_resid_g1(T, y, x, params, steady_state, it_, false);" << endl
<< " g2 = " << basename
<< ".dynamic_g2(T, y, x, params, steady_state, it_, false);" << endl;
else if (ending == "g3") else if (ending == "g3")
output << " [residual, g1, g2] = " << basename << ".dynamic_resid_g1_g2(T, y, x, params, steady_state, it_, false);" << endl output << " [residual, g1, g2] = " << basename
<< " g3 = " << basename << ".dynamic_g3(T, y, x, params, steady_state, it_, false);" << endl; << ".dynamic_resid_g1_g2(T, y, x, params, steady_state, it_, false);" << endl
<< " g3 = " << basename
<< ".dynamic_g3(T, y, x, params, steady_state, it_, false);" << endl;
output << endl << "end" << endl; output << endl << "end" << endl;
output.close(); output.close();
} }
void void
DynamicModel::writeDynamicMFileHelper(const string &basename, DynamicModel::writeDynamicMFileHelper(const string& basename, const string& name,
const string &name, const string &retvalname, const string& retvalname, const string& name_tt, size_t ttlen,
const string &name_tt, size_t ttlen, const string& previous_tt_name, const ostringstream& init_s,
const string &previous_tt_name, const ostringstream& end_s, const ostringstream& s,
const ostringstream &init_s, const ostringstream &end_s, const ostringstream& s_tt) const
const ostringstream &s, const ostringstream &s_tt) const
{ {
filesystem::path filename {packageDir(basename) / (name_tt + ".m")}; filesystem::path filename {packageDir(basename) / (name_tt + ".m")};
ofstream output {filename, ios::out | ios::binary}; ofstream output {filename, ios::out | ios::binary};
...@@ -404,27 +425,43 @@ DynamicModel::writeDynamicMFileHelper(const string &basename, ...@@ -404,27 +425,43 @@ DynamicModel::writeDynamicMFileHelper(const string &basename,
<< "% File created by Dynare Preprocessor from .mod file" << endl << "% File created by Dynare Preprocessor from .mod file" << endl
<< "%" << endl << "%" << endl
<< "% Inputs:" << endl << "% Inputs:" << endl
<< "% T [#temp variables by 1] double vector of temporary terms to be filled by function" << endl << "% T [#temp variables by 1] double vector of temporary terms to be "
<< "% y [#dynamic variables by 1] double vector of endogenous variables in the order stored" << endl "filled by function"
<< "% in M_.lead_lag_incidence; see the Manual" << endl << endl
<< "% x [nperiods by M_.exo_nbr] double matrix of exogenous variables (in declaration order)" << endl << "% y [#dynamic variables by 1] double vector of endogenous variables "
<< "% for all simulation periods" << endl "in the order stored"
<< "% steady_state [M_.endo_nbr by 1] double vector of steady state values" << endl << endl
<< "% params [M_.param_nbr by 1] double vector of parameter values in declaration order" << endl << "% in M_.lead_lag_incidence; see "
<< "% it_ scalar double time period for exogenous variables for which" << endl "the Manual"
<< endl
<< "% x [nperiods by M_.exo_nbr] double matrix of exogenous variables "
"(in declaration order)"
<< endl
<< "% for all simulation periods"
<< endl
<< "% steady_state [M_.endo_nbr by 1] double vector of steady state values"
<< endl
<< "% params [M_.param_nbr by 1] double vector of parameter values in "
"declaration order"
<< endl
<< "% it_ scalar double time period for exogenous "
"variables for which"
<< endl
<< "% to evaluate the model" << endl << "% to evaluate the model" << endl
<< "%" << endl << "%" << endl
<< "% Output:" << endl << "% Output:" << endl
<< "% T [#temp variables by 1] double vector of temporary terms" << endl << "% T [#temp variables by 1] double vector of temporary terms" << endl
<< "%" << endl << endl << "%" << endl
<< endl
<< "assert(length(T) >= " << ttlen << ");" << endl << "assert(length(T) >= " << ttlen << ");" << endl
<< endl; << endl;
if (!previous_tt_name.empty()) if (!previous_tt_name.empty())
output << "T = " << basename << "." << previous_tt_name << "(T, y, x, params, steady_state, it_);" << endl << endl; output << "T = " << basename << "." << previous_tt_name
<< "(T, y, x, params, steady_state, it_);" << endl
<< endl;
output << s_tt.str() << endl output << s_tt.str() << endl << "end" << endl;
<< "end" << endl;
output.close(); output.close();
filename = packageDir(basename) / (name + ".m"); filename = packageDir(basename) / (name + ".m");
...@@ -435,36 +472,53 @@ DynamicModel::writeDynamicMFileHelper(const string &basename, ...@@ -435,36 +472,53 @@ DynamicModel::writeDynamicMFileHelper(const string &basename,
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
output << "function " << retvalname << " = " << name << "(T, y, x, params, steady_state, it_, T_flag)" << endl output << "function " << retvalname << " = " << name
<< "% function " << retvalname << " = " << name << "(T, y, x, params, steady_state, it_, T_flag)" << endl << "(T, y, x, params, steady_state, it_, T_flag)" << endl
<< "% function " << retvalname << " = " << name
<< "(T, y, x, params, steady_state, it_, T_flag)" << endl
<< "%" << endl << "%" << endl
<< "% File created by Dynare Preprocessor from .mod file" << endl << "% File created by Dynare Preprocessor from .mod file" << endl
<< "%" << endl << "%" << endl
<< "% Inputs:" << endl << "% Inputs:" << endl
<< "% T [#temp variables by 1] double vector of temporary terms to be filled by function" << endl << "% T [#temp variables by 1] double vector of temporary terms to be "
<< "% y [#dynamic variables by 1] double vector of endogenous variables in the order stored" << endl "filled by function"
<< "% in M_.lead_lag_incidence; see the Manual" << endl << endl
<< "% x [nperiods by M_.exo_nbr] double matrix of exogenous variables (in declaration order)" << endl << "% y [#dynamic variables by 1] double vector of endogenous variables "
<< "% for all simulation periods" << endl "in the order stored"
<< "% steady_state [M_.endo_nbr by 1] double vector of steady state values" << endl << endl
<< "% params [M_.param_nbr by 1] double vector of parameter values in declaration order" << endl << "% in M_.lead_lag_incidence; see "
<< "% it_ scalar double time period for exogenous variables for which" << endl "the Manual"
<< endl
<< "% x [nperiods by M_.exo_nbr] double matrix of exogenous variables "
"(in declaration order)"
<< endl
<< "% for all simulation periods"
<< endl
<< "% steady_state [M_.endo_nbr by 1] double vector of steady state values"
<< endl
<< "% params [M_.param_nbr by 1] double vector of parameter values in "
"declaration order"
<< endl
<< "% it_ scalar double time period for exogenous "
"variables for which"
<< endl
<< "% to evaluate the model" << endl << "% to evaluate the model" << endl
<< "% T_flag boolean boolean flag saying whether or not to calculate temporary terms" << endl << "% T_flag boolean boolean flag saying whether or not to "
"calculate temporary terms"
<< endl
<< "%" << endl << "%" << endl
<< "% Output:" << endl << "% Output:" << endl
<< "% " << retvalname << endl << "% " << retvalname << endl
<< "%" << endl << endl; << "%" << endl
<< endl;
if (!name_tt.empty()) if (!name_tt.empty())
output << "if T_flag" << endl output << "if T_flag" << endl
<< " T = " << basename << "." << name_tt << "(T, y, x, params, steady_state, it_);" << endl << " T = " << basename << "." << name_tt << "(T, y, x, params, steady_state, it_);"
<< endl
<< "end" << endl; << "end" << endl;
output << init_s.str() << endl output << init_s.str() << endl << s.str() << end_s.str() << endl << "end" << endl;
<< s.str()
<< end_s.str() << endl
<< "end" << endl;
output.close(); output.close();
} }
...@@ -478,18 +532,24 @@ DynamicModel::writeDynamicMCompatFile(const string &basename) const ...@@ -478,18 +532,24 @@ DynamicModel::writeDynamicMCompatFile(const string &basename) const
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
int ntt { static_cast<int>(temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size() + temporary_terms_derivatives[2].size() + temporary_terms_derivatives[3].size()) }; int ntt {static_cast<int>(
temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size()
+ temporary_terms_derivatives[2].size() + temporary_terms_derivatives[3].size())};
output << "function [residual, g1, g2, g3] = dynamic(y, x, params, steady_state, it_)" << endl output << "function [residual, g1, g2, g3] = dynamic(y, x, params, steady_state, it_)" << endl
<< " T = NaN(" << ntt << ", 1);" << endl << " T = NaN(" << ntt << ", 1);" << endl
<< " if nargout <= 1" << endl << " if nargout <= 1" << endl
<< " residual = " << basename << ".dynamic_resid(T, y, x, params, steady_state, it_, true);" << endl << " residual = " << basename
<< ".dynamic_resid(T, y, x, params, steady_state, it_, true);" << endl
<< " elseif nargout == 2" << endl << " elseif nargout == 2" << endl
<< " [residual, g1] = " << basename << ".dynamic_resid_g1(T, y, x, params, steady_state, it_, true);" << endl << " [residual, g1] = " << basename
<< ".dynamic_resid_g1(T, y, x, params, steady_state, it_, true);" << endl
<< " elseif nargout == 3" << endl << " elseif nargout == 3" << endl
<< " [residual, g1, g2] = " << basename << ".dynamic_resid_g1_g2(T, y, x, params, steady_state, it_, true);" << endl << " [residual, g1, g2] = " << basename
<< ".dynamic_resid_g1_g2(T, y, x, params, steady_state, it_, true);" << endl
<< " else" << endl << " else" << endl
<< " [residual, g1, g2, g3] = " << basename << ".dynamic_resid_g1_g2_g3(T, y, x, params, steady_state, it_, true);" << endl << " [residual, g1, g2, g3] = " << basename
<< ".dynamic_resid_g1_g2_g3(T, y, x, params, steady_state, it_, true);" << endl
<< " end" << endl << " end" << endl
<< "end" << endl; << "end" << endl;
...@@ -499,8 +559,7 @@ DynamicModel::writeDynamicMCompatFile(const string &basename) const ...@@ -499,8 +559,7 @@ DynamicModel::writeDynamicMCompatFile(const string &basename) const
vector<map<string, string>> vector<map<string, string>>
DynamicModel::parseIncludeExcludeEquations(const string& inc_exc_option_value, bool exclude_eqs) DynamicModel::parseIncludeExcludeEquations(const string& inc_exc_option_value, bool exclude_eqs)
{ {
auto removeLeadingTrailingWhitespace = [](string &str) auto removeLeadingTrailingWhitespace = [](string& str) {
{
str.erase(0, str.find_first_not_of("\t\n\v\f\r ")); str.erase(0, str.find_first_not_of("\t\n\v\f\r "));
str.erase(str.find_last_not_of("\t\n\v\f\r ") + 1); str.erase(str.find_last_not_of("\t\n\v\f\r ") + 1);
}; };
...@@ -523,12 +582,12 @@ DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_option_value, b ...@@ -523,12 +582,12 @@ DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_option_value, b
removeLeadingTrailingWhitespace(line); removeLeadingTrailingWhitespace(line);
if (!line.empty()) if (!line.empty())
{ {
if (tags.empty() && line.find("=") != string::npos) if (tags.empty() && line.find('=') != string::npos)
{ {
tagname_on_first_line = true; tagname_on_first_line = true;
tags += line + "("; tags += line + "(";
} }
else if (line.find("'") != string::npos) else if (line.find('\'') != string::npos)
tags += line + ","; tags += line + ",";
else else
tags += "'" + line + "',"; tags += "'" + line + "',";
...@@ -576,7 +635,8 @@ DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_option_value, b ...@@ -576,7 +635,8 @@ DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_option_value, b
string quote_regex = "'[^']+'"; string quote_regex = "'[^']+'";
string non_quote_regex = R"([^,\s]+)"; string non_quote_regex = R"([^,\s]+)";
regex r(R"((\s*)" + quote_regex + "|" + non_quote_regex + R"(\s*)(,\s*()" + quote_regex + "|" + non_quote_regex + R"()\s*)*)"); regex r(R"((\s*)" + quote_regex + "|" + non_quote_regex + R"(\s*)(,\s*()" + quote_regex + "|"
+ non_quote_regex + R"()\s*)*)");
if (!regex_match(tags, r)) if (!regex_match(tags, r))
{ {
cerr << "ERROR: " << (exclude_eqs ? "exclude_eqs" : "include_eqs") cerr << "ERROR: " << (exclude_eqs ? "exclude_eqs" : "include_eqs")
...@@ -586,8 +646,7 @@ DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_option_value, b ...@@ -586,8 +646,7 @@ DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_option_value, b
vector<map<string, string>> eq_tag_set; vector<map<string, string>> eq_tag_set;
regex s(quote_regex + "|" + non_quote_regex); regex s(quote_regex + "|" + non_quote_regex);
for (auto it = sregex_iterator(tags.begin(), tags.end(), s); for (auto it = sregex_iterator(tags.begin(), tags.end(), s); it != sregex_iterator(); ++it)
it != sregex_iterator(); ++it)
{ {
string_view str {it->str()}; string_view str {it->str()};
if (str.front() == '\'' && str.back() == '\'') if (str.front() == '\'' && str.back() == '\'')
...@@ -601,10 +660,10 @@ DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_option_value, b ...@@ -601,10 +660,10 @@ DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_option_value, b
} }
vector<int> vector<int>
DynamicModel::removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag, bool exclude_eqs, DynamicModel::removeEquationsHelper(
bool excluded_vars_change_type, set<map<string, string>>& listed_eqs_by_tag, bool exclude_eqs, bool excluded_vars_change_type,
vector<BinaryOpNode *> &all_equations, vector<BinaryOpNode*>& all_equations, vector<optional<int>>& all_equations_lineno,
vector<optional<int>> &all_equations_lineno, vector<optional<tuple<int, expr_t, expr_t>>>& all_complementarity_conditions,
EquationTags& all_equation_tags, bool static_equations) const EquationTags& all_equation_tags, bool static_equations) const
{ {
if (all_equations.empty()) if (all_equations.empty())
...@@ -616,8 +675,7 @@ DynamicModel::removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag, ...@@ -616,8 +675,7 @@ DynamicModel::removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag,
the caller knows which tag pairs have not been handled. */ the caller knows which tag pairs have not been handled. */
set<int> listed_eqs_by_number; set<int> listed_eqs_by_number;
for (auto it = listed_eqs_by_tag.begin(); it != listed_eqs_by_tag.end();) for (auto it = listed_eqs_by_tag.begin(); it != listed_eqs_by_tag.end();)
if (auto tmp = all_equation_tags.getEqnsByTags(*it); if (auto tmp = all_equation_tags.getEqnsByTags(*it); !tmp.empty())
!tmp.empty())
{ {
listed_eqs_by_number.insert(tmp.begin(), tmp.end()); listed_eqs_by_number.insert(tmp.begin(), tmp.end());
it = listed_eqs_by_tag.erase(it); it = listed_eqs_by_tag.erase(it);
...@@ -637,6 +695,7 @@ DynamicModel::removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag, ...@@ -637,6 +695,7 @@ DynamicModel::removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag,
// remove from equations, equations_lineno, equation_tags // remove from equations, equations_lineno, equation_tags
vector<BinaryOpNode*> new_equations; vector<BinaryOpNode*> new_equations;
vector<optional<int>> new_equations_lineno; vector<optional<int>> new_equations_lineno;
vector<optional<tuple<int, expr_t, expr_t>>> new_complementarity_conditions;
map<int, int> old_eqn_num_2_new; map<int, int> old_eqn_num_2_new;
vector<int> excluded_vars; vector<int> excluded_vars;
for (size_t i = 0; i < all_equations.size(); i++) for (size_t i = 0; i < all_equations.size(); i++)
...@@ -655,7 +714,9 @@ DynamicModel::removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag, ...@@ -655,7 +714,9 @@ DynamicModel::removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag,
else else
{ {
cerr << "ERROR: Equation " << i + 1 cerr << "ERROR: Equation " << i + 1
<< " has been excluded but it does not have a single variable on its left-hand side or an `endogenous` tag" << endl; << " has been excluded but it does not have a single variable on its "
"left-hand side or an `endogenous` tag"
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -666,11 +727,13 @@ DynamicModel::removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag, ...@@ -666,11 +727,13 @@ DynamicModel::removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag,
new_equations.emplace_back(all_equations[i]); new_equations.emplace_back(all_equations[i]);
old_eqn_num_2_new[i] = new_equations.size() - 1; old_eqn_num_2_new[i] = new_equations.size() - 1;
new_equations_lineno.emplace_back(all_equations_lineno[i]); new_equations_lineno.emplace_back(all_equations_lineno[i]);
new_complementarity_conditions.emplace_back(all_complementarity_conditions[i]);
} }
int n_excl = all_equations.size() - new_equations.size(); int n_excl = all_equations.size() - new_equations.size();
all_equations = new_equations; all_equations = move(new_equations);
all_equations_lineno = new_equations_lineno; all_equations_lineno = move(new_equations_lineno);
all_complementarity_conditions = move(new_complementarity_conditions);
all_equation_tags.erase(eqs_to_delete_by_number, old_eqn_num_2_new); all_equation_tags.erase(eqs_to_delete_by_number, old_eqn_num_2_new);
...@@ -680,36 +743,42 @@ DynamicModel::removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag, ...@@ -680,36 +743,42 @@ DynamicModel::removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag,
if (excluded_vars[i] == excluded_vars[j]) if (excluded_vars[i] == excluded_vars[j])
{ {
cerr << "ERROR: Variable " << symbol_table.getName(i) << " was excluded twice" cerr << "ERROR: Variable " << symbol_table.getName(i) << " was excluded twice"
<< " via a model_remove or model_replace statement, or via the include_eqs or exclude_eqs option" << endl; << " via a model_remove or model_replace statement, or via the include_eqs or "
"exclude_eqs option"
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
cout << "Excluded " << n_excl << (static_equations ? " static " : " dynamic ") cout << "Excluded " << n_excl << (static_equations ? " static " : " dynamic ") << "equation"
<< "equation" << (n_excl > 1 ? "s" : "") << " via model_remove or model_replace statement, or via include_eqs or exclude_eqs option" << endl; << (n_excl > 1 ? "s" : "")
<< " via model_remove or model_replace statement, or via include_eqs or exclude_eqs option"
<< endl;
return excluded_vars; return excluded_vars;
} }
void void
DynamicModel::removeEquations(const vector<map<string, string>> &listed_eqs_by_tag, bool exclude_eqs, DynamicModel::removeEquations(const vector<map<string, string>>& listed_eqs_by_tag,
bool excluded_vars_change_type) bool exclude_eqs, bool excluded_vars_change_type)
{ {
/* Convert the const vector to a (mutable) set */ /* Convert the const vector to a (mutable) set */
set listed_eqs_by_tag2(listed_eqs_by_tag.begin(), listed_eqs_by_tag.end()); set listed_eqs_by_tag2(listed_eqs_by_tag.begin(), listed_eqs_by_tag.end());
vector<int> excluded_vars = removeEquationsHelper(listed_eqs_by_tag2, exclude_eqs, vector<int> excluded_vars
excluded_vars_change_type, = removeEquationsHelper(listed_eqs_by_tag2, exclude_eqs, excluded_vars_change_type, equations,
equations, equations_lineno, equations_lineno, complementarity_conditions, equation_tags, false);
equation_tags, false);
// Ignore output because variables are not excluded when equations marked 'static' are excluded // Ignore output because variables are not excluded when equations marked 'static' are excluded
removeEquationsHelper(listed_eqs_by_tag2, exclude_eqs, excluded_vars_change_type, removeEquationsHelper(listed_eqs_by_tag2, exclude_eqs, excluded_vars_change_type,
static_only_equations, static_only_equations_lineno, static_only_equations, static_only_equations_lineno,
static_only_equations_equation_tags, true); static_only_complementarity_conditions, static_only_equations_equation_tags,
true);
if (!listed_eqs_by_tag2.empty()) if (!listed_eqs_by_tag2.empty())
{ {
cerr << "ERROR: model_remove/model_replace/exclude_eqs/include_eqs: The equations specified by" << endl; cerr
<< "ERROR: model_remove/model_replace/exclude_eqs/include_eqs: The equations specified by"
<< endl;
for (const auto& m : listed_eqs_by_tag) for (const auto& m : listed_eqs_by_tag)
{ {
cerr << " "; cerr << " ";
...@@ -746,12 +815,18 @@ DynamicModel::removeEquations(const vector<map<string, string>> &listed_eqs_by_t ...@@ -746,12 +815,18 @@ DynamicModel::removeEquations(const vector<map<string, string>> &listed_eqs_by_t
if (eqn_vars.contains(ev)) if (eqn_vars.contains(ev))
{ {
symbol_table.changeType(ev, SymbolType::exogenous); symbol_table.changeType(ev, SymbolType::exogenous);
cerr << "Variable '" << symbol_table.getName(ev) << "' turned into an exogenous, as its defining equation has been removed (but it still appears in an equation)" << endl; cerr << "Variable '" << symbol_table.getName(ev)
<< "' turned into an exogenous, as its defining equation has been removed (but it "
"still appears in an equation)"
<< endl;
} }
else else
{ {
symbol_table.changeType(ev, SymbolType::excludedVariable); symbol_table.changeType(ev, SymbolType::excludedVariable);
cerr << "Variable '" << symbol_table.getName(ev) << "' has been excluded from the model, as its defining equation has been removed and it appears nowhere else" << endl; cerr << "Variable '" << symbol_table.getName(ev)
<< "' has been excluded from the model, as its defining equation has been removed "
"and it appears nowhere else"
<< endl;
} }
} }
} }
...@@ -771,7 +846,9 @@ DynamicModel::includeExcludeEquations(const string &inc_exc_option_value, bool e ...@@ -771,7 +846,9 @@ DynamicModel::includeExcludeEquations(const string &inc_exc_option_value, bool e
ModFile::transformPass(), so we must do the check again */ ModFile::transformPass(), so we must do the check again */
if (staticOnlyEquationsNbr() != dynamicOnlyEquationsNbr()) if (staticOnlyEquationsNbr() != dynamicOnlyEquationsNbr())
{ {
cerr << "ERROR: exclude_eqs/include_eqs: You must remove the same number of equations marked `static` as equations marked `dynamic`." << endl; cerr << "ERROR: exclude_eqs/include_eqs: You must remove the same number of equations marked "
"`static` as equations marked `dynamic`."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -779,26 +856,33 @@ DynamicModel::includeExcludeEquations(const string &inc_exc_option_value, bool e ...@@ -779,26 +856,33 @@ DynamicModel::includeExcludeEquations(const string &inc_exc_option_value, bool e
void void
DynamicModel::writeBlockDriverOutput(ostream& output) const DynamicModel::writeBlockDriverOutput(ostream& output) const
{ {
output << "M_.block_structure.time_recursive = " << boolalpha << time_recursive_block_decomposition << ";" << endl; output << "M_.block_structure.time_recursive = " << boolalpha
<< time_recursive_block_decomposition << ";" << endl;
for (int blk = 0; blk < static_cast<int>(blocks.size()); blk++) for (int blk = 0; blk < static_cast<int>(blocks.size()); blk++)
{ {
int block_size = blocks[blk].size; int block_size = blocks[blk].size;
output << "M_.block_structure.block(" << blk+1 << ").Simulation_Type = " << static_cast<int>(blocks[blk].simulation_type) << ";" << endl output << "M_.block_structure.block(" << blk + 1
<< "M_.block_structure.block(" << blk+1 << ").endo_nbr = " << block_size << ";" << endl << ").Simulation_Type = " << static_cast<int>(blocks[blk].simulation_type) << ";"
<< "M_.block_structure.block(" << blk+1 << ").mfs = " << blocks[blk].mfs_size << ";" << endl << endl
<< "M_.block_structure.block(" << blk + 1 << ").endo_nbr = " << block_size << ";"
<< endl
<< "M_.block_structure.block(" << blk + 1 << ").mfs = " << blocks[blk].mfs_size << ";"
<< endl
<< "M_.block_structure.block(" << blk + 1 << ").equation = ["; << "M_.block_structure.block(" << blk + 1 << ").equation = [";
for (int eq = 0; eq < block_size; eq++) for (int eq = 0; eq < block_size; eq++)
output << " " << getBlockEquationID(blk, eq) + 1; output << " " << getBlockEquationID(blk, eq) + 1;
output << "];" << endl output << "];" << endl << "M_.block_structure.block(" << blk + 1 << ").variable = [";
<< "M_.block_structure.block(" << blk+1 << ").variable = [";
for (int var = 0; var < block_size; var++) for (int var = 0; var < block_size; var++)
output << " " << getBlockVariableID(blk, var) + 1; output << " " << getBlockVariableID(blk, var) + 1;
output << "];" << endl output << "];" << endl
<< "M_.block_structure.block(" << blk+1 << ").is_linear = " << boolalpha << blocks[blk].linear << ';' << endl << "M_.block_structure.block(" << blk + 1 << ").is_linear = " << boolalpha
<< "M_.block_structure.block(" << blk+1 << ").NNZDerivatives = " << blocks_derivatives[blk].size() << ';' << endl << blocks[blk].linear << ';' << endl
<< "M_.block_structure.block(" << blk + 1
<< ").NNZDerivatives = " << blocks_derivatives[blk].size() << ';' << endl
<< "M_.block_structure.block(" << blk + 1 << ").bytecode_jacob_cols_to_sparse = ["; << "M_.block_structure.block(" << blk + 1 << ").bytecode_jacob_cols_to_sparse = [";
const bool one_boundary {blocks[blk].simulation_type == BlockSimulationType::solveBackwardSimple const bool one_boundary {
blocks[blk].simulation_type == BlockSimulationType::solveBackwardSimple
|| blocks[blk].simulation_type == BlockSimulationType::solveForwardSimple || blocks[blk].simulation_type == BlockSimulationType::solveForwardSimple
|| blocks[blk].simulation_type == BlockSimulationType::solveBackwardComplete || blocks[blk].simulation_type == BlockSimulationType::solveBackwardComplete
|| blocks[blk].simulation_type == BlockSimulationType::solveForwardComplete}; || blocks[blk].simulation_type == BlockSimulationType::solveForwardComplete};
...@@ -813,9 +897,13 @@ DynamicModel::writeBlockDriverOutput(ostream &output) const ...@@ -813,9 +897,13 @@ DynamicModel::writeBlockDriverOutput(ostream &output) const
for (auto& [key, index] : blocks_jacob_cols_endo[blk]) for (auto& [key, index] : blocks_jacob_cols_endo[blk])
{ {
auto [var, lag] {key}; auto [var, lag] {key};
if (var >= blocks[blk].getRecursiveSize() // NB: this check can be removed once Jacobian no longer contains columns for derivatives w.r.t. recursive variables if (var >= blocks[blk].getRecursiveSize() // NB: this check can be removed once Jacobian
// no longer contains columns for derivatives
// w.r.t. recursive variables
&& !(one_boundary && lag != 0)) && !(one_boundary && lag != 0))
bytecode_jacob_cols_to_sparse[index] = static_cast<int>(!one_boundary)*(lag+1)*blocks[blk].mfs_size + var - blocks[blk].getRecursiveSize(); bytecode_jacob_cols_to_sparse[index]
= static_cast<int>(!one_boundary) * (lag + 1) * blocks[blk].mfs_size + var
- blocks[blk].getRecursiveSize();
else else
bytecode_jacob_cols_to_sparse[index] = -1; bytecode_jacob_cols_to_sparse[index] = -1;
} }
...@@ -829,16 +917,14 @@ DynamicModel::writeBlockDriverOutput(ostream &output) const ...@@ -829,16 +917,14 @@ DynamicModel::writeBlockDriverOutput(ostream &output) const
output << "M_.block_structure.variable_reordered = ["; output << "M_.block_structure.variable_reordered = [";
for (int i = 0; i < symbol_table.endo_nbr(); i++) for (int i = 0; i < symbol_table.endo_nbr(); i++)
output << " " << endo_idx_block2orig[i] + 1; output << " " << endo_idx_block2orig[i] + 1;
output << "];" << endl output << "];" << endl << "M_.block_structure.equation_reordered = [";
<< "M_.block_structure.equation_reordered = [";
for (int i = 0; i < symbol_table.endo_nbr(); i++) for (int i = 0; i < symbol_table.endo_nbr(); i++)
output << " " << eq_idx_block2orig[i] + 1; output << " " << eq_idx_block2orig[i] + 1;
output << "];" << endl; output << "];" << endl;
map<int, set<pair<int, int>>> lag_row_incidence; map<int, set<pair<int, int>>> lag_row_incidence;
for (const auto& [indices, d1] : derivatives[1]) for (const auto& [indices, d1] : derivatives[1])
if (int deriv_id = indices[1]; if (int deriv_id = indices[1]; getTypeByDerivID(deriv_id) == SymbolType::endogenous)
getTypeByDerivID(deriv_id) == SymbolType::endogenous)
{ {
int eq = indices[0]; int eq = indices[0];
int var {getTypeSpecificIDByDerivID(deriv_id)}; int var {getTypeSpecificIDByDerivID(deriv_id)};
...@@ -847,13 +933,16 @@ DynamicModel::writeBlockDriverOutput(ostream &output) const ...@@ -847,13 +933,16 @@ DynamicModel::writeBlockDriverOutput(ostream &output) const
} }
for (auto [lag, eq_var_set] : lag_row_incidence) for (auto [lag, eq_var_set] : lag_row_incidence)
{ {
output << "M_.block_structure.incidence(" << max_endo_lag+lag+1 << ").lead_lag = " << lag << ";" << endl output << "M_.block_structure.incidence(" << max_endo_lag + lag + 1 << ").lead_lag = " << lag
<< "M_.block_structure.incidence(" << max_endo_lag+lag+1 << ").sparse_IM = [" << endl; << ";" << endl
<< "M_.block_structure.incidence(" << max_endo_lag + lag + 1 << ").sparse_IM = ["
<< endl;
for (auto [eq, var] : eq_var_set) for (auto [eq, var] : eq_var_set)
output << " " << eq + 1 << " " << var + 1 << ";" << endl; output << " " << eq + 1 << " " << var + 1 << ";" << endl;
output << "];" << endl; output << "];" << endl;
} }
output << "M_.block_structure.dyn_tmp_nbr = " << blocks_temporary_terms_idxs.size() << ';' << endl; output << "M_.block_structure.dyn_tmp_nbr = " << blocks_temporary_terms_idxs.size() << ';'
<< endl;
} }
void void
...@@ -876,20 +965,15 @@ DynamicModel::writeDriverOutput(ostream &output, bool compute_xrefs) const ...@@ -876,20 +965,15 @@ DynamicModel::writeDriverOutput(ostream &output, bool compute_xrefs) const
<< "M_.orig_maximum_exo_det_lead = " << max_exo_det_lead_orig << ";" << endl << "M_.orig_maximum_exo_det_lead = " << max_exo_det_lead_orig << ";" << endl
<< "M_.orig_maximum_lag = " << max_lag_orig << ";" << endl << "M_.orig_maximum_lag = " << max_lag_orig << ";" << endl
<< "M_.orig_maximum_lead = " << max_lead_orig << ";" << endl << "M_.orig_maximum_lead = " << max_lead_orig << ";" << endl
<< "M_.orig_maximum_lag_with_diffs_expanded = " << max_lag_with_diffs_expanded_orig << ";" << endl << "M_.orig_maximum_lag_with_diffs_expanded = " << max_lag_with_diffs_expanded_orig << ";"
<< endl
<< "M_.lead_lag_incidence = ["; << "M_.lead_lag_incidence = [";
// Loop on endogenous variables // Loop on endogenous variables
int nstatic = 0, int nstatic = 0, nfwrd = 0, npred = 0, nboth = 0;
nfwrd = 0,
npred = 0,
nboth = 0;
for (int endoID = 0; endoID < symbol_table.endo_nbr(); endoID++) for (int endoID = 0; endoID < symbol_table.endo_nbr(); endoID++)
{ {
output << endl; output << endl;
int sstatic = 1, int sstatic = 1, sfwrd = 0, spred = 0, sboth = 0;
sfwrd = 0,
spred = 0,
sboth = 0;
// Loop on periods // Loop on periods
for (int lag = -max_endo_lag; lag <= max_endo_lead; lag++) for (int lag = -max_endo_lag; lag <= max_endo_lead; lag++)
{ {
...@@ -955,20 +1039,12 @@ DynamicModel::writeDriverOutput(ostream &output, bool compute_xrefs) const ...@@ -955,20 +1039,12 @@ DynamicModel::writeDriverOutput(ostream &output, bool compute_xrefs) const
/* Say if static and dynamic models differ (because of [static] and [dynamic] /* Say if static and dynamic models differ (because of [static] and [dynamic]
equation tags) */ equation tags) */
output << "M_.static_and_dynamic_models_differ = " output << "M_.static_and_dynamic_models_differ = " << boolalpha
<< boolalpha << (static_only_equations.size() > 0) << (static_only_equations.size() > 0) << ";" << endl;
<< ";" << endl;
// Say if model contains an external function call // Say if model contains an external function call
bool has_external_function = false; output << "M_.has_external_function = " << boolalpha
for (auto equation : equations) << ranges::any_of(equations, &ExprNode::containsExternalFunction) << ';' << endl;
if (equation->containsExternalFunction())
{
has_external_function = true;
break;
}
output << "M_.has_external_function = " << boolalpha << has_external_function
<< ';' << endl;
// Compute list of state variables, ordered in block-order // Compute list of state variables, ordered in block-order
vector<int> state_var; vector<int> state_var;
...@@ -978,7 +1054,7 @@ DynamicModel::writeDriverOutput(ostream &output, bool compute_xrefs) const ...@@ -978,7 +1054,7 @@ DynamicModel::writeDriverOutput(ostream &output, bool compute_xrefs) const
try try
{ {
getDerivID(symbol_table.getID(SymbolType::endogenous, endo_idx_block2orig[endoID]), lag); getDerivID(symbol_table.getID(SymbolType::endogenous, endo_idx_block2orig[endoID]), lag);
if (find(state_var.begin(), state_var.end(), endo_idx_block2orig[endoID]) == state_var.end()) if (ranges::find(state_var, endo_idx_block2orig[endoID]) == state_var.end())
state_var.push_back(endo_idx_block2orig[endoID]); state_var.push_back(endo_idx_block2orig[endoID]);
} }
catch (UnknownDerivIDException& e) catch (UnknownDerivIDException& e)
...@@ -1010,27 +1086,32 @@ DynamicModel::writeDriverOutput(ostream &output, bool compute_xrefs) const ...@@ -1010,27 +1086,32 @@ DynamicModel::writeDriverOutput(ostream &output, bool compute_xrefs) const
{ {
output << "M_.maximum_exo_det_lag = " << max_exo_det_lag << ";" << endl output << "M_.maximum_exo_det_lag = " << max_exo_det_lag << ";" << endl
<< "M_.maximum_exo_det_lead = " << max_exo_det_lead << ";" << endl << "M_.maximum_exo_det_lead = " << max_exo_det_lead << ";" << endl
<< "oo_.exo_det_steady_state = zeros(" << symbol_table.exo_det_nbr() << ", 1);" << endl; << "oo_.exo_det_steady_state = zeros(" << symbol_table.exo_det_nbr() << ", 1);"
<< endl;
} }
output << "M_.params = " << "NaN(" << symbol_table.param_nbr() << ", 1);" << endl; output << "M_.params = "
<< "NaN(" << symbol_table.param_nbr() << ", 1);" << endl;
string empty_cell = "cell(" + to_string(symbol_table.endo_nbr()) + ", 1)"; string empty_cell = "cell(" + to_string(symbol_table.endo_nbr()) + ", 1)";
output << "M_.endo_trends = struct('deflator', " << empty_cell output << "M_.endo_trends = struct('deflator', " << empty_cell << ", 'log_deflator', "
<< ", 'log_deflator', " << empty_cell << ", 'growth_factor', " << empty_cell << empty_cell << ", 'growth_factor', " << empty_cell << ", 'log_growth_factor', "
<< ", 'log_growth_factor', " << empty_cell << ");" << endl; << empty_cell << ");" << endl;
for (int i = 0; i < symbol_table.endo_nbr(); i++) for (int i = 0; i < symbol_table.endo_nbr(); i++)
{ {
int symb_id = symbol_table.getID(SymbolType::endogenous, i); int symb_id = symbol_table.getID(SymbolType::endogenous, i);
if (auto it = nonstationary_symbols_map.find(symb_id); it != nonstationary_symbols_map.end()) if (auto it = nonstationary_symbols_map.find(symb_id); it != nonstationary_symbols_map.end())
{ {
auto [is_log, deflator] = it->second; auto [is_log, deflator] = it->second;
output << "M_.endo_trends(" << i+1 << ")." output << "M_.endo_trends(" << i + 1 << ")." << (is_log ? "log_deflator" : "deflator")
<< (is_log ? "log_deflator" : "deflator") << " = '"; << " = '";
deflator->writeJsonOutput(output, {}, {}); deflator->writeJsonOutput(output, {}, {});
output << "';" << endl; output << "';" << endl;
auto growth_factor = const_cast<DynamicModel *>(this)->AddDivide(deflator, deflator->decreaseLeadsLags(1))->removeTrendLeadLag(trend_symbols_map)->replaceTrendVar(); auto growth_factor = const_cast<DynamicModel*>(this)
->AddDivide(deflator, deflator->decreaseLeadsLags(1))
->removeTrendLeadLag(trend_symbols_map)
->replaceTrendVar();
output << "M_.endo_trends(" << i + 1 << ")." output << "M_.endo_trends(" << i + 1 << ")."
<< (is_log ? "log_growth_factor" : "growth_factor") << " = '"; << (is_log ? "log_growth_factor" : "growth_factor") << " = '";
growth_factor->writeJsonOutput(output, {}, {}); growth_factor->writeJsonOutput(output, {}, {});
...@@ -1048,7 +1129,7 @@ DynamicModel::writeDriverOutput(ostream &output, bool compute_xrefs) const ...@@ -1048,7 +1129,7 @@ DynamicModel::writeDriverOutput(ostream &output, bool compute_xrefs) const
output << (i > computed_derivs_order ? -1 : NNZDerivatives[i]) << "; "; output << (i > computed_derivs_order ? -1 : NNZDerivatives[i]) << "; ";
output << "];" << endl; output << "];" << endl;
writeDriverSparseIndicesHelper<true>(output); writeDriverSparseIndicesHelper("dynamic", output);
// Write LHS of each equation in text form // Write LHS of each equation in text form
output << "M_.lhs = {" << endl; output << "M_.lhs = {" << endl;
...@@ -1059,6 +1140,11 @@ DynamicModel::writeDriverOutput(ostream &output, bool compute_xrefs) const ...@@ -1059,6 +1140,11 @@ DynamicModel::writeDriverOutput(ostream &output, bool compute_xrefs) const
output << "'; " << endl; output << "'; " << endl;
} }
output << "};" << endl; output << "};" << endl;
output << "M_.dynamic_mcp_equations_reordering = [";
for (auto i : mcp_equations_reordering)
output << i + 1 << "; ";
output << "];" << endl;
} }
void void
...@@ -1075,8 +1161,8 @@ DynamicModel::updateVarAndTrendModel() const ...@@ -1075,8 +1161,8 @@ DynamicModel::updateVarAndTrendModel() const
{ {
map<string, vector<optional<int>>> trend_varr; map<string, vector<optional<int>>> trend_varr;
map<string, vector<set<pair<int, int>>>> rhsr; map<string, vector<set<pair<int, int>>>> rhsr;
for (const auto &[model_name, eqns] : (var ? var_model_table.getEqNums() for (const auto& [model_name, eqns] :
: trend_component_model_table.getEqNums())) (var ? var_model_table.getEqNums() : trend_component_model_table.getEqNums()))
{ {
vector<int> lhs, trend_lhs; vector<int> lhs, trend_lhs;
vector<optional<int>> trend_var; vector<optional<int>> trend_var;
...@@ -1115,25 +1201,28 @@ DynamicModel::updateVarAndTrendModel() const ...@@ -1115,25 +1201,28 @@ DynamicModel::updateVarAndTrendModel() const
catch (...) catch (...)
{ {
} }
optional<int> trend_var_symb_id = equations[eqn]->arg2->findTargetVariable(lhs_symb_id); optional<int> trend_var_symb_id
= equations[eqn]->arg2->findTargetVariable(lhs_symb_id);
if (trend_var_symb_id) if (trend_var_symb_id)
{ {
if (symbol_table.isDiffAuxiliaryVariable(*trend_var_symb_id)) if (symbol_table.isDiffAuxiliaryVariable(*trend_var_symb_id))
try try
{ {
trend_var_symb_id = symbol_table.getOrigSymbIdForAuxVar(*trend_var_symb_id); trend_var_symb_id
= symbol_table.getOrigSymbIdForAuxVar(*trend_var_symb_id);
} }
catch (...) catch (...)
{ {
} }
if (find(trend_lhs.begin(), trend_lhs.end(), *trend_var_symb_id) == trend_lhs.end()) if (ranges::find(trend_lhs, *trend_var_symb_id) == trend_lhs.end())
{ {
cerr << "ERROR: trend found in trend_component equation #" << eqn << " (" cerr << "ERROR: trend found in trend_component equation #" << eqn << " ("
<< symbol_table.getName(*trend_var_symb_id) << ") does not correspond to a trend equation" << endl; << symbol_table.getName(*trend_var_symb_id)
<< ") does not correspond to a trend equation" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
trend_var.push_back(move(trend_var_symb_id)); trend_var.push_back(trend_var_symb_id);
} }
} }
...@@ -1237,13 +1326,16 @@ DynamicModel::fillVarModelTableFromOrigModel() const ...@@ -1237,13 +1326,16 @@ DynamicModel::fillVarModelTableFromOrigModel() const
if (lag > 0) if (lag > 0)
{ {
cerr << "ERROR: in Equation " << eqtag.value_or(to_string(eqn + 1)) cerr << "ERROR: in Equation " << eqtag.value_or(to_string(eqn + 1))
<< ". A VAR model may not have leaded endogenous variables on the RHS. " << endl; << ". A VAR model may not have leaded endogenous variables on the RHS. "
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else if (!var_model_table.getStructural().at(model_name) && lag == 0) else if (!var_model_table.getStructural().at(model_name) && lag == 0)
{ {
cerr << "ERROR: in Equation " << eqtag.value_or(to_string(eqn + 1)) cerr << "ERROR: in Equation " << eqtag.value_or(to_string(eqn + 1))
<< ". A non-structural VAR model may not have contemporaneous endogenous variables on the RHS. " << endl; << ". A non-structural VAR model may not have contemporaneous endogenous "
"variables on the RHS. "
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -1252,15 +1344,16 @@ DynamicModel::fillVarModelTableFromOrigModel() const ...@@ -1252,15 +1344,16 @@ DynamicModel::fillVarModelTableFromOrigModel() const
if (lag != 0) if (lag != 0)
{ {
cerr << "ERROR: in Equation " << eqtag.value_or(to_string(eqn + 1)) cerr << "ERROR: in Equation " << eqtag.value_or(to_string(eqn + 1))
<< ". A VAR model may not have lagged or leaded exogenous variables on the RHS. " << endl; << ". A VAR model may not have lagged or leaded exogenous variables on the "
"RHS. "
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// save lhs variables // save lhs variables
equations[eqn]->arg1->collectVARLHSVariable(lhs); equations[eqn]->arg1->collectVARLHSVariable(lhs);
equations[eqn]->arg1->countDiffs() > 0 ? diff_vec.push_back(equations[eqn]->arg1->countDiffs() > 0);
diff_vec.push_back(true) : diff_vec.push_back(false);
if (diff_vec.back()) if (diff_vec.back())
{ {
set<pair<int, int>> diff_set; set<pair<int, int>> diff_set;
...@@ -1272,11 +1365,10 @@ DynamicModel::fillVarModelTableFromOrigModel() const ...@@ -1272,11 +1365,10 @@ DynamicModel::fillVarModelTableFromOrigModel() const
<< eqn << endl; << eqn << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
orig_diff_var_vec.push_back(diff_set.begin()->first); orig_diff_var_vec.emplace_back(diff_set.begin()->first);
} }
else else
orig_diff_var_vec.push_back(nullopt); orig_diff_var_vec.emplace_back(nullopt);
} }
if (eqns.size() != lhs.size()) if (eqns.size() != lhs.size())
...@@ -1310,8 +1402,7 @@ DynamicModel::getVARDerivIDs(int lhs_symb_id, int lead_lag) const ...@@ -1310,8 +1402,7 @@ DynamicModel::getVARDerivIDs(int lhs_symb_id, int lead_lag) const
vector<int> deriv_ids; vector<int> deriv_ids;
// First directly look for the variable itself // First directly look for the variable itself
if (auto it = deriv_id_table.find({ lhs_symb_id, lead_lag }); if (auto it = deriv_id_table.find({lhs_symb_id, lead_lag}); it != deriv_id_table.end())
it != deriv_id_table.end())
deriv_ids.push_back(it->second); deriv_ids.push_back(it->second);
// Then go through auxiliary variables // Then go through auxiliary variables
...@@ -1371,7 +1462,7 @@ DynamicModel::fillVarModelTableMatrices() ...@@ -1371,7 +1462,7 @@ DynamicModel::fillVarModelTableMatrices()
// Fill autoregressive matrix (AR) // Fill autoregressive matrix (AR)
for (int lag = 1; lag <= max_lag; lag++) for (int lag = 1; lag <= max_lag; lag++)
{ {
vector<int> deriv_ids = getVARDerivIDs(lhs_symb_id, -lag);; vector<int> deriv_ids = getVARDerivIDs(lhs_symb_id, -lag);
for (size_t i = 0; i < eqns.size(); i++) for (size_t i = 0; i < eqns.size(); i++)
{ {
expr_t d = Zero; expr_t d = Zero;
...@@ -1381,7 +1472,10 @@ DynamicModel::fillVarModelTableMatrices() ...@@ -1381,7 +1472,10 @@ DynamicModel::fillVarModelTableMatrices()
{ {
if (!d->isConstant()) if (!d->isConstant())
{ {
cerr << "ERROR: Equation " << equation_tags.getTagValueByEqnAndKey(eqns[i], "name").value_or(to_string(eqns[i]+1)) << " is not linear" << endl; cerr << "ERROR: Equation "
<< equation_tags.getTagValueByEqnAndKey(eqns[i], "name")
.value_or(to_string(eqns[i] + 1))
<< " is not linear" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -1399,7 +1493,10 @@ DynamicModel::fillVarModelTableMatrices() ...@@ -1399,7 +1493,10 @@ DynamicModel::fillVarModelTableMatrices()
{ {
if (!d->isConstant()) if (!d->isConstant())
{ {
cerr << "ERROR: Equation " << equation_tags.getTagValueByEqnAndKey(eqns[i], "name").value_or(to_string(eqns[i]+1)) << " is not linear" << endl; cerr << "ERROR: Equation "
<< equation_tags.getTagValueByEqnAndKey(eqns[i], "name")
.value_or(to_string(eqns[i] + 1))
<< " is not linear" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -1414,7 +1511,9 @@ DynamicModel::fillVarModelTableMatrices() ...@@ -1414,7 +1511,9 @@ DynamicModel::fillVarModelTableMatrices()
{ {
auto rhs = equations[eqns[i]]->arg2; auto rhs = equations[eqns[i]]->arg2;
map<VariableNode*, NumConstNode*> subst_table; map<VariableNode*, NumConstNode*> subst_table;
auto rhs_vars = var_model_table.getRhs(model_name)[i]; // All the (transformed) endogenous on RHS, as computed by updateVarAndTrendModel() auto rhs_vars = var_model_table.getRhs(
model_name)[i]; // All the (transformed) endogenous on RHS, as computed by
// updateVarAndTrendModel()
rhs->collectDynamicVariables(SymbolType::exogenous, rhs_vars); // Add exos rhs->collectDynamicVariables(SymbolType::exogenous, rhs_vars); // Add exos
for (auto [symb_id, lag] : rhs_vars) for (auto [symb_id, lag] : rhs_vars)
subst_table[AddVariable(symb_id, lag)] = Zero; subst_table[AddVariable(symb_id, lag)] = Zero;
...@@ -1437,8 +1536,7 @@ DynamicModel::computeAutoregressiveMatrices() const ...@@ -1437,8 +1536,7 @@ DynamicModel::computeAutoregressiveMatrices() const
{ {
map<tuple<int, int, int>, expr_t> AR; map<tuple<int, int, int>, expr_t> AR;
const vector<int>& lhs = trend_component_model_table.getNonTargetLhs(model_name); const vector<int>& lhs = trend_component_model_table.getNonTargetLhs(model_name);
for (int i{0}; for (int i {0}; auto eqn : eqns)
auto eqn : eqns)
{ {
auto bopn = dynamic_cast<BinaryOpNode*>(equations[eqn]->arg2); auto bopn = dynamic_cast<BinaryOpNode*>(equations[eqn]->arg2);
bopn->fillAutoregressiveRow(i++, lhs, AR); bopn->fillAutoregressiveRow(i++, lhs, AR);
...@@ -1493,7 +1591,8 @@ DynamicModel::fillTrendComponentModelTable() const ...@@ -1493,7 +1591,8 @@ DynamicModel::fillTrendComponentModelTable() const
if (lhs_set.size() != 1 || !lhs_tmp_set.empty()) if (lhs_set.size() != 1 || !lhs_tmp_set.empty())
{ {
cerr << "ERROR: in Equation " << eqtag cerr << "ERROR: in Equation " << eqtag
<< ". A trend component model may only have one endogenous variable on the LHS. " << endl; << ". A trend component model may only have one endogenous variable on the LHS. "
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -1501,7 +1600,8 @@ DynamicModel::fillTrendComponentModelTable() const ...@@ -1501,7 +1600,8 @@ DynamicModel::fillTrendComponentModelTable() const
if (itlhs->second != 0) if (itlhs->second != 0)
{ {
cerr << "ERROR: in Equation " << eqtag cerr << "ERROR: in Equation " << eqtag
<< ". The variable on the LHS of a trend component model may not appear with a lead or a lag. " << ". The variable on the LHS of a trend component model may not appear with a "
"lead or a lag. "
<< endl; << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -1522,7 +1622,8 @@ DynamicModel::fillTrendComponentModelTable() const ...@@ -1522,7 +1622,8 @@ DynamicModel::fillTrendComponentModelTable() const
rhsr[model_name] = rhs; rhsr[model_name] = rhs;
} }
trend_component_model_table.setRhs(move(rhsr)); trend_component_model_table.setRhs(move(rhsr));
trend_component_model_table.setVals(move(eqnums), move(trend_eqnums), move(lhsr), move(lhs_expr_tr)); trend_component_model_table.setVals(move(eqnums), move(trend_eqnums), move(lhsr),
move(lhs_expr_tr));
} }
pair<map<string, map<tuple<int, int>, expr_t>>, map<string, map<tuple<int, int>, expr_t>>> pair<map<string, map<tuple<int, int>, expr_t>>, map<string, map<tuple<int, int>, expr_t>>>
...@@ -1538,18 +1639,17 @@ DynamicModel::computeErrorComponentMatrices(const ExprNode::subst_table_t &diff_ ...@@ -1538,18 +1639,17 @@ DynamicModel::computeErrorComponentMatrices(const ExprNode::subst_table_t &diff_
vector<int> undiff_nontarget_lhs = getUndiffLHSForPac(model_name, diff_subst_table); vector<int> undiff_nontarget_lhs = getUndiffLHSForPac(model_name, diff_subst_table);
vector<int> parsed_undiff_nontarget_lhs; vector<int> parsed_undiff_nontarget_lhs;
for (int i{0}; for (int i {0}; auto eqn : eqns)
auto eqn : eqns)
{ {
if (find(nontarget_eqnums.begin(), nontarget_eqnums.end(), eqn) != nontarget_eqnums.end()) if (ranges::find(nontarget_eqnums, eqn) != nontarget_eqnums.end())
parsed_undiff_nontarget_lhs.push_back(undiff_nontarget_lhs.at(i)); parsed_undiff_nontarget_lhs.push_back(undiff_nontarget_lhs.at(i));
i++; i++;
} }
for (int i{0}; for (int i {0}; auto eqn : eqns)
auto eqn : eqns) if (ranges::find(nontarget_eqnums, eqn) != nontarget_eqnums.end())
if (find(nontarget_eqnums.begin(), nontarget_eqnums.end(), eqn) != nontarget_eqnums.end()) equations[eqn]->arg2->fillErrorCorrectionRow(i++, parsed_undiff_nontarget_lhs, target_lhs,
equations[eqn]->arg2->fillErrorCorrectionRow(i++, parsed_undiff_nontarget_lhs, target_lhs, A0, A0star); A0, A0star);
A0r[model_name] = A0; A0r[model_name] = A0;
A0starr[model_name] = A0star; A0starr[model_name] = A0star;
} }
...@@ -1578,7 +1678,9 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel() const ...@@ -1578,7 +1678,9 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel() const
if (lag >= 0) if (lag >= 0)
{ {
cerr << "ERROR: in Equation " << eqtag.value_or(to_string(eqn + 1)) cerr << "ERROR: in Equation " << eqtag.value_or(to_string(eqn + 1))
<< ". A trend component model may not have leaded or contemporaneous endogenous variables on the RHS. " << endl; << ". A trend component model may not have leaded or contemporaneous "
"endogenous variables on the RHS. "
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
equations[eqn]->arg2->collectDynamicVariables(SymbolType::exogenous, rhs_exo_set); equations[eqn]->arg2->collectDynamicVariables(SymbolType::exogenous, rhs_exo_set);
...@@ -1586,17 +1688,16 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel() const ...@@ -1586,17 +1688,16 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel() const
if (lag != 0) if (lag != 0)
{ {
cerr << "ERROR: in Equation " << eqtag.value_or(to_string(eqn + 1)) cerr << "ERROR: in Equation " << eqtag.value_or(to_string(eqn + 1))
<< ". A trend component model may not have lagged or leaded exogenous variables on the RHS. " << endl; << ". A trend component model may not have lagged or leaded exogenous "
"variables on the RHS. "
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// save lhs variables // save lhs variables
equations[eqn]->arg1->collectVARLHSVariable(lhs); equations[eqn]->arg1->collectVARLHSVariable(lhs);
if (equations[eqn]->arg1->countDiffs() > 0) diff_vec.push_back(equations[eqn]->arg1->countDiffs() > 0);
diff_vec.push_back(true);
else
diff_vec.push_back(false);
if (diff_vec.back()) if (diff_vec.back())
{ {
set<pair<int, int>> diff_set; set<pair<int, int>> diff_set;
...@@ -1608,10 +1709,10 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel() const ...@@ -1608,10 +1709,10 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel() const
<< eqn << endl; << eqn << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
orig_diff_var_vec.push_back(diff_set.begin()->first); orig_diff_var_vec.emplace_back(diff_set.begin()->first);
} }
else else
orig_diff_var_vec.push_back(nullopt); orig_diff_var_vec.emplace_back(nullopt);
} }
if (eqns.size() != lhs.size()) if (eqns.size() != lhs.size())
...@@ -1640,7 +1741,8 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel() const ...@@ -1640,7 +1741,8 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel() const
} }
void void
DynamicModel::fillTrendComponentModelTableAREC(const ExprNode::subst_table_t &diff_subst_table) const DynamicModel::fillTrendComponentModelTableAREC(
const ExprNode::subst_table_t& diff_subst_table) const
{ {
auto ARr = computeAutoregressiveMatrices(); auto ARr = computeAutoregressiveMatrices();
trend_component_model_table.setAR(move(ARr)); trend_component_model_table.setAR(move(ARr));
...@@ -1660,7 +1762,7 @@ DynamicModel::getUndiffLHSForPac(const string &aux_model_name, ...@@ -1660,7 +1762,7 @@ DynamicModel::getUndiffLHSForPac(const string &aux_model_name,
for (auto eqn : nontrend_eqnums) for (auto eqn : nontrend_eqnums)
{ {
auto i = distance(eqnumber.begin(), find(eqnumber.begin(), eqnumber.end(), eqn)); auto i = ranges::distance(eqnumber.begin(), ranges::find(eqnumber, eqn));
if (eqnumber[i] != eqn) if (eqnumber[i] != eqn)
{ {
...@@ -1668,7 +1770,7 @@ DynamicModel::getUndiffLHSForPac(const string &aux_model_name, ...@@ -1668,7 +1770,7 @@ DynamicModel::getUndiffLHSForPac(const string &aux_model_name,
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (diff.at(i) != true) if (!diff.at(i))
{ {
cerr << "ERROR: the variable on the LHS of equation #" << eqn cerr << "ERROR: the variable on the LHS of equation #" << eqn
<< " does not have the diff operator applied to it yet you are trying to undiff it." << " does not have the diff operator applied to it yet you are trying to undiff it."
...@@ -1676,7 +1778,6 @@ DynamicModel::getUndiffLHSForPac(const string &aux_model_name, ...@@ -1676,7 +1778,6 @@ DynamicModel::getUndiffLHSForPac(const string &aux_model_name,
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
bool printerr = false;
expr_t node = nullptr; expr_t node = nullptr;
expr_t aux_var = lhs_expr_t.at(i); expr_t aux_var = lhs_expr_t.at(i);
for (const auto& it : diff_subst_table) for (const auto& it : diff_subst_table)
...@@ -1693,11 +1794,8 @@ DynamicModel::getUndiffLHSForPac(const string &aux_model_name, ...@@ -1693,11 +1794,8 @@ DynamicModel::getUndiffLHSForPac(const string &aux_model_name,
} }
node = node->undiff(); node = node->undiff();
auto it1 = diff_subst_table.find(node);
if (it1 == diff_subst_table.end())
printerr = true;
if (printerr) if (auto it1 = diff_subst_table.find(node); it1 == diff_subst_table.end())
{ // we have undiffed something like diff(x), hence x is not in diff_subst_table { // we have undiffed something like diff(x), hence x is not in diff_subst_table
lhs_expr_t.at(i) = node; lhs_expr_t.at(i) = node;
lhs.at(i) = dynamic_cast<VariableNode*>(node)->symb_id; lhs.at(i) = dynamic_cast<VariableNode*>(node)->symb_id;
...@@ -1712,20 +1810,25 @@ DynamicModel::getUndiffLHSForPac(const string &aux_model_name, ...@@ -1712,20 +1810,25 @@ DynamicModel::getUndiffLHSForPac(const string &aux_model_name,
} }
void void
DynamicModel::analyzePacEquationStructure(const string &name, map<string, string> &pac_eq_name, PacModelTable::equation_info_t &pac_equation_info) DynamicModel::analyzePacEquationStructure(const string& name, map<string, string>& pac_eq_name,
PacModelTable::equation_info_t& pac_equation_info)
{ {
for (auto& equation : equations) for (auto& equation : equations)
if (equation->containsPacExpectation(name)) if (equation->containsPacExpectation(name))
{ {
if (!pac_eq_name[name].empty()) if (pac_eq_name.contains(name))
{ {
cerr << "It is not possible to use 'pac_expectation(" << name << ")' in several equations." << endl; cerr << "It is not possible to use 'pac_expectation(" << name
<< ")' in several equations." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
optional<string> eqn { equation_tags.getTagValueByEqnAndKey(&equation - &equations[0], "name") }; optional<string> eqn {
equation_tags.getTagValueByEqnAndKey(&equation - &equations[0], "name")};
if (!eqn) if (!eqn)
{ {
cerr << "Every equation with a 'pac_expectation' operator must have been assigned an equation tag name" << endl; cerr << "Every equation with a 'pac_expectation' operator must have been assigned an "
"equation tag name"
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
pac_eq_name[name] = *eqn; pac_eq_name[name] = *eqn;
...@@ -1755,7 +1858,8 @@ DynamicModel::analyzePacEquationStructure(const string &name, map<string, string ...@@ -1755,7 +1858,8 @@ DynamicModel::analyzePacEquationStructure(const string &name, map<string, string
pair<int, vector<tuple<int, bool, int>>> ec_params_and_vars; pair<int, vector<tuple<int, bool, int>>> ec_params_and_vars;
vector<tuple<optional<int>, optional<int>, int>> ar_params_and_vars; vector<tuple<optional<int>, optional<int>, int>> ar_params_and_vars;
vector<tuple<int, int, optional<int>, double>> non_optim_vars_params_and_constants, optim_additive_vars_params_and_constants, additive_vars_params_and_constants; vector<tuple<int, int, optional<int>, double>> non_optim_vars_params_and_constants,
optim_additive_vars_params_and_constants, additive_vars_params_and_constants;
if (!optim_part) if (!optim_part)
{ {
auto bopn = dynamic_cast<BinaryOpNode*>(equation->arg2); auto bopn = dynamic_cast<BinaryOpNode*>(equation->arg2);
...@@ -1764,7 +1868,8 @@ DynamicModel::analyzePacEquationStructure(const string &name, map<string, string ...@@ -1764,7 +1868,8 @@ DynamicModel::analyzePacEquationStructure(const string &name, map<string, string
cerr << "Error in PAC equation" << endl; cerr << "Error in PAC equation" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
bopn->getPacAREC(lhs_symb_id, lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars, additive_vars_params_and_constants); bopn->getPacAREC(lhs_symb_id, lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars,
additive_vars_params_and_constants);
} }
else else
{ {
...@@ -1774,12 +1879,15 @@ DynamicModel::analyzePacEquationStructure(const string &name, map<string, string ...@@ -1774,12 +1879,15 @@ DynamicModel::analyzePacEquationStructure(const string &name, map<string, string
cerr << "Error in PAC equation" << endl; cerr << "Error in PAC equation" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
bopn->getPacAREC(lhs_symb_id, lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars, optim_additive_vars_params_and_constants); bopn->getPacAREC(lhs_symb_id, lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars,
optim_additive_vars_params_and_constants);
try try
{ {
non_optim_vars_params_and_constants = non_optim_part->matchLinearCombinationOfVariables(); non_optim_vars_params_and_constants
= non_optim_part->matchLinearCombinationOfVariables();
if (additive_part) if (additive_part)
additive_vars_params_and_constants = additive_part->matchLinearCombinationOfVariables(); additive_vars_params_and_constants
= additive_part->matchLinearCombinationOfVariables();
} }
catch (ExprNode::MatchFailureException& e) catch (ExprNode::MatchFailureException& e)
{ {
...@@ -1799,12 +1907,21 @@ DynamicModel::analyzePacEquationStructure(const string &name, map<string, string ...@@ -1799,12 +1907,21 @@ DynamicModel::analyzePacEquationStructure(const string &name, map<string, string
cerr << "analyzePacEquationStructure: error obtaining RHS parameters." << endl; cerr << "analyzePacEquationStructure: error obtaining RHS parameters." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
pac_equation_info[name] = { lhs, move(optim_share_index), pac_equation_info[name] = {lhs,
move(ar_params_and_vars), move(ec_params_and_vars), optim_share_index,
move(ar_params_and_vars),
move(ec_params_and_vars),
move(non_optim_vars_params_and_constants), move(non_optim_vars_params_and_constants),
move(additive_vars_params_and_constants), move(additive_vars_params_and_constants),
move(optim_additive_vars_params_and_constants)}; move(optim_additive_vars_params_and_constants)};
} }
if (!pac_eq_name.contains(name))
{
cerr << "ERROR: the model does not contain the 'pac_expectation(" << name << ")' operator."
<< endl;
exit(EXIT_FAILURE);
}
} }
int int
...@@ -1816,7 +1933,8 @@ DynamicModel::getPacTargetSymbId(const string &pac_model_name) const ...@@ -1816,7 +1933,8 @@ DynamicModel::getPacTargetSymbId(const string &pac_model_name) const
set<pair<int, int>> lhss; set<pair<int, int>> lhss;
equation->arg1->collectDynamicVariables(SymbolType::endogenous, lhss); equation->arg1->collectDynamicVariables(SymbolType::endogenous, lhss);
if (lhss.size() != 1) if (lhss.size() != 1)
throw PacTargetNotIdentifiedException{pac_model_name, "LHS must contain a single endogenous"}; throw PacTargetNotIdentifiedException {pac_model_name,
"LHS must contain a single endogenous"};
int lhs_symb_id = lhss.begin()->first; int lhs_symb_id = lhss.begin()->first;
if (!symbol_table.isDiffAuxiliaryVariable(lhs_symb_id)) if (!symbol_table.isDiffAuxiliaryVariable(lhs_symb_id))
throw PacTargetNotIdentifiedException {pac_model_name, "LHS must be a diff operator"}; throw PacTargetNotIdentifiedException {pac_model_name, "LHS must be a diff operator"};
...@@ -1835,26 +1953,25 @@ DynamicModel::getPacTargetSymbId(const string &pac_model_name) const ...@@ -1835,26 +1953,25 @@ DynamicModel::getPacTargetSymbId(const string &pac_model_name) const
for (auto [term, sign] : terms) for (auto [term, sign] : terms)
try try
{ {
auto [param_id, target_id] = term->matchParamTimesTargetMinusVariable(undiff_lhs_symb_id); auto [param_id, target_id]
= term->matchParamTimesTargetMinusVariable(undiff_lhs_symb_id);
return target_id; return target_id;
} }
catch (ExprNode::MatchFailureException&) catch (ExprNode::MatchFailureException&)
{ {
} }
throw PacTargetNotIdentifiedException{pac_model_name, "No term of the form parameter*(target-LHS_level)"}; throw PacTargetNotIdentifiedException {pac_model_name,
"No term of the form parameter*(target-LHS_level)"};
} }
throw PacTargetNotIdentifiedException{pac_model_name, "No equation with the corresponding pac_expectation operator"}; throw PacTargetNotIdentifiedException {
pac_model_name, "No equation with the corresponding pac_expectation operator"};
} }
void void
DynamicModel::computePacModelConsistentExpectationSubstitution(const string &name, DynamicModel::computePacModelConsistentExpectationSubstitution(
int discount_symb_id, const string& name, int discount_symb_id, int pac_eq_max_lag, expr_t growth_correction_term,
int pac_eq_max_lag, string auxname, ExprNode::subst_table_t& diff_subst_table,
expr_t growth_correction_term, map<string, int>& pac_aux_var_symb_ids, map<string, vector<int>>& pac_aux_param_symb_ids,
string auxname,
ExprNode::subst_table_t &diff_subst_table,
map<string, int> &pac_aux_var_symb_ids,
map<string, vector<int>> &pac_aux_param_symb_ids,
map<string, expr_t>& pac_expectation_substitution) map<string, expr_t>& pac_expectation_substitution)
{ {
int pac_target_symb_id; int pac_target_symb_id;
...@@ -1886,22 +2003,22 @@ DynamicModel::computePacModelConsistentExpectationSubstitution(const string &nam ...@@ -1886,22 +2003,22 @@ DynamicModel::computePacModelConsistentExpectationSubstitution(const string &nam
int alpha_i_symb_id = symbol_table.addSymbol(param_name, SymbolType::parameter); int alpha_i_symb_id = symbol_table.addSymbol(param_name, SymbolType::parameter);
pac_aux_param_symb_ids[name].push_back(alpha_i_symb_id); pac_aux_param_symb_ids[name].push_back(alpha_i_symb_id);
A = AddPlus(A, AddVariable(alpha_i_symb_id)); A = AddPlus(A, AddVariable(alpha_i_symb_id));
fp = AddPlus(fp, fp = AddPlus(fp, AddTimes(AddTimes(AddVariable(alpha_i_symb_id),
AddTimes(AddTimes(AddVariable(alpha_i_symb_id),
AddPower(beta, AddPossiblyNegativeConstant(i))), AddPower(beta, AddPossiblyNegativeConstant(i))),
AddVariable(mce_z1_symb_id, i))); AddVariable(mce_z1_symb_id, i)));
} }
catch (SymbolTable::AlreadyDeclaredException& e) catch (SymbolTable::AlreadyDeclaredException& e)
{ {
cerr << "The variable/parameter '" << param_name << "' conflicts with a parameter that will be generated for the '" << name << "' PAC model. Please rename it." << endl; cerr << "The variable/parameter '" << param_name
<< "' conflicts with a parameter that will be generated for the '" << name
<< "' PAC model. Please rename it." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
// Add diff nodes and eqs for pac_target_symb_id // Add diff nodes and eqs for pac_target_symb_id
const VariableNode* target_base_diff_node; const VariableNode* target_base_diff_node;
auto create_target_lag = [&](int lag) auto create_target_lag = [&](int lag) {
{
if (symbol_table.isAuxiliaryVariable(pac_target_symb_id)) if (symbol_table.isAuxiliaryVariable(pac_target_symb_id))
// We know it is a log, see ExprNode::matchParamTimesTargetMinusVariable() // We know it is a log, see ExprNode::matchParamTimesTargetMinusVariable()
return AddLog(AddVariable(symbol_table.getOrigSymbIdForAuxVar(pac_target_symb_id), lag)); return AddLog(AddVariable(symbol_table.getOrigSymbIdForAuxVar(pac_target_symb_id), lag));
...@@ -1910,16 +2027,14 @@ DynamicModel::computePacModelConsistentExpectationSubstitution(const string &nam ...@@ -1910,16 +2027,14 @@ DynamicModel::computePacModelConsistentExpectationSubstitution(const string &nam
}; };
expr_t diff_node_to_search = AddDiff(create_target_lag(0)); expr_t diff_node_to_search = AddDiff(create_target_lag(0));
if (auto sit = diff_subst_table.find(diff_node_to_search); if (auto sit = diff_subst_table.find(diff_node_to_search); sit != diff_subst_table.end())
sit != diff_subst_table.end())
target_base_diff_node = sit->second; target_base_diff_node = sit->second;
else else
{ {
int symb_id = symbol_table.addDiffAuxiliaryVar(diff_node_to_search->idx, diff_node_to_search); int symb_id = symbol_table.addDiffAuxiliaryVar(diff_node_to_search->idx, diff_node_to_search);
target_base_diff_node = AddVariable(symb_id); target_base_diff_node = AddVariable(symb_id);
auto neweq = AddEqual(const_cast<VariableNode*>(target_base_diff_node), auto neweq = AddEqual(const_cast<VariableNode*>(target_base_diff_node),
AddMinus(create_target_lag(0), AddMinus(create_target_lag(0), create_target_lag(-1)));
create_target_lag(-1)));
addEquation(neweq, nullopt); addEquation(neweq, nullopt);
addAuxEquation(neweq); addAuxEquation(neweq);
neqs++; neqs++;
...@@ -1956,19 +2071,21 @@ DynamicModel::computePacModelConsistentExpectationSubstitution(const string &nam ...@@ -1956,19 +2071,21 @@ DynamicModel::computePacModelConsistentExpectationSubstitution(const string &nam
{ {
alpha_j_symb_id = symbol_table.addSymbol(param_name, SymbolType::parameter); alpha_j_symb_id = symbol_table.addSymbol(param_name, SymbolType::parameter);
} }
ssum = AddPlus(ssum, ssum = AddPlus(ssum, AddTimes(AddVariable(alpha_j_symb_id),
AddTimes(AddVariable(alpha_j_symb_id), AddPower(beta, AddPossiblyNegativeConstant(j)))); AddPower(beta, AddPossiblyNegativeConstant(j))));
} }
fs = AddPlus(fs, AddTimes(ssum, target_aux_var_to_add[k])); fs = AddPlus(fs, AddTimes(ssum, target_aux_var_to_add[k]));
} }
auto neweq = AddEqual(AddVariable(mce_z1_symb_id), auto neweq = AddEqual(
AddVariable(mce_z1_symb_id),
AddMinus(AddTimes(A, AddMinus(const_cast<VariableNode*>(target_base_diff_node), fs)), fp)); AddMinus(AddTimes(A, AddMinus(const_cast<VariableNode*>(target_base_diff_node), fs)), fp));
addEquation(neweq, nullopt); addEquation(neweq, nullopt);
/* This equation is not added to the list of auxiliary equations, because it /* This equation is not added to the list of auxiliary equations, because it
is recursive, and this would in particular break dynamic_set_auxiliary_series.m */ is recursive, and this would in particular break dynamic_set_auxiliary_series.m */
neqs++; neqs++;
cout << "PAC Model Consistent Expectation: added " << neqs << " auxiliary variables and equations for model " << name << "." << endl; cout << "PAC Model Consistent Expectation: added " << neqs
<< " auxiliary variables and equations for model " << name << "." << endl;
/* The growth correction term is not added to the definition of Z₁ /* The growth correction term is not added to the definition of Z₁
because the latter is recursive. Rather put it at the level of the because the latter is recursive. Rather put it at the level of the
...@@ -1977,25 +2094,219 @@ DynamicModel::computePacModelConsistentExpectationSubstitution(const string &nam ...@@ -1977,25 +2094,219 @@ DynamicModel::computePacModelConsistentExpectationSubstitution(const string &nam
} }
void void
DynamicModel::computePacBackwardExpectationSubstitution(const string &name, DynamicModel::computePacModelConsistentExpectationSubstitutionWithComponents(
const vector<int> &lhs, const string& name, int discount_symb_id, int pac_eq_max_lag,
int max_lag, ExprNode::subst_table_t& diff_subst_table, map<string, vector<int>>& pac_aux_param_symb_ids,
const string &aux_model_type, vector<PacModelTable::target_component_t>& pac_target_components,
expr_t growth_correction_term,
string auxname,
map<string, int> &pac_aux_var_symb_ids,
map<string, vector<int>> &pac_aux_param_symb_ids,
map<string, expr_t>& pac_expectation_substitution) map<string, expr_t>& pac_expectation_substitution)
{ {
auto create_aux_param = [&](const string &param_name) auto create_aux_param = [&](const string& param_name) {
try
{
return symbol_table.addSymbol(param_name, SymbolType::parameter);
}
catch (SymbolTable::AlreadyDeclaredException)
{
cerr << "ERROR: the variable/parameter '" << param_name
<< "' conflicts with some auxiliary parameter that will be generated for the '" << name
<< "' PAC model. Please rename that parameter." << endl;
exit(EXIT_FAILURE);
}
};
int neqs = 0;
// At the end of this loop:
// ₘ ₘ
// A_1 = 1+∑ αᵢ = A(1) and A_beta = 1+∑ αᵢβⁱ
// ᵢ₌₁ ᵢ₌₁
expr_t A_1 = One;
expr_t A_beta = One;
expr_t beta = AddVariable(discount_symb_id);
for (int i = 1; i <= pac_eq_max_lag + 1; i++)
{
string param_name = "mce_alpha_" + name + "_" + to_string(i);
try
{
int alpha_i_symb_id = symbol_table.addSymbol(param_name, SymbolType::parameter);
pac_aux_param_symb_ids[name].push_back(alpha_i_symb_id);
A_1 = AddPlus(A_1, AddVariable(alpha_i_symb_id));
A_beta = AddPlus(A_beta, AddTimes(AddVariable(alpha_i_symb_id),
AddPower(beta, AddPossiblyNegativeConstant(i))));
}
catch (SymbolTable::AlreadyDeclaredException& e)
{
cerr << "The variable/parameter '" << param_name
<< "' conflicts with a parameter that will be generated for the '" << name
<< "' PAC model. Please rename it." << endl;
exit(EXIT_FAILURE);
}
}
auto create_target_lag = [&](int variable, int lag) {
if (symbol_table.isAuxiliaryVariable(variable))
return AddVariable(symbol_table.getOrigSymbIdForAuxVar(variable), lag);
else
return AddVariable(variable, lag);
};
expr_t substexpr = Zero;
for (int component_idx {1};
auto& [component, growth, auxname, kind, coeff, growth_neutrality_param, h_indices,
original_growth, growth_info] : pac_target_components)
{
// Create the auxiliary variable for this component
int aux_id = symbol_table.addPacExpectationAuxiliaryVar(auxname, component);
// Get the component variable id
int component_id = dynamic_cast<VariableNode*>(component)->symb_id;
// ₘ
// fp = ∑ αᵢβⁱZₜ₊ᵢ
// ᵢ₌₁
expr_t fp = Zero;
for (int i = 1; i <= pac_eq_max_lag + 1; i++)
{
int alpha_i_symb_id = -1;
string param_name = "mce_alpha_" + name + "_" + to_string(i);
try
{
alpha_i_symb_id = symbol_table.getID(param_name);
}
catch (SymbolTable::UnknownSymbolNameException& e)
{
alpha_i_symb_id = symbol_table.addSymbol(param_name, SymbolType::parameter);
}
fp = AddPlus(fp, AddTimes(AddTimes(AddVariable(alpha_i_symb_id),
AddPower(beta, AddPossiblyNegativeConstant(i))),
AddVariable(aux_id, i)));
}
if (kind != PacTargetKind::ll) // non-stationary component y¹ₜ
{
// Add diff nodes and eqs for the non-stationary component
const VariableNode* aux_target_ns_var_diff_node;
expr_t diff_node_to_search = AddDiff(create_target_lag(component_id, 0));
if (auto sit = diff_subst_table.find(diff_node_to_search); sit != diff_subst_table.end())
aux_target_ns_var_diff_node = sit->second;
else
{
int symb_id
= symbol_table.addDiffAuxiliaryVar(diff_node_to_search->idx, diff_node_to_search);
aux_target_ns_var_diff_node = AddVariable(symb_id);
auto neweq = AddEqual(const_cast<VariableNode*>(aux_target_ns_var_diff_node),
AddMinus(create_target_lag(component_id, 0),
create_target_lag(component_id, -1)));
addEquation(neweq, nullopt);
addAuxEquation(neweq);
neqs++;
}
map<int, VariableNode*> target_ns_aux_var_to_add;
const VariableNode* last_aux_var = aux_target_ns_var_diff_node;
for (int i = 1; i <= pac_eq_max_lag; i++, neqs++)
{
expr_t this_diff_node = AddDiff(create_target_lag(component_id, i));
int symb_id = symbol_table.addDiffLeadAuxiliaryVar(
this_diff_node->idx, this_diff_node, last_aux_var->symb_id, 1);
VariableNode* current_aux_var = AddVariable(symb_id);
auto neweq = AddEqual(current_aux_var, AddVariable(last_aux_var->symb_id, 1));
addEquation(neweq, nullopt);
addAuxEquation(neweq);
last_aux_var = current_aux_var;
target_ns_aux_var_to_add[i] = current_aux_var;
}
// At the end of this loop,
// ₘ₋₁ ⎛ ₘ₋₁ ⎞
// fs = ∑ ⎢ ∑ αᵢβⁱ⎥ Δy¹ₜ₊ᵢ
// ₖ₌₁ ⎝ ᵢ₌ₖ ⎠
expr_t fs = Zero;
for (int k = 1; k <= pac_eq_max_lag; k++)
{
expr_t ssum = Zero;
for (int j = k + 1; j <= pac_eq_max_lag + 1; j++)
{
int alpha_j_symb_id = -1;
string param_name = "mce_alpha_" + name + "_" + to_string(j);
try
{
alpha_j_symb_id = symbol_table.getID(param_name);
}
catch (SymbolTable::UnknownSymbolNameException& e)
{
alpha_j_symb_id = symbol_table.addSymbol(param_name, SymbolType::parameter);
}
ssum = AddPlus(ssum, AddTimes(AddVariable(alpha_j_symb_id),
AddPower(beta, AddPossiblyNegativeConstant(j))));
}
fs = AddPlus(fs, AddTimes(ssum, target_ns_aux_var_to_add[k]));
}
// Assembling the equation Zₜ¹ = A_1 ( Δyₜ¹ - fs ) - fp_1
auto neweq_1 = AddEqual(
AddVariable(aux_id),
AddMinus(
AddTimes(A_1,
AddMinus(const_cast<VariableNode*>(aux_target_ns_var_diff_node), fs)),
fp));
addEquation(neweq_1, nullopt);
neqs++;
/* This equation is not added to the list of auxiliary equations, because it
is recursive, and this would in particular break dynamic_set_auxiliary_series.m */
}
else // Stationary component yₜ⁰
{
// Assembling the equation Zₜ⁰ = A_beta A_1 yₜ⁰ - fp
auto neweq_0 = AddEqual(AddVariable(aux_id),
AddMinus(AddTimes(A_beta, AddTimes(A_1, component)), fp));
addEquation(neweq_0, nullopt);
neqs++;
/* This equation is not added to the list of auxiliary equations, because it
is recursive, and this would in particular break dynamic_set_auxiliary_series.m */
}
// If needed, add the growth neutrality correction for this component
expr_t growth_correction_term = Zero;
string name_component = name + "_component" + to_string(component_idx);
if (growth)
{ {
growth_neutrality_param
= create_aux_param(name_component + "_pac_growth_neutrality_correction");
growth_correction_term = AddTimes(growth, AddVariable(growth_neutrality_param));
}
else
growth_neutrality_param = -1;
substexpr = AddPlus(substexpr,
AddTimes(coeff, AddPlus(AddVariable(aux_id), growth_correction_term)));
component_idx++;
}
cout << "PAC Model Consistent Expectation: added " << neqs
<< " auxiliary variables and equations for model " << name << "." << endl;
/* The growth correction term is not added to the definition of Z₁
because the latter is recursive. Rather put it at the level of the
substition of pac_expectation operator. */
pac_expectation_substitution[name] = substexpr;
}
void
DynamicModel::computePacBackwardExpectationSubstitution(
const string& name, const vector<int>& lhs, int max_lag, const string& aux_model_type,
expr_t growth_correction_term, string auxname, map<string, int>& pac_aux_var_symb_ids,
map<string, vector<int>>& pac_aux_param_symb_ids,
map<string, expr_t>& pac_expectation_substitution)
{
auto create_aux_param = [&](const string& param_name) {
try try
{ {
return symbol_table.addSymbol(param_name, SymbolType::parameter); return symbol_table.addSymbol(param_name, SymbolType::parameter);
} }
catch (SymbolTable::AlreadyDeclaredException) catch (SymbolTable::AlreadyDeclaredException)
{ {
cerr << "ERROR: the variable/parameter '" << param_name << "' conflicts with some auxiliary parameter that will be generated for the '" << name << "' PAC model. Please rename that parameter." << endl; cerr << "ERROR: the variable/parameter '" << param_name
<< "' conflicts with some auxiliary parameter that will be generated for the '" << name
<< "' PAC model. Please rename that parameter." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
}; };
...@@ -2012,13 +2323,11 @@ DynamicModel::computePacBackwardExpectationSubstitution(const string &name, ...@@ -2012,13 +2323,11 @@ DynamicModel::computePacBackwardExpectationSubstitution(const string &name,
for (int i = 1; i < max_lag + 1; i++) for (int i = 1; i < max_lag + 1; i++)
for (auto lhsit : lhs) for (auto lhsit : lhs)
{ {
int new_param_symb_id = create_aux_param("h_" + name + "_var_" int new_param_symb_id = create_aux_param("h_" + name + "_var_" + symbol_table.getName(lhsit)
+ symbol_table.getName(lhsit)
+ "_lag_" + to_string(i)); + "_lag_" + to_string(i));
pac_aux_param_symb_ids[name].push_back(new_param_symb_id); pac_aux_param_symb_ids[name].push_back(new_param_symb_id);
subExpr = AddPlus(subExpr, subExpr
AddTimes(AddVariable(new_param_symb_id), = AddPlus(subExpr, AddTimes(AddVariable(new_param_symb_id), AddVariable(lhsit, -i)));
AddVariable(lhsit, -i)));
} }
subExpr = AddPlus(subExpr, growth_correction_term); subExpr = AddPlus(subExpr, growth_correction_term);
...@@ -2034,22 +2343,21 @@ DynamicModel::computePacBackwardExpectationSubstitution(const string &name, ...@@ -2034,22 +2343,21 @@ DynamicModel::computePacBackwardExpectationSubstitution(const string &name,
} }
void void
DynamicModel::computePacBackwardExpectationSubstitutionWithComponents(const string &name, DynamicModel::computePacBackwardExpectationSubstitutionWithComponents(
const vector<int> &lhs, const string& name, const vector<int>& lhs, int max_lag, const string& aux_model_type,
int max_lag,
const string &aux_model_type,
vector<PacModelTable::target_component_t>& pac_target_components, vector<PacModelTable::target_component_t>& pac_target_components,
map<string, expr_t>& pac_expectation_substitution) map<string, expr_t>& pac_expectation_substitution)
{ {
auto create_aux_param = [&](const string &param_name) auto create_aux_param = [&](const string& param_name) {
{
try try
{ {
return symbol_table.addSymbol(param_name, SymbolType::parameter); return symbol_table.addSymbol(param_name, SymbolType::parameter);
} }
catch (SymbolTable::AlreadyDeclaredException) catch (SymbolTable::AlreadyDeclaredException)
{ {
cerr << "ERROR: the variable/parameter '" << param_name << "' conflicts with some auxiliary parameter that will be generated for the '" << name << "' PAC model. Please rename that parameter." << endl; cerr << "ERROR: the variable/parameter '" << param_name
<< "' conflicts with some auxiliary parameter that will be generated for the '" << name
<< "' PAC model. Please rename that parameter." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
}; };
...@@ -2057,7 +2365,8 @@ DynamicModel::computePacBackwardExpectationSubstitutionWithComponents(const stri ...@@ -2057,7 +2365,8 @@ DynamicModel::computePacBackwardExpectationSubstitutionWithComponents(const stri
expr_t substexpr = Zero; expr_t substexpr = Zero;
for (int component_idx {1}; for (int component_idx {1};
auto &[component, growth, auxname, kind, coeff, growth_neutrality_param, h_indices, original_growth, growth_info] : pac_target_components) auto& [component, growth, auxname, kind, coeff, growth_neutrality_param, h_indices,
original_growth, growth_info] : pac_target_components)
{ {
string name_component = name + "_component" + to_string(component_idx); string name_component = name + "_component" + to_string(component_idx);
...@@ -2074,16 +2383,19 @@ DynamicModel::computePacBackwardExpectationSubstitutionWithComponents(const stri ...@@ -2074,16 +2383,19 @@ DynamicModel::computePacBackwardExpectationSubstitutionWithComponents(const stri
for (int i = 1; i < max_lag + 1; i++) for (int i = 1; i < max_lag + 1; i++)
for (auto lhsit : lhs) for (auto lhsit : lhs)
{ {
int new_param_symb_id = create_aux_param("h_" + name_component + "_var_" + symbol_table.getName(lhsit) + "_lag_" + to_string(i)); int new_param_symb_id
= create_aux_param("h_" + name_component + "_var_" + symbol_table.getName(lhsit)
+ "_lag_" + to_string(i));
h_indices.push_back(new_param_symb_id); h_indices.push_back(new_param_symb_id);
auxdef = AddPlus(auxdef, AddTimes(AddVariable(new_param_symb_id), auxdef
AddVariable(lhsit, -i))); = AddPlus(auxdef, AddTimes(AddVariable(new_param_symb_id), AddVariable(lhsit, -i)));
} }
// If needed, add the growth neutrality correction for this component // If needed, add the growth neutrality correction for this component
if (growth) if (growth)
{ {
growth_neutrality_param = create_aux_param(name_component + "_pac_growth_neutrality_correction"); growth_neutrality_param
= create_aux_param(name_component + "_pac_growth_neutrality_correction");
auxdef = AddPlus(auxdef, AddTimes(growth, AddVariable(growth_neutrality_param))); auxdef = AddPlus(auxdef, AddTimes(growth, AddVariable(growth_neutrality_param)));
} }
else else
...@@ -2114,7 +2426,8 @@ DynamicModel::substitutePacExpectation(const map<string, expr_t> &pac_expectatio ...@@ -2114,7 +2426,8 @@ DynamicModel::substitutePacExpectation(const map<string, expr_t> &pac_expectatio
for (auto& [model_name, substexpr] : pac_expectation_substitution) for (auto& [model_name, substexpr] : pac_expectation_substitution)
{ {
optional<int> eq {equation_tags.getEqnByTag("name", pac_eq_name.at(model_name))}; optional<int> eq {equation_tags.getEqnByTag("name", pac_eq_name.at(model_name))};
auto substeq = dynamic_cast<BinaryOpNode *>(equations[eq.value()]->substitutePacExpectation(model_name, substexpr)); auto substeq = dynamic_cast<BinaryOpNode*>(
equations[eq.value()]->substitutePacExpectation(model_name, substexpr));
assert(substeq); assert(substeq);
equations[eq.value()] = substeq; equations[eq.value()] = substeq;
} }
...@@ -2124,12 +2437,14 @@ void ...@@ -2124,12 +2437,14 @@ void
DynamicModel::substitutePacTargetNonstationary(const string& pac_model_name, expr_t substexpr) DynamicModel::substitutePacTargetNonstationary(const string& pac_model_name, expr_t substexpr)
{ {
for (auto& eq : equations) for (auto& eq : equations)
eq = dynamic_cast<BinaryOpNode *>(eq->substitutePacTargetNonstationary(pac_model_name, substexpr)); eq = dynamic_cast<BinaryOpNode*>(
eq->substitutePacTargetNonstationary(pac_model_name, substexpr));
} }
void void
DynamicModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_context_t &eval_context, DynamicModel::computingPass(int derivsOrder, int paramsDerivsOrder,
bool no_tmp_terms, bool block, bool use_dll) const eval_context_t& eval_context, bool no_tmp_terms, bool block,
bool use_dll)
{ {
initializeVariablesAndEquations(); initializeVariablesAndEquations();
...@@ -2151,15 +2466,16 @@ DynamicModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_c ...@@ -2151,15 +2466,16 @@ DynamicModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_c
removed once the legacy representation is dropped). */ removed once the legacy representation is dropped). */
if (log2(getJacobianColsNbr(false)) * derivsOrder >= numeric_limits<int>::digits) if (log2(getJacobianColsNbr(false)) * derivsOrder >= numeric_limits<int>::digits)
{ {
cerr << "ERROR: The derivatives matrix of the " << modelClassName() << " is too large. Please decrease the approximation order." << endl; cerr << "ERROR: The derivatives matrix of the " << modelClassName()
<< " is too large. Please decrease the approximation order." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Compute derivatives w.r. to all endogenous, exogenous and exogenous deterministic // Compute derivatives w.r. to all endogenous, exogenous and exogenous deterministic
set<int> vars; set<int> vars;
for (auto& [symb_lag, deriv_id] : deriv_id_table) for (auto& [symb_lag, deriv_id] : deriv_id_table)
if (SymbolType type = symbol_table.getType(symb_lag.first); if (SymbolType type = symbol_table.getType(symb_lag.first); type == SymbolType::endogenous
type == SymbolType::endogenous || type == SymbolType::exogenous || type == SymbolType::exogenous
|| type == SymbolType::exogenousDet) || type == SymbolType::exogenousDet)
vars.insert(deriv_id); vars.insert(deriv_id);
...@@ -2174,7 +2490,8 @@ DynamicModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_c ...@@ -2174,7 +2490,8 @@ DynamicModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_c
if (paramsDerivsOrder > 0) if (paramsDerivsOrder > 0)
{ {
cout << "Computing " << modelClassName() << " derivatives w.r.t. parameters (order " << paramsDerivsOrder << ")." << endl; cout << "Computing " << modelClassName() << " derivatives w.r.t. parameters (order "
<< paramsDerivsOrder << ")." << endl;
computeParamsDerivatives(paramsDerivsOrder); computeParamsDerivatives(paramsDerivsOrder);
} }
...@@ -2199,21 +2516,21 @@ DynamicModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_c ...@@ -2199,21 +2516,21 @@ DynamicModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_c
cerr << "ERROR: Block decomposition requested but failed." << endl; cerr << "ERROR: Block decomposition requested but failed." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
computeMCPEquationsReordering();
} }
void void
DynamicModel::computeXrefs() DynamicModel::computeXrefs()
{ {
for (int i{0}; for (int i {0}; auto& equation : equations)
auto &equation : equations)
{ {
ExprNode::EquationInfo ei; ExprNode::EquationInfo ei;
equation->computeXrefs(ei); equation->computeXrefs(ei);
xrefs[i++] = ei; xrefs[i++] = ei;
} }
for (int i{0}; for (int i {0}; const auto& [eq, eqinfo] : xrefs)
const auto &[eq, eqinfo] : xrefs)
{ {
computeRevXref(xref_param, eqinfo.param, i); computeRevXref(xref_param, eqinfo.param, i);
computeRevXref(xref_endo, eqinfo.endo, i); computeRevXref(xref_endo, eqinfo.endo, i);
...@@ -2224,7 +2541,8 @@ DynamicModel::computeXrefs() ...@@ -2224,7 +2541,8 @@ DynamicModel::computeXrefs()
} }
void void
DynamicModel::computeRevXref(map<pair<int, int>, set<int>> &xrefset, const set<pair<int, int>> &eiref, int eqn) DynamicModel::computeRevXref(map<pair<int, int>, set<int>>& xrefset,
const set<pair<int, int>>& eiref, int eqn)
{ {
for (const auto& it : eiref) for (const auto& it : eiref)
{ {
...@@ -2243,8 +2561,7 @@ DynamicModel::writeXrefs(ostream &output) const ...@@ -2243,8 +2561,7 @@ DynamicModel::writeXrefs(ostream &output) const
<< "M_.xref1.endo = cell(1, M_.eq_nbr);" << endl << "M_.xref1.endo = cell(1, M_.eq_nbr);" << endl
<< "M_.xref1.exo = cell(1, M_.eq_nbr);" << endl << "M_.xref1.exo = cell(1, M_.eq_nbr);" << endl
<< "M_.xref1.exo_det = cell(1, M_.eq_nbr);" << endl; << "M_.xref1.exo_det = cell(1, M_.eq_nbr);" << endl;
for (int i{1}; for (int i {1}; const auto& [eq, eqinfo] : xrefs)
const auto &[eq, eqinfo] : xrefs)
{ {
output << "M_.xref1.param{" << i << "} = [ "; output << "M_.xref1.param{" << i << "} = [ ";
for (const auto& [id, lag] : eqinfo.param) for (const auto& [id, lag] : eqinfo.param)
...@@ -2253,17 +2570,20 @@ DynamicModel::writeXrefs(ostream &output) const ...@@ -2253,17 +2570,20 @@ DynamicModel::writeXrefs(ostream &output) const
output << "M_.xref1.endo{" << i << "} = [ "; output << "M_.xref1.endo{" << i << "} = [ ";
for (const auto& [id, lag] : eqinfo.endo) for (const auto& [id, lag] : eqinfo.endo)
output << "struct('id', " << symbol_table.getTypeSpecificID(id) + 1 << ", 'shift', " << lag << ");"; output << "struct('id', " << symbol_table.getTypeSpecificID(id) + 1 << ", 'shift', " << lag
<< ");";
output << "];" << endl; output << "];" << endl;
output << "M_.xref1.exo{" << i << "} = [ "; output << "M_.xref1.exo{" << i << "} = [ ";
for (const auto& [id, lag] : eqinfo.exo) for (const auto& [id, lag] : eqinfo.exo)
output << "struct('id', " << symbol_table.getTypeSpecificID(id) + 1 << ", 'shift', " << lag << ");"; output << "struct('id', " << symbol_table.getTypeSpecificID(id) + 1 << ", 'shift', " << lag
<< ");";
output << "];" << endl; output << "];" << endl;
output << "M_.xref1.exo_det{" << i << "} = [ "; output << "M_.xref1.exo_det{" << i << "} = [ ";
for (const auto& [id, lag] : eqinfo.exo_det) for (const auto& [id, lag] : eqinfo.exo_det)
output << "struct('id', " << symbol_table.getTypeSpecificID(id) + 1 << ", 'shift', " << lag << ");"; output << "struct('id', " << symbol_table.getTypeSpecificID(id) + 1 << ", 'shift', " << lag
<< ");";
output << "];" << endl; output << "];" << endl;
i++; i++;
...@@ -2280,10 +2600,10 @@ DynamicModel::writeXrefs(ostream &output) const ...@@ -2280,10 +2600,10 @@ DynamicModel::writeXrefs(ostream &output) const
} }
void void
DynamicModel::writeRevXrefs(ostream &output, const map<pair<int, int>, set<int>> &xrefmap, const string &type) const DynamicModel::writeRevXrefs(ostream& output, const map<pair<int, int>, set<int>>& xrefmap,
const string& type) const
{ {
for (int last_tsid{-1}; for (int last_tsid {-1}; const auto& [key, eqs] : xrefmap)
const auto &[key, eqs] : xrefmap)
{ {
auto& [id, lag] = key; auto& [id, lag] = key;
int tsid = symbol_table.getTypeSpecificID(id) + 1; int tsid = symbol_table.getTypeSpecificID(id) + 1;
...@@ -2302,7 +2622,6 @@ DynamicModel::writeRevXrefs(ostream &output, const map<pair<int, int>, set<int>> ...@@ -2302,7 +2622,6 @@ DynamicModel::writeRevXrefs(ostream &output, const map<pair<int, int>, set<int>>
} }
} }
map<tuple<int, int, int>, DynamicModel::BlockDerivativeType> map<tuple<int, int, int>, DynamicModel::BlockDerivativeType>
DynamicModel::determineBlockDerivativesType(int blk) DynamicModel::determineBlockDerivativesType(int blk)
{ {
...@@ -2310,16 +2629,14 @@ DynamicModel::determineBlockDerivativesType(int blk) ...@@ -2310,16 +2629,14 @@ DynamicModel::determineBlockDerivativesType(int blk)
int size = blocks[blk].size; int size = blocks[blk].size;
int nb_recursive = blocks[blk].getRecursiveSize(); int nb_recursive = blocks[blk].getRecursiveSize();
for (int lag {time_recursive_block_decomposition ? 0 : -blocks[blk].max_endo_lag}; for (int lag {time_recursive_block_decomposition ? 0 : -blocks[blk].max_endo_lag};
lag <= (time_recursive_block_decomposition ? 0 : blocks[blk].max_endo_lead); lag <= (time_recursive_block_decomposition ? 0 : blocks[blk].max_endo_lead); lag++)
lag++)
for (int eq = 0; eq < size; eq++) for (int eq = 0; eq < size; eq++)
{ {
set<pair<int, int>> endos_and_lags; set<pair<int, int>> endos_and_lags;
int eq_orig = getBlockEquationID(blk, eq); int eq_orig = getBlockEquationID(blk, eq);
equations[eq_orig]->collectEndogenous(endos_and_lags); equations[eq_orig]->collectEndogenous(endos_and_lags);
for (int var = 0; var < size; var++) for (int var = 0; var < size; var++)
if (int var_orig = getBlockVariableID(blk, var); if (int var_orig = getBlockVariableID(blk, var); endos_and_lags.contains({var_orig, lag}))
endos_and_lags.contains({ var_orig, lag }))
{ {
if (getBlockEquationType(blk, eq) == EquationType::evaluateRenormalized if (getBlockEquationType(blk, eq) == EquationType::evaluateRenormalized
&& eq < nb_recursive) && eq < nb_recursive)
...@@ -2360,7 +2677,8 @@ DynamicModel::computeChainRuleJacobian() ...@@ -2360,7 +2677,8 @@ DynamicModel::computeChainRuleJacobian()
map<int, BinaryOpNode*> recursive_vars; map<int, BinaryOpNode*> recursive_vars;
for (int i = 0; i < nb_recursives; i++) for (int i = 0; i < nb_recursives; i++)
{ {
int deriv_id = getDerivID(symbol_table.getID(SymbolType::endogenous, getBlockVariableID(blk, i)), 0); int deriv_id = getDerivID(
symbol_table.getID(SymbolType::endogenous, getBlockVariableID(blk, i)), 0);
if (getBlockEquationType(blk, i) == EquationType::evaluateRenormalized) if (getBlockEquationType(blk, i) == EquationType::evaluateRenormalized)
recursive_vars[deriv_id] = getBlockEquationRenormalizedExpr(blk, i); recursive_vars[deriv_id] = getBlockEquationRenormalizedExpr(blk, i);
else else
...@@ -2379,17 +2697,20 @@ DynamicModel::computeChainRuleJacobian() ...@@ -2379,17 +2697,20 @@ DynamicModel::computeChainRuleJacobian()
switch (derivType) switch (derivType)
{ {
case BlockDerivativeType::standard: case BlockDerivativeType::standard:
if (auto it = derivatives[1].find({ eq_orig, deriv_id }); if (auto it = derivatives[1].find({eq_orig, deriv_id}); it != derivatives[1].end())
it != derivatives[1].end())
d = it->second; d = it->second;
else else
d = Zero; d = Zero;
break; break;
case BlockDerivativeType::chainRule: case BlockDerivativeType::chainRule:
d = equations[eq_orig]->getChainRuleDerivative(deriv_id, recursive_vars, non_null_chain_rule_derivatives, chain_rule_deriv_cache); d = equations[eq_orig]->getChainRuleDerivative(deriv_id, recursive_vars,
non_null_chain_rule_derivatives,
chain_rule_deriv_cache);
break; break;
case BlockDerivativeType::normalizedChainRule: case BlockDerivativeType::normalizedChainRule:
d = equation_type_and_normalized_equation[eq_orig].second->getChainRuleDerivative(deriv_id, recursive_vars, non_null_chain_rule_derivatives, chain_rule_deriv_cache); d = equation_type_and_normalized_equation[eq_orig].second->getChainRuleDerivative(
deriv_id, recursive_vars, non_null_chain_rule_derivatives,
chain_rule_deriv_cache);
break; break;
} }
...@@ -2410,9 +2731,13 @@ DynamicModel::computeChainRuleJacobian() ...@@ -2410,9 +2731,13 @@ DynamicModel::computeChainRuleJacobian()
auto& [eq, var, lag] {indices}; auto& [eq, var, lag] {indices};
assert(lag >= -1 && lag <= 1 && eq >= nb_recursives); assert(lag >= -1 && lag <= 1 && eq >= nb_recursives);
if (var >= nb_recursives && !(one_boundary && lag != 0)) if (var >= nb_recursives && !(one_boundary && lag != 0))
blocks_jacobian_sparse_column_major_order[blk].try_emplace({eq-nb_recursives, var-nb_recursives+static_cast<int>(!one_boundary)*(lag+1)*mfs_size}, d1); blocks_jacobian_sparse_column_major_order[blk].try_emplace(
{eq - nb_recursives,
var - nb_recursives + static_cast<int>(!one_boundary) * (lag + 1) * mfs_size},
d1);
} }
blocks_jacobian_sparse_colptr[blk] = computeCSCColPtr(blocks_jacobian_sparse_column_major_order[blk], (one_boundary ? 1 : 3)*mfs_size); blocks_jacobian_sparse_colptr[blk] = computeCSCColPtr(
blocks_jacobian_sparse_column_major_order[blk], (one_boundary ? 1 : 3) * mfs_size);
} }
} }
} }
...@@ -2430,21 +2755,20 @@ DynamicModel::computeBlockDynJacobianCols() ...@@ -2430,21 +2755,20 @@ DynamicModel::computeBlockDynJacobianCols()
int block_eq {eq2block[eq_orig]}; int block_eq {eq2block[eq_orig]};
int var {getTypeSpecificIDByDerivID(deriv_id)}; int var {getTypeSpecificIDByDerivID(deriv_id)};
int lag {getLagByDerivID(deriv_id)}; int lag {getLagByDerivID(deriv_id)};
if (getTypeByDerivID(deriv_id) == SymbolType::endogenous if (getTypeByDerivID(deriv_id) == SymbolType::endogenous && block_eq == endo2block[var])
&& block_eq == endo2block[var])
dynamic_endo[block_eq].emplace(lag, getBlockInitialVariableID(block_eq, var)); dynamic_endo[block_eq].emplace(lag, getBlockInitialVariableID(block_eq, var));
} }
// Compute Jacobian column indices // Compute Jacobian column indices
blocks_jacob_cols_endo.resize(nb_blocks); blocks_jacob_cols_endo.resize(nb_blocks);
for (size_t blk {0}; blk < nb_blocks; blk++) for (size_t blk {0}; blk < nb_blocks; blk++)
for (int index{0}; for (int index {0}; auto [lag, var] : dynamic_endo[blk])
auto [lag, var] : dynamic_endo[blk])
blocks_jacob_cols_endo[blk][{var, lag}] = index++; blocks_jacob_cols_endo[blk][{var, lag}] = index++;
} }
void void
DynamicModel::writeDynamicFile(const string &basename, bool use_dll, const string &mexext, const filesystem::path &matlabroot, bool julia) const DynamicModel::writeDynamicFile(const string& basename, bool use_dll, const string& mexext,
const filesystem::path& matlabroot, bool julia) const
{ {
filesystem::path model_dir {basename}; filesystem::path model_dir {basename};
model_dir /= "model"; model_dir /= "model";
...@@ -2497,10 +2821,13 @@ DynamicModel::writeDynamicFile(const string &basename, bool use_dll, const strin ...@@ -2497,10 +2821,13 @@ DynamicModel::writeDynamicFile(const string &basename, bool use_dll, const strin
writeSetAuxiliaryVariablesFile<true>(basename, julia); writeSetAuxiliaryVariablesFile<true>(basename, julia);
// Support for model debugging
if (!julia) if (!julia)
{
writeComplementarityConditionsFile<true>(basename);
// Support for model debugging
writeDebugModelMFiles<true>(basename); writeDebugModelMFiles<true>(basename);
} }
}
void void
DynamicModel::clearEquations() DynamicModel::clearEquations()
...@@ -2508,6 +2835,7 @@ DynamicModel::clearEquations() ...@@ -2508,6 +2835,7 @@ DynamicModel::clearEquations()
equations.clear(); equations.clear();
equations_lineno.clear(); equations_lineno.clear();
equation_tags.clear(); equation_tags.clear();
complementarity_conditions.clear();
} }
void void
...@@ -2515,14 +2843,26 @@ DynamicModel::replaceMyEquations(DynamicModel &dynamic_model) const ...@@ -2515,14 +2843,26 @@ DynamicModel::replaceMyEquations(DynamicModel &dynamic_model) const
{ {
dynamic_model.clearEquations(); dynamic_model.clearEquations();
auto clone_if_not_null = [&](expr_t e) { return e ? e->clone(dynamic_model) : nullptr; };
for (size_t i = 0; i < equations.size(); i++) for (size_t i = 0; i < equations.size(); i++)
dynamic_model.addEquation(equations[i]->clone(dynamic_model), equations_lineno[i]); {
optional<tuple<int, expr_t, expr_t>> cc_clone;
if (complementarity_conditions[i])
{
auto& [symb_id, lower_bound, upper_bound] = *complementarity_conditions[i];
cc_clone = {symb_id, clone_if_not_null(lower_bound), clone_if_not_null(upper_bound)};
}
dynamic_model.addEquation(equations[i]->clone(dynamic_model), equations_lineno[i],
move(cc_clone));
}
dynamic_model.equation_tags = equation_tags; dynamic_model.equation_tags = equation_tags;
} }
int int
DynamicModel::computeRamseyPolicyFOCs(const StaticModel &static_model) DynamicModel::computeRamseyPolicyFOCs(const StaticModel& planner_objective,
map<int, pair<expr_t, expr_t>> cloned_ramsey_constraints)
{ {
cout << "Ramsey Problem: added " << equations.size() << " multipliers." << endl; cout << "Ramsey Problem: added " << equations.size() << " multipliers." << endl;
...@@ -2536,8 +2876,8 @@ DynamicModel::computeRamseyPolicyFOCs(const StaticModel &static_model) ...@@ -2536,8 +2876,8 @@ DynamicModel::computeRamseyPolicyFOCs(const StaticModel &static_model)
} }
// Add Planner Objective to equations so that it appears in Lagrangian // Add Planner Objective to equations so that it appears in Lagrangian
assert(static_model.equations.size() == 1); assert(planner_objective.equations.size() == 1);
addEquation(static_model.equations[0]->clone(*this), nullopt); addEquation(planner_objective.equations[0]->clone(*this), nullopt);
// Get max endo lead and max endo lag // Get max endo lead and max endo lag
set<pair<int, int>> dynvars; set<pair<int, int>> dynvars;
...@@ -2573,13 +2913,16 @@ DynamicModel::computeRamseyPolicyFOCs(const StaticModel &static_model) ...@@ -2573,13 +2913,16 @@ DynamicModel::computeRamseyPolicyFOCs(const StaticModel &static_model)
else else
dfpower = AddMinus(Zero, AddNonNegativeConstant(lagstream.str())); dfpower = AddMinus(Zero, AddNonNegativeConstant(lagstream.str()));
lagrangian = AddPlus(AddTimes(AddPower(discount_factor_node, dfpower), lagrangian
equations[i]->getNonZeroPartofEquation()->decreaseLeadsLags(lag)), lagrangian); = AddPlus(AddTimes(AddPower(discount_factor_node, dfpower),
equations[i]->getNonZeroPartofEquation()->decreaseLeadsLags(lag)),
lagrangian);
} }
// Save line numbers and tags, see below // Save line numbers, tags and complementarity conditions, see below
auto old_equations_lineno = equations_lineno; auto old_equations_lineno = equations_lineno;
auto old_equation_tags = equation_tags; auto old_equation_tags = equation_tags;
auto old_complementarity_conditions = complementarity_conditions;
// Prepare derivation of the Lagrangian // Prepare derivation of the Lagrangian
clearEquations(); clearEquations();
...@@ -2596,24 +2939,37 @@ DynamicModel::computeRamseyPolicyFOCs(const StaticModel &static_model) ...@@ -2596,24 +2939,37 @@ DynamicModel::computeRamseyPolicyFOCs(const StaticModel &static_model)
vector<expr_t> neweqs; vector<expr_t> neweqs;
vector<optional<int>> neweqs_lineno; vector<optional<int>> neweqs_lineno;
map<int, map<string, string>> neweqs_tags; map<int, map<string, string>> neweqs_tags;
map<int, optional<tuple<int, expr_t, expr_t>>> new_complementarity_conditions;
int orig_endo_nbr {0}; int orig_endo_nbr {0};
for (auto& [symb_id_and_lag, deriv_id] : deriv_id_table) for (auto& [symb_id_and_lag, deriv_id] : deriv_id_table)
{ {
auto& [symb_id, lag] = symb_id_and_lag; auto& [symb_id, lag] = symb_id_and_lag;
if (symbol_table.getType(symb_id) == SymbolType::endogenous && lag == 0) if (symbol_table.getType(symb_id) == SymbolType::endogenous && lag == 0)
{ {
neweqs.push_back(AddEqual(equations[0]->getNonZeroPartofEquation()->getDerivative(deriv_id), Zero)); neweqs.push_back(
if (optional<int> i = symbol_table.getEquationNumberForMultiplier(symb_id); AddEqual(equations[0]->getNonZeroPartofEquation()->getDerivative(deriv_id), Zero));
i) if (optional<int> i = symbol_table.getEquationNumberForMultiplier(symb_id); i)
{ {
// This is a derivative w.r.t. a Lagrange multiplier // This is a derivative w.r.t. a Lagrange multiplier
neweqs_lineno.push_back(old_equations_lineno[*i]); neweqs_lineno.push_back(old_equations_lineno[*i]);
neweqs_tags[neweqs.size()-1] = old_equation_tags.getTagsByEqn(*i); neweqs_tags.emplace(neweqs.size() - 1, old_equation_tags.getTagsByEqn(*i));
new_complementarity_conditions.emplace(neweqs.size() - 1,
old_complementarity_conditions.at(*i));
} }
else else
{ {
orig_endo_nbr++; orig_endo_nbr++;
neweqs_lineno.push_back(nullopt); neweqs_lineno.emplace_back(nullopt);
if (string eqname {"Ramsey FOC w.r.t. "s + symbol_table.getName(symb_id)};
!equation_tags.exists("name", eqname))
neweqs_tags.emplace(neweqs.size() - 1, map<string, string> {{"name", eqname}});
if (cloned_ramsey_constraints.contains(symb_id))
{
auto& [lower_bound, upper_bound] = cloned_ramsey_constraints.at(symb_id);
new_complementarity_conditions.emplace(neweqs.size() - 1,
tuple {symb_id, lower_bound, upper_bound});
}
} }
} }
} }
...@@ -2621,7 +2977,7 @@ DynamicModel::computeRamseyPolicyFOCs(const StaticModel &static_model) ...@@ -2621,7 +2977,7 @@ DynamicModel::computeRamseyPolicyFOCs(const StaticModel &static_model)
// Overwrite equations with the Lagrangian derivatives // Overwrite equations with the Lagrangian derivatives
clearEquations(); clearEquations();
for (size_t i = 0; i < neweqs.size(); i++) for (size_t i = 0; i < neweqs.size(); i++)
addEquation(neweqs[i], neweqs_lineno[i], neweqs_tags[i]); addEquation(neweqs[i], neweqs_lineno[i], new_complementarity_conditions[i], neweqs_tags[i]);
return orig_endo_nbr; return orig_endo_nbr;
} }
...@@ -2653,14 +3009,15 @@ DynamicModel::expandEqTags() ...@@ -2653,14 +3009,15 @@ DynamicModel::expandEqTags()
if (!existing_tags.contains(eq)) if (!existing_tags.contains(eq))
{ {
if (auto lhs_expr = dynamic_cast<VariableNode*>(equations[eq]->arg1); if (auto lhs_expr = dynamic_cast<VariableNode*>(equations[eq]->arg1);
lhs_expr lhs_expr && !equation_tags.exists("name", lhs_expr->getName()))
&& !equation_tags.exists("name", symbol_table.getName(lhs_expr->symb_id))) equation_tags.add(eq, "name", lhs_expr->getName());
equation_tags.add(eq, "name", symbol_table.getName(lhs_expr->symb_id));
else if (!equation_tags.exists("name", to_string(eq + 1))) else if (!equation_tags.exists("name", to_string(eq + 1)))
equation_tags.add(eq, "name", to_string(eq + 1)); equation_tags.add(eq, "name", to_string(eq + 1));
else else
{ {
cerr << "Error creating default equation tag: cannot assign default tag to equation number " << eq+1 << " because it is already in use" << endl; cerr << "Error creating default equation tag: cannot assign default tag to equation "
"number "
<< eq + 1 << " because it is already in use" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -2675,9 +3032,7 @@ DynamicModel::findUnusedEndogenous() ...@@ -2675,9 +3032,7 @@ DynamicModel::findUnusedEndogenous()
for (auto& equation : static_only_equations) for (auto& equation : static_only_equations)
equation->collectVariables(SymbolType::endogenous, usedEndo); equation->collectVariables(SymbolType::endogenous, usedEndo);
set<int> allEndo = symbol_table.getEndogenous(); set<int> allEndo = symbol_table.getEndogenous();
set_difference(allEndo.begin(), allEndo.end(), ranges::set_difference(allEndo, usedEndo, inserter(unusedEndo, unusedEndo.begin()));
usedEndo.begin(), usedEndo.end(),
inserter(unusedEndo, unusedEndo.begin()));
return unusedEndo; return unusedEndo;
} }
...@@ -2691,12 +3046,8 @@ DynamicModel::findUnusedExogenous() ...@@ -2691,12 +3046,8 @@ DynamicModel::findUnusedExogenous()
equation->collectVariables(SymbolType::exogenous, usedExo); equation->collectVariables(SymbolType::exogenous, usedExo);
set<int> observedExo = symbol_table.getObservedExogenous(); set<int> observedExo = symbol_table.getObservedExogenous();
set<int> allExo = symbol_table.getExogenous(); set<int> allExo = symbol_table.getExogenous();
set_difference(allExo.begin(), allExo.end(), ranges::set_difference(allExo, observedExo, inserter(unobservedExo, unobservedExo.begin()));
observedExo.begin(), observedExo.end(), ranges::set_difference(unobservedExo, usedExo, inserter(unusedExo, unusedExo.begin()));
inserter(unobservedExo, unobservedExo.begin()));
set_difference(unobservedExo.begin(), unobservedExo.end(),
usedExo.begin(), usedExo.end(),
inserter(unusedExo, unusedExo.begin()));
return unusedExo; return unusedExo;
} }
...@@ -2711,8 +3062,8 @@ DynamicModel::setLeadsLagsOrig() ...@@ -2711,8 +3062,8 @@ DynamicModel::setLeadsLagsOrig()
equation->collectDynamicVariables(SymbolType::exogenous, dynvars); equation->collectDynamicVariables(SymbolType::exogenous, dynvars);
equation->collectDynamicVariables(SymbolType::exogenousDet, dynvars); equation->collectDynamicVariables(SymbolType::exogenousDet, dynvars);
max_lag_with_diffs_expanded_orig = max(equation->maxLagWithDiffsExpanded(), max_lag_with_diffs_expanded_orig
max_lag_with_diffs_expanded_orig); = max(equation->maxLagWithDiffsExpanded(), max_lag_with_diffs_expanded_orig);
} }
for (const auto& [symb_id, lag] : dynvars) for (const auto& [symb_id, lag] : dynvars)
...@@ -2831,8 +3182,7 @@ DynamicModel::getTypeSpecificIDByDerivID(int deriv_id) const ...@@ -2831,8 +3182,7 @@ DynamicModel::getTypeSpecificIDByDerivID(int deriv_id) const
int int
DynamicModel::getDerivID(int symb_id, int lag) const noexcept(false) DynamicModel::getDerivID(int symb_id, int lag) const noexcept(false)
{ {
if (auto it = deriv_id_table.find({ symb_id, lag }); if (auto it = deriv_id_table.find({symb_id, lag}); it == deriv_id_table.end())
it == deriv_id_table.end())
throw UnknownDerivIDException(); throw UnknownDerivIDException();
else else
return it->second; return it->second;
...@@ -2849,7 +3199,8 @@ DynamicModel::addAllParamDerivId(set<int> &deriv_id_set) ...@@ -2849,7 +3199,8 @@ DynamicModel::addAllParamDerivId(set<int> &deriv_id_set)
void void
DynamicModel::computeDynJacobianCols() DynamicModel::computeDynJacobianCols()
{ {
// Sort the dynamic endogenous variables by lexicographic order over (lag, type_specific_symbol_id) // Sort the dynamic endogenous variables by lexicographic order over (lag,
// type_specific_symbol_id)
map<pair<int, int>, int> ordered_dyn_endo; map<pair<int, int>, int> ordered_dyn_endo;
for (const auto& [symb_lag, deriv_id] : deriv_id_table) for (const auto& [symb_lag, deriv_id] : deriv_id_table)
if (const auto& [symb_id, lag] = symb_lag; if (const auto& [symb_id, lag] = symb_lag;
...@@ -2857,8 +3208,7 @@ DynamicModel::computeDynJacobianCols() ...@@ -2857,8 +3208,7 @@ DynamicModel::computeDynJacobianCols()
ordered_dyn_endo[{lag, symbol_table.getTypeSpecificID(symb_id)}] = deriv_id; ordered_dyn_endo[{lag, symbol_table.getTypeSpecificID(symb_id)}] = deriv_id;
// Fill the dynamic jacobian columns for endogenous (legacy representation) // Fill the dynamic jacobian columns for endogenous (legacy representation)
for (int sorted_id{0}; for (int sorted_id {0}; const auto& [ignore, deriv_id] : ordered_dyn_endo)
const auto &[ignore, deriv_id] : ordered_dyn_endo)
dyn_jacobian_cols_table[deriv_id] = sorted_id++; dyn_jacobian_cols_table[deriv_id] = sorted_id++;
/* Fill the dynamic columns for exogenous and exogenous deterministic (legacy /* Fill the dynamic columns for exogenous and exogenous deterministic (legacy
...@@ -2867,8 +3217,7 @@ DynamicModel::computeDynJacobianCols() ...@@ -2867,8 +3217,7 @@ DynamicModel::computeDynJacobianCols()
{ {
int symb_id {symb_lag.first}; int symb_id {symb_lag.first};
int tsid {symbol_table.getTypeSpecificID(symb_id)}; // At this point, there is no trend_var int tsid {symbol_table.getTypeSpecificID(symb_id)}; // At this point, there is no trend_var
if (SymbolType type{symbol_table.getType(symb_id)}; if (SymbolType type {symbol_table.getType(symb_id)}; type == SymbolType::exogenous)
type == SymbolType::exogenous)
dyn_jacobian_cols_table[deriv_id] = ordered_dyn_endo.size() + tsid; dyn_jacobian_cols_table[deriv_id] = ordered_dyn_endo.size() + tsid;
else if (type == SymbolType::exogenousDet) else if (type == SymbolType::exogenousDet)
dyn_jacobian_cols_table[deriv_id] = ordered_dyn_endo.size() + symbol_table.exo_nbr() + tsid; dyn_jacobian_cols_table[deriv_id] = ordered_dyn_endo.size() + symbol_table.exo_nbr() + tsid;
...@@ -2876,7 +3225,8 @@ DynamicModel::computeDynJacobianCols() ...@@ -2876,7 +3225,8 @@ DynamicModel::computeDynJacobianCols()
/* NB: the following could differ from dyn_jacobian_cols_table.size() if /* NB: the following could differ from dyn_jacobian_cols_table.size() if
there are unused exogenous (and “nostrict” option is given) */ there are unused exogenous (and “nostrict” option is given) */
dyn_jacobian_ncols = ordered_dyn_endo.size() + symbol_table.exo_nbr() + symbol_table.exo_det_nbr(); dyn_jacobian_ncols
= ordered_dyn_endo.size() + symbol_table.exo_nbr() + symbol_table.exo_det_nbr();
} }
void void
...@@ -2888,8 +3238,7 @@ DynamicModel::testTrendDerivativesEqualToZero(const eval_context_t &eval_context ...@@ -2888,8 +3238,7 @@ DynamicModel::testTrendDerivativesEqualToZero(const eval_context_t &eval_context
|| symbol_table.getType(symb_id1) == SymbolType::logTrend) || symbol_table.getType(symb_id1) == SymbolType::logTrend)
for (int eq = 0; eq < static_cast<int>(equations.size()); eq++) for (int eq = 0; eq < static_cast<int>(equations.size()); eq++)
{ {
expr_t homogeneq = AddMinus(equations[eq]->arg1, expr_t homogeneq = AddMinus(equations[eq]->arg1, equations[eq]->arg2);
equations[eq]->arg2);
// Do not run the test if the term inside the log is zero // Do not run the test if the term inside the log is zero
if (fabs(homogeneq->eval(eval_context)) > zero_band) if (fabs(homogeneq->eval(eval_context)) > zero_band)
...@@ -2900,16 +3249,22 @@ DynamicModel::testTrendDerivativesEqualToZero(const eval_context_t &eval_context ...@@ -2900,16 +3249,22 @@ DynamicModel::testTrendDerivativesEqualToZero(const eval_context_t &eval_context
if (auto& [symb_id2, lag2] = symb_lag2; if (auto& [symb_id2, lag2] = symb_lag2;
symbol_table.getType(symb_id2) == SymbolType::endogenous) symbol_table.getType(symb_id2) == SymbolType::endogenous)
{ {
double nearZero = testeq->getDerivative(deriv_id2)->eval(eval_context); // eval d F / d Trend d Endog double nearZero = testeq->getDerivative(deriv_id2)->eval(
eval_context); // eval d F / d Trend d Endog
if (fabs(nearZero) > balanced_growth_test_tol) if (fabs(nearZero) > balanced_growth_test_tol)
{ {
cerr << "ERROR: trends not compatible with balanced growth path; the second-order cross partial of equation " << eq + 1; cerr << "ERROR: trends not compatible with balanced growth path; the "
"second-order cross partial of equation "
<< eq + 1;
if (equations_lineno[eq]) if (equations_lineno[eq])
cerr << " (line " << *equations_lineno[eq] << ") "; cerr << " (line " << *equations_lineno[eq] << ") ";
cerr << "w.r.t. trend variable " cerr << "w.r.t. trend variable " << symbol_table.getName(symb_id1)
<< symbol_table.getName(symb_id1) << " and endogenous variable " << " and endogenous variable " << symbol_table.getName(symb_id2)
<< symbol_table.getName(symb_id2) << " is not null (abs. value = " << " is not null (abs. value = " << fabs(nearZero)
<< fabs(nearZero) << "). If you are confident that your trends are correctly specified, you can raise the value of option 'balanced_growth_test_tol' in the 'model' block." << endl; << "). If you are confident that your trends are correctly specified, "
"you can raise the value of option 'balanced_growth_test_tol' in "
"the 'model' block."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -2920,13 +3275,15 @@ DynamicModel::testTrendDerivativesEqualToZero(const eval_context_t &eval_context ...@@ -2920,13 +3275,15 @@ DynamicModel::testTrendDerivativesEqualToZero(const eval_context_t &eval_context
void void
DynamicModel::writeLatexFile(const string& basename, bool write_equation_tags) const DynamicModel::writeLatexFile(const string& basename, bool write_equation_tags) const
{ {
writeLatexModelFile(basename, "dynamic", ExprNodeOutputType::latexDynamicModel, write_equation_tags); writeLatexModelFile(basename, "dynamic", ExprNodeOutputType::latexDynamicModel,
write_equation_tags);
} }
void void
DynamicModel::writeLatexOriginalFile(const string& basename, bool write_equation_tags) const DynamicModel::writeLatexOriginalFile(const string& basename, bool write_equation_tags) const
{ {
writeLatexModelFile(basename, "original", ExprNodeOutputType::latexDynamicModel, write_equation_tags); writeLatexModelFile(basename, "original", ExprNodeOutputType::latexDynamicModel,
write_equation_tags);
} }
void void
...@@ -2954,7 +3311,8 @@ DynamicModel::substituteExoLag(bool deterministic_model) ...@@ -2954,7 +3311,8 @@ DynamicModel::substituteExoLag(bool deterministic_model)
} }
void void
DynamicModel::substituteLeadLagInternal(AuxVarType type, bool deterministic_model, const vector<string> &subset) DynamicModel::substituteLeadLagInternal(AuxVarType type, bool deterministic_model,
const vector<string>& subset)
{ {
ExprNode::subst_table_t subst_table; ExprNode::subst_table_t subst_table;
vector<BinaryOpNode*> neweqs; vector<BinaryOpNode*> neweqs;
...@@ -2999,7 +3357,8 @@ DynamicModel::substituteLeadLagInternal(AuxVarType type, bool deterministic_mode ...@@ -2999,7 +3357,8 @@ DynamicModel::substituteLeadLagInternal(AuxVarType type, bool deterministic_mode
switch (type) switch (type)
{ {
case AuxVarType::endoLead: case AuxVarType::endoLead:
subst = equation->substituteEndoLeadGreaterThanTwo(subst_table, neweqs, deterministic_model); subst = equation->substituteEndoLeadGreaterThanTwo(subst_table, neweqs,
deterministic_model);
break; break;
case AuxVarType::endoLag: case AuxVarType::endoLag:
subst = equation->substituteEndoLagGreaterThanTwo(subst_table, neweqs); subst = equation->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
...@@ -3115,8 +3474,7 @@ set<int> ...@@ -3115,8 +3474,7 @@ set<int>
DynamicModel::findPacExpectationEquationNumbers() const DynamicModel::findPacExpectationEquationNumbers() const
{ {
set<int> eqnumbers; set<int> eqnumbers;
for (int i{0}; for (int i {0}; auto& equation : equations)
auto &equation : equations)
{ {
if (equation->containsPacExpectation()) if (equation->containsPacExpectation())
eqnumbers.insert(i); eqnumbers.insert(i);
...@@ -3126,15 +3484,17 @@ DynamicModel::findPacExpectationEquationNumbers() const ...@@ -3126,15 +3484,17 @@ DynamicModel::findPacExpectationEquationNumbers() const
} }
pair<lag_equivalence_table_t, ExprNode::subst_table_t> pair<lag_equivalence_table_t, ExprNode::subst_table_t>
DynamicModel::substituteUnaryOps(VarExpectationModelTable &var_expectation_model_table, PacModelTable &pac_model_table) DynamicModel::substituteUnaryOps(VarExpectationModelTable& var_expectation_model_table,
PacModelTable& pac_model_table)
{ {
vector<int> eqnumbers(equations.size()); auto v = views::iota(0, static_cast<int>(equations.size()));
iota(eqnumbers.begin(), eqnumbers.end(), 0); return substituteUnaryOps({v.begin(), v.end()}, var_expectation_model_table, pac_model_table);
return substituteUnaryOps({ eqnumbers.begin(), eqnumbers.end() }, var_expectation_model_table, pac_model_table);
} }
pair<lag_equivalence_table_t, ExprNode::subst_table_t> pair<lag_equivalence_table_t, ExprNode::subst_table_t>
DynamicModel::substituteUnaryOps(const set<int> &eqnumbers, VarExpectationModelTable &var_expectation_model_table, PacModelTable &pac_model_table) DynamicModel::substituteUnaryOps(const set<int>& eqnumbers,
VarExpectationModelTable& var_expectation_model_table,
PacModelTable& pac_model_table)
{ {
lag_equivalence_table_t nodes; lag_equivalence_table_t nodes;
ExprNode::subst_table_t subst_table; ExprNode::subst_table_t subst_table;
...@@ -3153,13 +3513,14 @@ DynamicModel::substituteUnaryOps(const set<int> &eqnumbers, VarExpectationModelT ...@@ -3153,13 +3513,14 @@ DynamicModel::substituteUnaryOps(const set<int> &eqnumbers, VarExpectationModelT
// Substitute in model local variables // Substitute in model local variables
vector<BinaryOpNode*> neweqs; vector<BinaryOpNode*> neweqs;
for (int mlv : used_local_vars) for (int mlv : used_local_vars)
local_variables_table[mlv] = local_variables_table[mlv]->substituteUnaryOpNodes(nodes, subst_table, neweqs); local_variables_table[mlv]
= local_variables_table[mlv]->substituteUnaryOpNodes(nodes, subst_table, neweqs);
// Substitute in equations // Substitute in equations
for (int eq : eqnumbers) for (int eq : eqnumbers)
{ {
auto substeq = dynamic_cast<BinaryOpNode *>(equations[eq]-> auto substeq = dynamic_cast<BinaryOpNode*>(
substituteUnaryOpNodes(nodes, subst_table, neweqs)); equations[eq]->substituteUnaryOpNodes(nodes, subst_table, neweqs));
assert(substeq); assert(substeq);
equations[eq] = substeq; equations[eq] = substeq;
} }
...@@ -3177,13 +3538,15 @@ DynamicModel::substituteUnaryOps(const set<int> &eqnumbers, VarExpectationModelT ...@@ -3177,13 +3538,15 @@ DynamicModel::substituteUnaryOps(const set<int> &eqnumbers, VarExpectationModelT
} }
if (subst_table.size() > 0) if (subst_table.size() > 0)
cout << "Substitution of Unary Ops: added " << neweqs.size() << " auxiliary variables and equations." << endl; cout << "Substitution of Unary Ops: added " << neweqs.size()
<< " auxiliary variables and equations." << endl;
return {nodes, subst_table}; return {nodes, subst_table};
} }
pair<lag_equivalence_table_t, ExprNode::subst_table_t> pair<lag_equivalence_table_t, ExprNode::subst_table_t>
DynamicModel::substituteDiff(VarExpectationModelTable &var_expectation_model_table, PacModelTable &pac_model_table) DynamicModel::substituteDiff(VarExpectationModelTable& var_expectation_model_table,
PacModelTable& pac_model_table)
{ {
/* Note: at this point, we know that there is no diff operator with a lead, /* Note: at this point, we know that there is no diff operator with a lead,
because they have been expanded by DataTree::AddDiff(). because they have been expanded by DataTree::AddDiff().
...@@ -3215,8 +3578,8 @@ DynamicModel::substituteDiff(VarExpectationModelTable &var_expectation_model_tab ...@@ -3215,8 +3578,8 @@ DynamicModel::substituteDiff(VarExpectationModelTable &var_expectation_model_tab
// Substitute in equations // Substitute in equations
for (auto& equation : equations) for (auto& equation : equations)
{ {
auto substeq = dynamic_cast<BinaryOpNode *>(equation-> auto substeq = dynamic_cast<BinaryOpNode*>(
substituteDiff(diff_nodes, diff_subst_table, neweqs)); equation->substituteDiff(diff_nodes, diff_subst_table, neweqs));
assert(substeq); assert(substeq);
equation = substeq; equation = substeq;
} }
...@@ -3232,7 +3595,8 @@ DynamicModel::substituteDiff(VarExpectationModelTable &var_expectation_model_tab ...@@ -3232,7 +3595,8 @@ DynamicModel::substituteDiff(VarExpectationModelTable &var_expectation_model_tab
} }
if (diff_subst_table.size() > 0) if (diff_subst_table.size() > 0)
cout << "Substitution of Diff operator: added " << neweqs.size() << " auxiliary variables and equations." << endl; cout << "Substitution of Diff operator: added " << neweqs.size()
<< " auxiliary variables and equations." << endl;
return {diff_nodes, diff_subst_table}; return {diff_nodes, diff_subst_table};
} }
...@@ -3250,7 +3614,8 @@ DynamicModel::substituteExpectation(bool partial_information_model) ...@@ -3250,7 +3614,8 @@ DynamicModel::substituteExpectation(bool partial_information_model)
// Substitute in equations // Substitute in equations
for (auto& equation : equations) for (auto& equation : equations)
{ {
equation = dynamic_cast<BinaryOpNode *>(equation->substituteExpectation(subst_table, neweqs, partial_information_model)); equation = dynamic_cast<BinaryOpNode*>(
equation->substituteExpectation(subst_table, neweqs, partial_information_model));
assert(equation); assert(equation);
} }
...@@ -3267,9 +3632,11 @@ DynamicModel::substituteExpectation(bool partial_information_model) ...@@ -3267,9 +3632,11 @@ DynamicModel::substituteExpectation(bool partial_information_model)
if (subst_table.size() > 0) if (subst_table.size() > 0)
{ {
if (partial_information_model) if (partial_information_model)
cout << "Substitution of Expectation operator: added " << subst_table.size() << " auxiliary variables and " << neweqs.size() << " auxiliary equations." << endl; cout << "Substitution of Expectation operator: added " << subst_table.size()
<< " auxiliary variables and " << neweqs.size() << " auxiliary equations." << endl;
else else
cout << "Substitution of Expectation operator: added " << neweqs.size() << " auxiliary variables and equations." << endl; cout << "Substitution of Expectation operator: added " << neweqs.size()
<< " auxiliary variables and equations." << endl;
} }
} }
...@@ -3300,10 +3667,12 @@ DynamicModel::substituteLogTransform() ...@@ -3300,10 +3667,12 @@ DynamicModel::substituteLogTransform()
definition = definition->substituteLogTransform(symb_id, aux_symb_id); definition = definition->substituteLogTransform(symb_id, aux_symb_id);
for (auto& equation : equations) for (auto& equation : equations)
equation = dynamic_cast<BinaryOpNode *>(equation->substituteLogTransform(symb_id, aux_symb_id)); equation
= dynamic_cast<BinaryOpNode*>(equation->substituteLogTransform(symb_id, aux_symb_id));
for (auto& equation : static_only_equations) for (auto& equation : static_only_equations)
equation = dynamic_cast<BinaryOpNode *>(equation->substituteLogTransform(symb_id, aux_symb_id)); equation
= dynamic_cast<BinaryOpNode*>(equation->substituteLogTransform(symb_id, aux_symb_id));
/* /*
We add the following new equations: We add the following new equations:
...@@ -3319,8 +3688,37 @@ DynamicModel::substituteLogTransform() ...@@ -3319,8 +3688,37 @@ DynamicModel::substituteLogTransform()
block of type “evaluate”, or maybe even the epilogue) block of type “evaluate”, or maybe even the epilogue)
*/ */
addAuxEquation(AddEqual(AddVariable(aux_symb_id), aux_def)); addAuxEquation(AddEqual(AddVariable(aux_symb_id), aux_def));
addEquation(AddEqual(AddVariable(symb_id), AddExp(AddVariable(aux_symb_id))), addEquation(AddEqual(AddVariable(symb_id), AddExp(AddVariable(aux_symb_id))), nullopt, {});
nullopt, {}); }
}
void
DynamicModel::substituteAggregationOperators()
{
ExprNode::subst_table_t subst_table;
vector<BinaryOpNode*> neweqs;
for (auto& [symb_id, expr] : local_variables_table)
expr = expr->substituteAggregationOperators(subst_table, neweqs);
for (auto& equation : equations)
{
equation = dynamic_cast<BinaryOpNode*>(
equation->substituteAggregationOperators(subst_table, neweqs));
assert(equation);
}
for (auto& equation : static_only_equations)
{
equation = dynamic_cast<BinaryOpNode*>(
equation->substituteAggregationOperators(subst_table, neweqs));
assert(equation);
}
for (auto neweq : neweqs)
{
addEquation(neweq, nullopt);
addAuxEquation(neweq);
} }
} }
...@@ -3334,12 +3732,11 @@ DynamicModel::checkNoWithLogTransform(const set<int> &eqnumbers) ...@@ -3334,12 +3732,11 @@ DynamicModel::checkNoWithLogTransform(const set<int> &eqnumbers)
const set<int>& with_log_transform = symbol_table.getVariablesWithLogTransform(); const set<int>& with_log_transform = symbol_table.getVariablesWithLogTransform();
vector<int> intersect; vector<int> intersect;
set_intersection(endos.begin(), endos.end(), ranges::set_intersection(endos, with_log_transform, back_inserter(intersect));
with_log_transform.begin(), with_log_transform.end(),
back_inserter(intersect));
if (!intersect.empty()) if (!intersect.empty())
{ {
cerr << "ERROR: the following variables are declared with var(log) and therefore cannot appear in a VAR/TCM/PAC equation: "; cerr << "ERROR: the following variables are declared with var(log) and therefore cannot "
"appear in a VAR/TCM/PAC equation: ";
for (int symb_id : intersect) for (int symb_id : intersect)
cerr << symbol_table.getName(symb_id) << " "; cerr << symbol_table.getName(symb_id) << " ";
cerr << endl; cerr << endl;
...@@ -3351,17 +3748,18 @@ void ...@@ -3351,17 +3748,18 @@ void
DynamicModel::detrendEquations() DynamicModel::detrendEquations()
{ {
// We go backwards in the list of trend_vars, to deal correctly with I(2) processes // We go backwards in the list of trend_vars, to deal correctly with I(2) processes
for (auto it = nonstationary_symbols_map.crbegin(); for (const auto& [symb_id, deflator] : std::ranges::reverse_view(nonstationary_symbols_map))
it != nonstationary_symbols_map.crend(); ++it)
{ {
for (auto& equation : equations) for (auto& equation : equations)
{ {
equation = dynamic_cast<BinaryOpNode *>(equation->detrend(it->first, it->second.first, it->second.second)); equation = dynamic_cast<BinaryOpNode*>(
equation->detrend(symb_id, deflator.first, deflator.second));
assert(equation); assert(equation);
} }
for (auto& equation : static_only_equations) for (auto& equation : static_only_equations)
{ {
equation = dynamic_cast<BinaryOpNode *>(equation->detrend(it->first, it->second.first, it->second.second)); equation = dynamic_cast<BinaryOpNode*>(
equation->detrend(symb_id, deflator.first, deflator.second));
assert(equation); assert(equation);
} }
} }
...@@ -3439,14 +3837,17 @@ DynamicModel::fillEvalContext(eval_context_t &eval_context) const ...@@ -3439,14 +3837,17 @@ DynamicModel::fillEvalContext(eval_context_t &eval_context) const
} }
void void
DynamicModel::addStaticOnlyEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags) DynamicModel::addStaticOnlyEquation(expr_t eq, const optional<int>& lineno,
optional<tuple<int, expr_t, expr_t>> complementarity_condition,
map<string, string> eq_tags)
{ {
auto beq = dynamic_cast<BinaryOpNode*>(eq); auto beq = dynamic_cast<BinaryOpNode*>(eq);
assert(beq && beq->op_code == BinaryOpcode::equal); assert(beq && beq->op_code == BinaryOpcode::equal);
static_only_equations_equation_tags.add(static_only_equations.size(), move(eq_tags)); static_only_equations_equation_tags.add(static_only_equations.size(), move(eq_tags));
static_only_equations.push_back(beq); static_only_equations.push_back(beq);
static_only_equations_lineno.push_back(move(lineno)); static_only_equations_lineno.push_back(lineno);
static_only_complementarity_conditions.push_back(move(complementarity_condition));
} }
size_t size_t
...@@ -3462,22 +3863,26 @@ DynamicModel::dynamicOnlyEquationsNbr() const ...@@ -3462,22 +3863,26 @@ DynamicModel::dynamicOnlyEquationsNbr() const
} }
void void
DynamicModel::addOccbinEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags, const vector<string> &regimes_bind, const vector<string> &regimes_relax) DynamicModel::addOccbinEquation(expr_t eq, const optional<int>& lineno, map<string, string> eq_tags,
const vector<string>& constraints_bind,
const vector<string>& constraints_relax)
{ {
auto beq = dynamic_cast<BinaryOpNode*>(eq); auto beq = dynamic_cast<BinaryOpNode*>(eq);
assert(beq && beq->op_code == BinaryOpcode::equal); assert(beq && beq->op_code == BinaryOpcode::equal);
occbin_regime_trackers[eq_tags.at("name")].addRegime(constraints_bind, constraints_relax);
// Construct the term to be added to the corresponding equation // Construct the term to be added to the corresponding equation
expr_t basic_term = AddMinus(beq->arg1, beq->arg2); expr_t basic_term = AddMinus(beq->arg1, beq->arg2);
expr_t term = basic_term; expr_t term = basic_term;
for (auto &regime : regimes_bind) for (auto& constraint : constraints_bind)
{ {
int param_id = symbol_table.getID(ParsingDriver::buildOccbinBindParamName(regime)); int param_id = symbol_table.getID(ParsingDriver::buildOccbinBindParamName(constraint));
term = AddTimes(term, AddVariable(param_id)); term = AddTimes(term, AddVariable(param_id));
} }
for (auto &regime : regimes_relax) for (auto& constraint : constraints_relax)
{ {
int param_id = symbol_table.getID(ParsingDriver::buildOccbinBindParamName(regime)); int param_id = symbol_table.getID(ParsingDriver::buildOccbinBindParamName(constraint));
term = AddTimes(term, AddMinus(One, AddVariable(param_id))); term = AddTimes(term, AddMinus(One, AddVariable(param_id)));
} }
...@@ -3496,27 +3901,29 @@ DynamicModel::addOccbinEquation(expr_t eq, optional<int> lineno, map<string, str ...@@ -3496,27 +3901,29 @@ DynamicModel::addOccbinEquation(expr_t eq, optional<int> lineno, map<string, str
{ {
auto eq_tags_dynamic = eq_tags; auto eq_tags_dynamic = eq_tags;
eq_tags_dynamic["dynamic"] = ""; eq_tags_dynamic["dynamic"] = "";
addEquation(AddEqual(term, Zero), lineno, eq_tags_dynamic); addEquation(AddEqual(term, Zero), lineno, nullopt, eq_tags_dynamic);
} }
// Create or update the static equation (corresponding to the pure relax regime) // Create or update the static equation (corresponding to the pure relax regime)
if (regimes_bind.empty()) if (constraints_bind.empty())
{ {
/* Similar remark as above. We could have entirely skipped this /* Similar remark as above. We could have entirely skipped this
equation updating, since normally there is only one such clause, equation updating, since normally there is only one such clause,
but the following adds a (somewhat bizarre) support for equation but the following adds a (somewhat bizarre) support for equation
snippets without “bind” nor “relax” */ snippets without “bind” nor “relax” */
optional<int> eqn_static { static_only_equations_equation_tags.getEqnByTag("name", eq_tags.at("name")) }; optional<int> eqn_static {
static_only_equations_equation_tags.getEqnByTag("name", eq_tags.at("name"))};
if (eqn_static) if (eqn_static)
{ {
BinaryOpNode* orig_eq {static_only_equations[*eqn_static]}; BinaryOpNode* orig_eq {static_only_equations[*eqn_static]};
static_only_equations[*eqn_static] = AddEqual(AddPlus(AddMinus(orig_eq->arg1, orig_eq->arg2), basic_term), Zero); static_only_equations[*eqn_static]
= AddEqual(AddPlus(AddMinus(orig_eq->arg1, orig_eq->arg2), basic_term), Zero);
// It’s unclear how to update lineno and tags, so don’t do it // It’s unclear how to update lineno and tags, so don’t do it
} }
else else
{ {
eq_tags["static"] = ""; eq_tags["static"] = "";
addStaticOnlyEquation(AddEqual(basic_term, Zero), lineno, move(eq_tags)); addStaticOnlyEquation(AddEqual(basic_term, Zero), lineno, nullopt, move(eq_tags));
} }
} }
} }
...@@ -3534,9 +3941,8 @@ DynamicModel::isChecksumMatching(const string &basename) const ...@@ -3534,9 +3941,8 @@ DynamicModel::isChecksumMatching(const string &basename) const
deriv_node_temp_terms_t tef_terms; deriv_node_temp_terms_t tef_terms;
temporary_terms_t temp_term_union; temporary_terms_t temp_term_union;
writeTemporaryTerms<buffer_type>(temporary_terms_derivatives[0], writeTemporaryTerms<buffer_type>(temporary_terms_derivatives[0], temp_term_union,
temp_term_union, temporary_terms_idxs, temporary_terms_idxs, buffer, tef_terms);
buffer, tef_terms);
writeModelEquations<buffer_type>(buffer, temp_term_union); writeModelEquations<buffer_type>(buffer, temp_term_union);
...@@ -3585,8 +3991,7 @@ DynamicModel::writeJsonOutput(ostream &output) const ...@@ -3585,8 +3991,7 @@ DynamicModel::writeJsonOutput(ostream &output) const
output << ", "; output << ", ";
writeJsonVariableMapping(output); writeJsonVariableMapping(output);
output << R"(, "dynamic_tmp_nbr": [)"; output << R"(, "dynamic_tmp_nbr": [)";
for (bool printed_something {false}; for (bool printed_something {false}; const auto& tts : temporary_terms_derivatives)
const auto &tts : temporary_terms_derivatives)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
...@@ -3623,16 +4028,13 @@ void ...@@ -3623,16 +4028,13 @@ void
DynamicModel::writeJsonVariableMapping(ostream& output) const DynamicModel::writeJsonVariableMapping(ostream& output) const
{ {
output << R"("variable_mapping":[)" << endl; output << R"("variable_mapping":[)" << endl;
for (bool printed_something{false}; for (bool printed_something {false}; const auto& [var, eqs] : variableMapping)
const auto &[var, eqs] : variableMapping)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
output << R"({"name": ")" << symbol_table.getName(var) << R"(", "equations":[)"; output << R"({"name": ")" << symbol_table.getName(var) << R"(", "equations":[)";
for (bool printed_something2{false}; for (bool printed_something2 {false}; int it2 : eqs)
int it2 : eqs) if (auto tmp = equation_tags.getTagValueByEqnAndKey(it2, "name"); tmp)
if (auto tmp = equation_tags.getTagValueByEqnAndKey(it2, "name");
tmp)
{ {
if (exchange(printed_something2, true)) if (exchange(printed_something2, true))
output << ", "; output << ", ";
...@@ -3644,18 +4046,16 @@ DynamicModel::writeJsonVariableMapping(ostream &output) const ...@@ -3644,18 +4046,16 @@ DynamicModel::writeJsonVariableMapping(ostream &output) const
} }
void void
DynamicModel::writeJsonXrefsHelper(ostream &output, const map<pair<int, int>, set<int>> &xrefmap) const DynamicModel::writeJsonXrefsHelper(ostream& output,
const map<pair<int, int>, set<int>>& xrefmap) const
{ {
for (bool printed_something{false}; for (bool printed_something {false}; const auto& [symb_lag, eqs] : xrefmap)
const auto &[symb_lag, eqs] : xrefmap)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
output << R"({"name": ")" << symbol_table.getName(symb_lag.first) << R"(")" output << R"({"name": ")" << symbol_table.getName(symb_lag.first) << R"(")"
<< R"(, "shift": )" << symb_lag.second << R"(, "shift": )" << symb_lag.second << R"(, "equations": [)";
<< R"(, "equations": [)"; for (bool printed_something2 {false}; int eq : eqs)
for (bool printed_something2{false};
int eq : eqs)
{ {
if (exchange(printed_something2, true)) if (exchange(printed_something2, true))
output << ", "; output << ", ";
...@@ -3697,19 +4097,13 @@ DynamicModel::writeJsonDynamicModelInfo(ostream &output) const ...@@ -3697,19 +4097,13 @@ DynamicModel::writeJsonDynamicModelInfo(ostream &output) const
output << R"("model_info": {)" output << R"("model_info": {)"
<< R"("lead_lag_incidence": [)"; << R"("lead_lag_incidence": [)";
// Loop on endogenous variables // Loop on endogenous variables
int nstatic = 0, int nstatic = 0, nfwrd = 0, npred = 0, nboth = 0;
nfwrd = 0,
npred = 0,
nboth = 0;
for (int endoID = 0; endoID < symbol_table.endo_nbr(); endoID++) for (int endoID = 0; endoID < symbol_table.endo_nbr(); endoID++)
{ {
if (endoID != 0) if (endoID != 0)
output << ","; output << ",";
output << "["; output << "[";
int sstatic = 1, int sstatic = 1, sfwrd = 0, spred = 0, sboth = 0;
sfwrd = 0,
spred = 0,
sboth = 0;
// Loop on periods // Loop on periods
for (int lag = -max_endo_lag; lag <= max_endo_lead; lag++) for (int lag = -max_endo_lag; lag <= max_endo_lead; lag++)
{ {
...@@ -3774,8 +4168,8 @@ DynamicModel::writeJsonDynamicModelInfo(ostream &output) const ...@@ -3774,8 +4168,8 @@ DynamicModel::writeJsonDynamicModelInfo(ostream &output) const
<< R"("orig_maximum_exo_det_lead": )" << max_exo_det_lead_orig << "," << endl << R"("orig_maximum_exo_det_lead": )" << max_exo_det_lead_orig << "," << endl
<< R"("orig_maximum_lag": )" << max_lag_orig << "," << endl << R"("orig_maximum_lag": )" << max_lag_orig << "," << endl
<< R"("orig_maximum_lead": )" << max_lead_orig << "," << endl << R"("orig_maximum_lead": )" << max_lead_orig << "," << endl
<< R"("orig_maximum_lag_with_diffs_expanded": )" << max_lag_with_diffs_expanded_orig << R"("orig_maximum_lag_with_diffs_expanded": )" << max_lag_with_diffs_expanded_orig << ","
<< "," <<endl << endl
<< R"("NNZDerivatives": [)"; << R"("NNZDerivatives": [)";
for (int i = 1; i < static_cast<int>(NNZDerivatives.size()); i++) for (int i = 1; i < static_cast<int>(NNZDerivatives.size()); i++)
{ {
...@@ -3783,8 +4177,7 @@ DynamicModel::writeJsonDynamicModelInfo(ostream &output) const ...@@ -3783,8 +4177,7 @@ DynamicModel::writeJsonDynamicModelInfo(ostream &output) const
if (i < static_cast<int>(NNZDerivatives.size()) - 1) if (i < static_cast<int>(NNZDerivatives.size()) - 1)
output << ", "; output << ", ";
} }
output << "]}" output << "]}" << endl;
<< endl;
} }
void void
...@@ -3808,22 +4201,16 @@ DynamicModel::writeJsonParamsDerivatives(ostream &output, bool writeDetails) con ...@@ -3808,22 +4201,16 @@ DynamicModel::writeJsonParamsDerivatives(ostream &output, bool writeDetails) con
if (!params_derivatives.size()) if (!params_derivatives.size())
return; return;
auto [mlv_output, tt_output, rp_output, gp_output, rpp_output, gpp_output, hp_output, g3p_output] auto [mlv_output, tt_output, rp_output, gp_output, rpp_output, gpp_output, hp_output,
{ writeJsonParamsDerivativesHelper<true>(writeDetails) }; g3p_output] {writeJsonParamsDerivativesHelper<true>(writeDetails)};
if (writeDetails) if (writeDetails)
output << R"("dynamic_model_params_derivative": {)"; output << R"("dynamic_model_params_derivative": {)";
else else
output << R"("dynamic_model_params_derivatives_simple": {)"; output << R"("dynamic_model_params_derivatives_simple": {)";
output << mlv_output.str() output << mlv_output.str() << ", " << tt_output.str() << ", " << rp_output.str() << ", "
<< ", " << tt_output.str() << gp_output.str() << ", " << rpp_output.str() << ", " << gpp_output.str() << ", "
<< ", " << rp_output.str() << hp_output.str() << ", " << g3p_output.str() << "}";
<< ", " << gp_output.str()
<< ", " << rpp_output.str()
<< ", " << gpp_output.str()
<< ", " << hp_output.str()
<< ", " << g3p_output.str()
<< "}";
} }
void void
...@@ -3839,7 +4226,8 @@ DynamicModel::checkNoRemainingPacExpectation() const ...@@ -3839,7 +4226,8 @@ DynamicModel::checkNoRemainingPacExpectation() const
for (size_t eq = 0; eq < equations.size(); eq++) for (size_t eq = 0; eq < equations.size(); eq++)
if (equations[eq]->containsPacExpectation()) if (equations[eq]->containsPacExpectation())
{ {
cerr << "ERROR: in equation " << equation_tags.getTagValueByEqnAndKey(eq, "name").value_or(to_string(eq+1)) cerr << "ERROR: in equation "
<< equation_tags.getTagValueByEqnAndKey(eq, "name").value_or(to_string(eq + 1))
<< ", the pac_expectation operator references an unknown pac_model" << endl; << ", the pac_expectation operator references an unknown pac_model" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -3850,8 +4238,8 @@ DynamicModel::simplifyEquations() ...@@ -3850,8 +4238,8 @@ DynamicModel::simplifyEquations()
{ {
size_t last_subst_table_size = 0; size_t last_subst_table_size = 0;
map<VariableNode*, NumConstNode*> subst_table; map<VariableNode*, NumConstNode*> subst_table;
// Equations with “mcp” tag are excluded, see dynare#1697 // Equations with a complementarity condition are excluded, see dynare#1697
findConstantEquationsWithoutMcpTag(subst_table); findConstantEquationsWithoutComplementarityCondition(subst_table);
while (subst_table.size() != last_subst_table_size) while (subst_table.size() != last_subst_table_size)
{ {
last_subst_table_size = subst_table.size(); last_subst_table_size = subst_table.size();
...@@ -3862,7 +4250,7 @@ DynamicModel::simplifyEquations() ...@@ -3862,7 +4250,7 @@ DynamicModel::simplifyEquations()
for (auto& equation : static_only_equations) for (auto& equation : static_only_equations)
equation = dynamic_cast<BinaryOpNode*>(equation->replaceVarsInEquation(subst_table)); equation = dynamic_cast<BinaryOpNode*>(equation->replaceVarsInEquation(subst_table));
subst_table.clear(); subst_table.clear();
findConstantEquationsWithoutMcpTag(subst_table); findConstantEquationsWithoutComplementarityCondition(subst_table);
} }
} }
...@@ -3872,8 +4260,11 @@ DynamicModel::checkNoRemainingPacTargetNonstationary() const ...@@ -3872,8 +4260,11 @@ DynamicModel::checkNoRemainingPacTargetNonstationary() const
for (size_t eq = 0; eq < equations.size(); eq++) for (size_t eq = 0; eq < equations.size(); eq++)
if (equations[eq]->containsPacTargetNonstationary()) if (equations[eq]->containsPacTargetNonstationary())
{ {
cerr << "ERROR: in equation " << equation_tags.getTagValueByEqnAndKey(eq, "name").value_or(to_string(eq+1)) cerr << "ERROR: in equation "
<< ", the pac_target_nonstationary operator does not match a corresponding 'pac_target_info' block" << endl; << equation_tags.getTagValueByEqnAndKey(eq, "name").value_or(to_string(eq + 1))
<< ", the pac_target_nonstationary operator does not match a corresponding "
"'pac_target_info' block"
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -3883,16 +4274,161 @@ DynamicModel::checkIsLinear() const ...@@ -3883,16 +4274,161 @@ DynamicModel::checkIsLinear() const
{ {
if (!nonzero_hessian_eqs.empty()) if (!nonzero_hessian_eqs.empty())
{ {
cerr << "ERROR: If the model is declared linear the second derivatives must be equal to zero." << endl cerr << "ERROR: If the model is declared linear the second derivatives must be equal to zero."
<< endl
<< " The following equations have non-zero second derivatives:" << endl; << " The following equations have non-zero second derivatives:" << endl;
for (auto it : nonzero_hessian_eqs) for (auto it : nonzero_hessian_eqs)
{ {
cerr << " * Eq # " << it + 1; cerr << " * Eq # " << it + 1;
if (optional<string> eqname { equation_tags.getTagValueByEqnAndKey(it, "name") }; if (optional<string> eqname {equation_tags.getTagValueByEqnAndKey(it, "name")}; eqname)
eqname)
cerr << " [" << *eqname << "]"; cerr << " [" << *eqname << "]";
cerr << endl; cerr << endl;
} }
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
void
DynamicModel::checkOccbinRegimes() const
{
for (const auto& [eq_name, tracker] : occbin_regime_trackers)
{
try
{
tracker.checkAllRegimesPresent();
}
catch (OccbinRegimeTracker::MissingRegimeException& e)
{
cerr << "ERROR: for equation '" << eq_name << "', the regime corresponding to ";
if (!e.constraints_bind.empty())
{
cerr << "bind='";
for (bool first_printed {false}; const auto& r : e.constraints_bind)
{
if (exchange(first_printed, true))
cerr << ",";
cerr << r;
}
}
if (!e.constraints_bind.empty() && !e.constraints_relax.empty())
cerr << "' and ";
if (!e.constraints_relax.empty())
{
cerr << "relax='";
for (bool first_printed {false}; const auto& r : e.constraints_relax)
{
if (exchange(first_printed, true))
cerr << ",";
cerr << r;
}
}
cerr << "' is not defined" << endl;
exit(EXIT_FAILURE);
}
}
}
void
DynamicModel::OccbinRegimeTracker::addRegime(const vector<string>& constraints_bind,
const vector<string>& constraints_relax)
{
// Check that no constraint appears in both bind and relax
set constraints_bind_sorted(constraints_bind.begin(), constraints_bind.end()),
constraints_relax_sorted(constraints_relax.begin(), constraints_relax.end());
vector<string> constraints_intersect;
ranges::set_intersection(constraints_bind_sorted, constraints_relax_sorted,
back_inserter(constraints_intersect));
if (!constraints_intersect.empty())
throw ConstraintInBothBindAndRelaxException {constraints_intersect.front()};
// If a constraint has never been mentioned before, add it to the list and adapt the regimes
vector<string> constraints_union;
ranges::set_union(constraints_bind_sorted, constraints_relax_sorted,
back_inserter(constraints_union));
for (const auto& c : constraints_union)
if (ranges::find(constraints, c) == constraints.end())
{
constraints.push_back(c);
auto regimes_copy = regimes_present;
regimes_present.clear();
for (const auto& r : regimes_copy)
{
auto r0 = r, r1 = r;
r0.push_back(false);
r1.push_back(true);
regimes_present.insert(r0);
regimes_present.insert(r1);
}
}
// Create the bit vector(s) corresponding to the function arguments
vector<bool> new_regime_template(constraints.size(), false);
for (const auto& c : constraints_bind)
{
int i = ranges::distance(constraints.begin(), ranges::find(constraints, c));
new_regime_template[i] = true;
}
set<vector<bool>> new_regimes {new_regime_template};
set all_constraints_sorted(constraints.begin(), constraints.end());
vector<string> constraints_not_mentioned;
ranges::set_difference(all_constraints_sorted, constraints_union,
back_inserter(constraints_not_mentioned));
for (const auto& c : constraints_not_mentioned)
{
int i = ranges::distance(constraints.begin(), ranges::find(constraints, c));
auto new_regimes_copy = new_regimes;
for (const auto& r : new_regimes_copy)
{
auto r2 = r;
r2[i] = true;
new_regimes.insert(move(r2));
}
}
// Add the new bit vector(s)
for (const auto& r : new_regimes)
{
auto [it, success] = regimes_present.insert(r);
if (!success)
{
auto [constraints_bind_duplicate, constraints_relax_duplicate]
= convertBitVectorToRegimes(r);
throw RegimeAlreadyPresentException {constraints_bind_duplicate,
constraints_relax_duplicate};
}
}
}
void
DynamicModel::OccbinRegimeTracker::checkAllRegimesPresent() const
{
vector<bool> r(constraints.size(), false);
do
{
if (!regimes_present.contains(r))
{
auto [constraints_bind, constraints_relax] = convertBitVectorToRegimes(r);
throw MissingRegimeException {constraints_bind, constraints_relax};
}
auto it = ranges::find(r, false);
if (it == r.end())
break;
*it = true;
/* NB: cannot use ranges::fill since vector<bool>::iterator does not satisfy
indirectly_writable concept. Should be fixed in C++23: https://wg21.link/p2321 */
fill(r.begin(), it, false);
}
while (true);
}
pair<vector<string>, vector<string>>
DynamicModel::OccbinRegimeTracker::convertBitVectorToRegimes(const vector<bool>& r) const
{
vector<string> constraints_bind, constraints_relax;
for (size_t i = 0; i < constraints.size(); i++)
if (r[i])
constraints_bind.push_back(constraints[i]);
else
constraints_relax.push_back(constraints[i]);
return {constraints_bind, constraints_relax};
}
/* /*
* Copyright © 2003-2023 Dynare Team * Copyright © 2003-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -17,14 +17,14 @@ ...@@ -17,14 +17,14 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef _DYNAMICMODEL_HH #ifndef DYNAMIC_MODEL_HH
#define _DYNAMICMODEL_HH #define DYNAMIC_MODEL_HH
#include <fstream>
#include <filesystem> #include <filesystem>
#include <fstream>
#include "StaticModel.hh"
#include "Bytecode.hh" #include "Bytecode.hh"
#include "StaticModel.hh"
using namespace std; using namespace std;
...@@ -42,6 +42,41 @@ public: ...@@ -42,6 +42,41 @@ public:
variable is zero. Controlled by option “balanced_growth_test_tol” of the variable is zero. Controlled by option “balanced_growth_test_tol” of the
“model” block. The default should not be too small (see dynare#1389). */ “model” block. The default should not be too small (see dynare#1389). */
double balanced_growth_test_tol {1e-6}; double balanced_growth_test_tol {1e-6};
/* For a given equation, tracks all the regimes and the declared alternatives with combinations of
bind and relax tags */
class OccbinRegimeTracker
{
private:
// The list of constraints used for this equation
vector<string> constraints;
/* The list of regimes present for this equation; each regime is a vector of boolean, of same
length as “constraints”; each boolean represents a constraint (in the order of
“constraints”): false for relax, true for bind */
set<vector<bool>> regimes_present;
public:
struct ConstraintInBothBindAndRelaxException
{
const string constraint;
};
struct RegimeAlreadyPresentException
{
const vector<string> constraints_bind, constraints_relax;
};
void addRegime(const vector<string>& constraints_bind,
const vector<string>& constraints_relax) noexcept(false);
struct MissingRegimeException
{
const vector<string> constraints_bind, constraints_relax;
};
void checkAllRegimesPresent() const noexcept(false);
private:
[[nodiscard]] pair<vector<string>, vector<string>>
convertBitVectorToRegimes(const vector<bool>& r) const;
};
private: private:
/* Used in the balanced growth test, for skipping equations where the test /* Used in the balanced growth test, for skipping equations where the test
cannot be performed (i.e. when LHS=RHS at the initial values). Should not cannot be performed (i.e. when LHS=RHS at the initial values). Should not
...@@ -58,6 +93,9 @@ private: ...@@ -58,6 +93,9 @@ private:
//! Stores the equation tags of equations declared as [static] //! Stores the equation tags of equations declared as [static]
EquationTags static_only_equations_equation_tags; EquationTags static_only_equations_equation_tags;
// Complementarity conditions of equations declared as [static]
vector<optional<tuple<int, expr_t, expr_t>>> static_only_complementarity_conditions;
using deriv_id_table_t = map<pair<int, int>, int>; using deriv_id_table_t = map<pair<int, int>, int>;
//! Maps a pair (symbol_id, lag) to a deriv ID //! Maps a pair (symbol_id, lag) to a deriv ID
deriv_id_table_t deriv_id_table; deriv_id_table_t deriv_id_table;
...@@ -89,7 +127,8 @@ private: ...@@ -89,7 +127,8 @@ private:
int max_endo_lag_orig {0}, max_endo_lead_orig {0}; int max_endo_lag_orig {0}, max_endo_lead_orig {0};
//! Maximum lag and lead over exogenous variables (positive values) of original model //! Maximum lag and lead over exogenous variables (positive values) of original model
int max_exo_lag_orig {0}, max_exo_lead_orig {0}; int max_exo_lag_orig {0}, max_exo_lead_orig {0};
//! Maximum lag and lead over deterministic exogenous variables (positive values) of original model //! Maximum lag and lead over deterministic exogenous variables (positive values) of original
//! model
int max_exo_det_lag_orig {0}, max_exo_det_lead_orig {0}; int max_exo_det_lag_orig {0}, max_exo_det_lead_orig {0};
// Cross reference information: eq → set of (symb_id, lag) for each symbol type // Cross reference information: eq → set of (symb_id, lag) for each symbol type
...@@ -156,7 +195,8 @@ private: ...@@ -156,7 +195,8 @@ private:
void testTrendDerivativesEqualToZero(const eval_context_t& eval_context); void testTrendDerivativesEqualToZero(const eval_context_t& eval_context);
//! Allocates the derivation IDs for all dynamic variables of the model //! 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 */ /*! Also computes max_{endo,exo}_{lead_lag}, and initializes dynJacobianColsNbr to the number of
* dynamic endos */
void computeDerivIDs(); void computeDerivIDs();
/* Compute the Jacobian column indices in the block decomposition case /* Compute the Jacobian column indices in the block decomposition case
...@@ -167,26 +207,28 @@ private: ...@@ -167,26 +207,28 @@ private:
//! Factorized code for substitutions of leads/lags //! Factorized code for substitutions of leads/lags
/*! \param[in] type determines which type of variables is concerned /*! \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] deterministic_model whether we are in a deterministic model (only for exogenous
\param[in] subset variables to which to apply the transformation (only for diff of forward vars) leads/lags) \param[in] subset variables to which to apply the transformation (only for diff of
forward vars)
*/ */
void substituteLeadLagInternal(AuxVarType type, bool deterministic_model, const vector<string> &subset); void substituteLeadLagInternal(AuxVarType type, bool deterministic_model,
const vector<string>& subset);
//! Help computeXrefs to compute the reverse references (i.e. param->eqs, endo->eqs, etc) //! 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); void computeRevXref(map<pair<int, int>, set<int>>& xrefset, const set<pair<int, int>>& eiref,
int eqn);
//! Write reverse cross references //! Write reverse cross references
void writeRevXrefs(ostream &output, const map<pair<int, int>, set<int>> &xrefmap, const string &type) const; void writeRevXrefs(ostream& output, const map<pair<int, int>, set<int>>& xrefmap,
const string& type) const;
/* Writes MATLAB/Octave wrapper function for computing residuals and /* Writes MATLAB/Octave wrapper function for computing residuals and
derivatives at the same time (legacy representation) */ derivatives at the same time (legacy representation) */
void writeDynamicMWrapperFunction(const string& name, const string& ending) const; void writeDynamicMWrapperFunction(const string& name, const string& ending) const;
/* Helper for writing MATLAB/Octave functions for residuals/derivatives and /* Helper for writing MATLAB/Octave functions for residuals/derivatives and
their temporary terms (legacy representation) */ their temporary terms (legacy representation) */
void writeDynamicMFileHelper(const string &basename, void writeDynamicMFileHelper(const string& basename, const string& name, const string& retvalname,
const string &name, const string &retvalname, const string& name_tt, size_t ttlen, const string& previous_tt_name,
const string &name_tt, size_t ttlen,
const string &previous_tt_name,
const ostringstream& init_s, const ostringstream& end_s, const ostringstream& init_s, const ostringstream& end_s,
const ostringstream& s, const ostringstream& s_tt) const; const ostringstream& s, const ostringstream& s_tt) const;
...@@ -221,7 +263,8 @@ private: ...@@ -221,7 +263,8 @@ private:
Returns a set of pairs (tag name, tag value) corresponding to the set of Returns a set of pairs (tag name, tag value) corresponding to the set of
equations to be included or excluded. equations to be included or excluded.
*/ */
static vector<map<string, string>> parseIncludeExcludeEquations(const string &inc_exc_option_value, bool exclude_eqs); static vector<map<string, string>>
parseIncludeExcludeEquations(const string& inc_exc_option_value, bool exclude_eqs);
/* Helper for the removeEquations() method. /* Helper for the removeEquations() method.
listed_eqs_by_tag describes a list of equations to remove (identified by listed_eqs_by_tag describes a list of equations to remove (identified by
...@@ -240,12 +283,11 @@ private: ...@@ -240,12 +283,11 @@ private:
Returns a list of excluded variables (empty if Returns a list of excluded variables (empty if
excluded_vars_change_type=false) */ excluded_vars_change_type=false) */
vector<int> removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag, vector<int> removeEquationsHelper(
bool exclude_eqs, bool excluded_vars_change_type, set<map<string, string>>& listed_eqs_by_tag, bool exclude_eqs, bool excluded_vars_change_type,
vector<BinaryOpNode *> &all_equations, vector<BinaryOpNode*>& all_equations, vector<optional<int>>& all_equations_lineno,
vector<optional<int>> &all_equations_lineno, vector<optional<tuple<int, expr_t, expr_t>>>& all_complementarity_conditions,
EquationTags &all_equation_tags, EquationTags& all_equation_tags, bool static_equations) const;
bool static_equations) const;
//! Compute autoregressive matrices of trend component models //! Compute autoregressive matrices of trend component models
/* The algorithm uses matching rules over expression trees. It cannot handle /* The algorithm uses matching rules over expression trees. It cannot handle
...@@ -254,7 +296,8 @@ private: ...@@ -254,7 +296,8 @@ private:
//! Compute error component matrices of trend component_models //! Compute error component matrices of trend component_models
/*! Returns a pair (A0r, A0starr) */ /*! Returns a pair (A0r, A0starr) */
pair<map<string, map<tuple<int, int>, expr_t>>, map<string, map<tuple<int, int>, expr_t>>> computeErrorComponentMatrices(const ExprNode::subst_table_t &diff_subst_table) const; pair<map<string, map<tuple<int, int>, expr_t>>, map<string, map<tuple<int, int>, expr_t>>>
computeErrorComponentMatrices(const ExprNode::subst_table_t& diff_subst_table) const;
/* For a VAR model, given the symbol ID of a LHS variable, and a (negative) /* For a VAR model, given the symbol ID of a LHS variable, and a (negative)
lag, returns all the corresponding deriv_ids (by properly dealing with two lag, returns all the corresponding deriv_ids (by properly dealing with two
...@@ -270,6 +313,9 @@ private: ...@@ -270,6 +313,9 @@ private:
return blocks_jacob_cols_endo[blk].at({var, lag}); return blocks_jacob_cols_endo[blk].at({var, lag});
} }
// Used to check consistency of bind/relax tags; the keys are equation names
map<string, OccbinRegimeTracker> occbin_regime_trackers;
protected: protected:
string string
modelClassName() const override modelClassName() const override
...@@ -278,9 +324,9 @@ protected: ...@@ -278,9 +324,9 @@ protected:
} }
public: public:
DynamicModel(SymbolTable &symbol_table_arg, DynamicModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg,
TrendComponentModelTable& trend_component_model_table_arg, TrendComponentModelTable& trend_component_model_table_arg,
VarModelTable& var_model_table_arg); VarModelTable& var_model_table_arg);
...@@ -295,10 +341,11 @@ public: ...@@ -295,10 +341,11 @@ public:
//! Execute computations (variable sorting + derivation + block decomposition) //! Execute computations (variable sorting + derivation + block decomposition)
/*! /*!
\param derivsOrder order of derivatives w.r. to exo, exo_det and endo should be computed (implies jacobianExo = true when order >= 2) \param derivsOrder order of 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 (>0 implies jacobianExo = true) (implies jacobianExo = true when order >= 2) \param paramsDerivsOrder order of derivatives w.r.
\param eval_context evaluation context for normalization to a pair (endo/exo/exo_det, parameter) to be computed (>0 implies jacobianExo = true) \param
\param no_tmp_terms if true, no temporary terms will be computed in the dynamic files eval_context evaluation context for normalization \param no_tmp_terms if true, no temporary
terms will be computed in the dynamic files
*/ */
void computingPass(int derivsOrder, int paramsDerivsOrder, const eval_context_t& eval_context, void computingPass(int derivsOrder, int paramsDerivsOrder, const eval_context_t& eval_context,
bool no_tmp_terms, bool block, bool use_dll); bool no_tmp_terms, bool block, bool use_dll);
...@@ -374,7 +421,8 @@ public: ...@@ -374,7 +421,8 @@ public:
void updateVarAndTrendModel() const; void updateVarAndTrendModel() const;
//! Writes dynamic model file (+ bytecode) //! Writes dynamic model file (+ bytecode)
void writeDynamicFile(const string &basename, bool use_dll, const string &mexext, const filesystem::path &matlabroot, bool julia) const; void writeDynamicFile(const string& basename, bool use_dll, const string& mexext,
const filesystem::path& matlabroot, bool julia) const;
//! Writes file containing parameters derivatives //! Writes file containing parameters derivatives
template<bool julia> template<bool julia>
...@@ -383,7 +431,8 @@ public: ...@@ -383,7 +431,8 @@ public:
//! Creates mapping for variables and equations they are present in //! Creates mapping for variables and equations they are present in
void createVariableMapping(); void createVariableMapping();
//! Expands equation tags with default equation names (available "name" tag or LHS variable or equation ID) //! Expands equation tags with default equation names (available "name" tag or LHS variable or
//! equation ID)
void expandEqTags(); void expandEqTags();
//! Find endogenous variables not used in model //! Find endogenous variables not used in model
...@@ -411,7 +460,8 @@ public: ...@@ -411,7 +460,8 @@ public:
Returns the number of optimality FOCs, which is by construction equal to Returns the number of optimality FOCs, which is by construction equal to
the number of endogenous before adding the Lagrange multipliers the number of endogenous before adding the Lagrange multipliers
(internally called ramsey_endo_nbr). */ (internally called ramsey_endo_nbr). */
int computeRamseyPolicyFOCs(const StaticModel &static_model); int computeRamseyPolicyFOCs(const StaticModel& planner_objective,
map<int, pair<expr_t, expr_t>> cloned_ramsey_constraints);
//! Clears all equations //! Clears all equations
void clearEquations(); void clearEquations();
...@@ -420,7 +470,9 @@ public: ...@@ -420,7 +470,9 @@ public:
void replaceMyEquations(DynamicModel& dynamic_model) const; void replaceMyEquations(DynamicModel& dynamic_model) const;
//! Adds an equation marked as [static] //! Adds an equation marked as [static]
void addStaticOnlyEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags); void addStaticOnlyEquation(expr_t eq, const optional<int>& lineno,
optional<tuple<int, expr_t, expr_t>> complementarity_condition,
map<string, string> eq_tags);
//! Returns number of static only equations //! Returns number of static only equations
size_t staticOnlyEquationsNbr() const; size_t staticOnlyEquationsNbr() const;
...@@ -433,7 +485,9 @@ public: ...@@ -433,7 +485,9 @@ public:
auxiliary parameters have already been added to the symbol table. auxiliary parameters have already been added to the symbol table.
It also assumes that the “bind” and “relax” tags have been cleared from It also assumes that the “bind” and “relax” tags have been cleared from
eq_tags. */ eq_tags. */
void addOccbinEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags, const vector<string> &regimes_bind, const vector<string> &regimes_relax); void addOccbinEquation(expr_t eq, const optional<int>& lineno, map<string, string> eq_tags,
const vector<string>& constraints_bind,
const vector<string>& constraints_relax);
//! Writes LaTeX file with the equations of the dynamic model //! Writes LaTeX file with the equations of the dynamic model
void writeLatexFile(const string& basename, bool write_equation_tags) const; void writeLatexFile(const string& basename, bool write_equation_tags) const;
...@@ -471,8 +525,7 @@ public: ...@@ -471,8 +525,7 @@ public:
} }
else else
{ {
if (auto it = dyn_jacobian_cols_table.find(deriv_id); if (auto it = dyn_jacobian_cols_table.find(deriv_id); it == dyn_jacobian_cols_table.end())
it == dyn_jacobian_cols_table.end())
throw UnknownDerivIDException(); throw UnknownDerivIDException();
else else
return it->second; return it->second;
...@@ -481,20 +534,13 @@ public: ...@@ -481,20 +534,13 @@ public:
int int
getJacobianColsNbr(bool sparse) const override getJacobianColsNbr(bool sparse) const override
{ {
return sparse ? return sparse
3*symbol_table.endo_nbr() + symbol_table.exo_nbr() + symbol_table.exo_det_nbr() : ? 3 * symbol_table.endo_nbr() + symbol_table.exo_nbr() + symbol_table.exo_det_nbr()
dyn_jacobian_ncols; : dyn_jacobian_ncols;
} }
void addAllParamDerivId(set<int>& deriv_id_set) override; void addAllParamDerivId(set<int>& deriv_id_set) override;
//! Returns true indicating that this is a dynamic model
bool
isDynamic() const override
{
return true;
};
//! Drive test of detrended equations //! Drive test of detrended equations
void runTrendTest(const eval_context_t& eval_context); void runTrendTest(const eval_context_t& eval_context);
...@@ -515,12 +561,17 @@ public: ...@@ -515,12 +561,17 @@ public:
//! Transforms the model by removing all UnaryOpcode::expectation //! Transforms the model by removing all UnaryOpcode::expectation
void substituteExpectation(bool partial_information_model); void substituteExpectation(bool partial_information_model);
//! Transforms the model by decreasing the lead/lag of predetermined variables in model equations by one //! Transforms the model by decreasing the lead/lag of predetermined variables in model equations
//! by one
void transformPredeterminedVariables(); void transformPredeterminedVariables();
// Performs the transformations associated to variables declared with “var(log)” // Performs the transformations associated to variables declared with “var(log)”
void substituteLogTransform(); void substituteLogTransform();
/* Performs the transformations associated to aggregation operators in heterogeneous models, such
as SUM(…) */
void substituteAggregationOperators();
// Check that no variable was declared with “var(log)” in the given equations // Check that no variable was declared with “var(log)” in the given equations
void checkNoWithLogTransform(const set<int>& eqnumbers); void checkNoWithLogTransform(const set<int>& eqnumbers);
...@@ -548,20 +599,28 @@ public: ...@@ -548,20 +599,28 @@ public:
/* Creates aux vars for all unary operators in all equations. Also makes the /* Creates aux vars for all unary operators in all equations. Also makes the
substitution in growth terms of pac_model/pac_target_info and in substitution in growth terms of pac_model/pac_target_info and in
expressions of var_expectation_model. */ expressions of var_expectation_model. */
pair<lag_equivalence_table_t, ExprNode::subst_table_t> substituteUnaryOps(VarExpectationModelTable &var_expectation_model_table, PacModelTable &pac_model_table); pair<lag_equivalence_table_t, ExprNode::subst_table_t>
substituteUnaryOps(VarExpectationModelTable& var_expectation_model_table,
PacModelTable& pac_model_table);
/* Creates aux vars for all unary operators in specified equations. Also makes the /* Creates aux vars for all unary operators in specified equations. Also makes the
substitution in growth terms of pac_model/pac_target_info and in substitution in growth terms of pac_model/pac_target_info and in
expressions of var_expectation_model. */ expressions of var_expectation_model. */
pair<lag_equivalence_table_t, ExprNode::subst_table_t> substituteUnaryOps(const set<int> &eqnumbers, VarExpectationModelTable &var_expectation_model_table, PacModelTable &pac_model_table); pair<lag_equivalence_table_t, ExprNode::subst_table_t>
substituteUnaryOps(const set<int>& eqnumbers,
VarExpectationModelTable& var_expectation_model_table,
PacModelTable& pac_model_table);
//! Substitutes diff operator //! Substitutes diff operator
pair<lag_equivalence_table_t, ExprNode::subst_table_t> substituteDiff(VarExpectationModelTable &var_expectation_model_table, PacModelTable &pac_model_table); pair<lag_equivalence_table_t, ExprNode::subst_table_t>
substituteDiff(VarExpectationModelTable& var_expectation_model_table,
PacModelTable& pac_model_table);
//! Substitute VarExpectation operators //! Substitute VarExpectation operators
void substituteVarExpectation(const map<string, expr_t>& subst_table); void substituteVarExpectation(const map<string, expr_t>& subst_table);
void analyzePacEquationStructure(const string &name, map<string, string> &pac_eq_name, PacModelTable::equation_info_t &pac_equation_info); void analyzePacEquationStructure(const string& name, map<string, string>& pac_eq_name,
PacModelTable::equation_info_t& pac_equation_info);
// Exception thrown by getPacTargetSymbId() // Exception thrown by getPacTargetSymbId()
struct PacTargetNotIdentifiedException struct PacTargetNotIdentifiedException
...@@ -578,26 +637,31 @@ public: ...@@ -578,26 +637,31 @@ public:
The symbol IDs of the new endogenous are added to pac_aux_var_symb_ids, The symbol IDs of the new endogenous are added to pac_aux_var_symb_ids,
and the new auxiliary parameters to pac_mce_alpha_symb_ids. and the new auxiliary parameters to pac_mce_alpha_symb_ids.
*/ */
void computePacModelConsistentExpectationSubstitution(const string &name, void computePacModelConsistentExpectationSubstitution(
int discount_symb_id, int pac_eq_max_lag, const string& name, int discount_symb_id, int pac_eq_max_lag, expr_t growth_correction_term,
expr_t growth_correction_term, string auxname, ExprNode::subst_table_t& diff_subst_table,
string auxname, map<string, int>& pac_aux_var_symb_ids, map<string, vector<int>>& pac_aux_param_symb_ids,
ExprNode::subst_table_t &diff_subst_table,
map<string, int> &pac_aux_var_symb_ids,
map<string, vector<int>> &pac_aux_param_symb_ids,
map<string, expr_t>& pac_expectation_substitution); map<string, expr_t>& pac_expectation_substitution);
/* For a PAC MCE model with an associated pac_target_info, fill pac_expectation_substitution with
the expression that will be substituted for the pac_expectation operator. In the process, add
the variables and the equations defining Z₁ and Z₀ for each component. The new auxiliary
parameters are added to pac_mce_alpha_symb_ids. The routine also creates the auxiliary
variables for the components, and adds the corresponding equations.
*/
void computePacModelConsistentExpectationSubstitutionWithComponents(
const string& name, int discount_symb_id, int pac_eq_max_lag,
ExprNode::subst_table_t& diff_subst_table, map<string, vector<int>>& pac_aux_param_symb_ids,
vector<PacModelTable::target_component_t>& pac_target_components,
map<string, expr_t>& pac_expectation_substitution);
/* For a PAC backward model, fill pac_expectation_substitution with the /* For a PAC backward model, fill pac_expectation_substitution with the
expression that will be substituted for the pac_expectation operator. expression that will be substituted for the pac_expectation operator.
The symbol IDs of the new parameters are also added to pac_aux_param_symb_ids. The symbol IDs of the new parameters are also added to pac_aux_param_symb_ids.
The symbol ID of the new auxiliary variable is added to pac_aux_var_symb_ids. */ The symbol ID of the new auxiliary variable is added to pac_aux_var_symb_ids. */
void computePacBackwardExpectationSubstitution(const string &name, void computePacBackwardExpectationSubstitution(const string& name, const vector<int>& lhs,
const vector<int> &lhs, int max_lag, const string& aux_model_type,
int max_lag, expr_t growth_correction_term, string auxname,
const string &aux_model_type,
expr_t growth_correction_term,
string auxname,
map<string, int>& pac_aux_var_symb_ids, map<string, int>& pac_aux_var_symb_ids,
map<string, vector<int>>& pac_aux_param_symb_ids, map<string, vector<int>>& pac_aux_param_symb_ids,
map<string, expr_t>& pac_expectation_substitution); map<string, expr_t>& pac_expectation_substitution);
...@@ -610,10 +674,8 @@ public: ...@@ -610,10 +674,8 @@ public:
in target_components. in target_components.
The routine also creates the auxiliary variables for the components, and The routine also creates the auxiliary variables for the components, and
adds the corresponding equations. */ adds the corresponding equations. */
void computePacBackwardExpectationSubstitutionWithComponents(const string &name, void computePacBackwardExpectationSubstitutionWithComponents(
const vector<int> &lhs, const string& name, const vector<int>& lhs, int max_lag, const string& aux_model_type,
int max_lag,
const string &aux_model_type,
vector<PacModelTable::target_component_t>& pac_target_components, vector<PacModelTable::target_component_t>& pac_target_components,
map<string, expr_t>& pac_expectation_substitution); map<string, expr_t>& pac_expectation_substitution);
...@@ -650,15 +712,17 @@ public: ...@@ -650,15 +712,17 @@ public:
auto auto
getStaticOnlyEquationsInfo() const getStaticOnlyEquationsInfo() const
{ {
return tuple{static_only_equations, static_only_equations_lineno, static_only_equations_equation_tags}; return tuple {static_only_equations, static_only_equations_lineno,
}; static_only_complementarity_conditions, static_only_equations_equation_tags};
}
//! Returns true if a parameter was used in the model block with a lead or lag //! Returns true if a parameter was used in the model block with a lead or lag
bool ParamUsedWithLeadLag() const; bool ParamUsedWithLeadLag() const;
bool isChecksumMatching(const string& basename) const; bool isChecksumMatching(const string& basename) const;
//! Simplify model equations: if a variable is equal to a constant, replace that variable elsewhere in the model //! Simplify model equations: if a variable is equal to a constant, replace that variable
//! elsewhere in the model
/*! Equations with MCP tags are excluded, see dynare#1697 */ /*! Equations with MCP tags are excluded, see dynare#1697 */
void simplifyEquations(); void simplifyEquations();
...@@ -685,6 +749,9 @@ public: ...@@ -685,6 +749,9 @@ public:
{ {
static_mfs = static_mfs_arg; static_mfs = static_mfs_arg;
} }
// Checks that all alternatives are declared for all Occbin regimes in all equations
void checkOccbinRegimes() const;
}; };
template<bool julia> template<bool julia>
...@@ -694,10 +761,11 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const ...@@ -694,10 +761,11 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const
if (!params_derivatives.size()) if (!params_derivatives.size())
return; return;
constexpr ExprNodeOutputType output_type { julia ? ExprNodeOutputType::juliaDynamicModel : ExprNodeOutputType::matlabDynamicModel }; constexpr ExprNodeOutputType output_type {julia ? ExprNodeOutputType::juliaDynamicModel
: ExprNodeOutputType::matlabDynamicModel};
auto [tt_output, rp_output, gp_output, rpp_output, gpp_output, hp_output, g3p_output] auto [tt_output, rp_output, gp_output, rpp_output, gpp_output, hp_output,
{ writeParamsDerivativesFileHelper<output_type>() }; g3p_output] {writeParamsDerivativesFileHelper<output_type>()};
if constexpr (!julia) if constexpr (!julia)
{ {
...@@ -708,79 +776,159 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const ...@@ -708,79 +776,159 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl; cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
paramsDerivsFile << "function [rp, gp, rpp, gpp, hp, g3p] = dynamic_params_derivs(y, x, params, steady_state, it_, ss_param_deriv, ss_param_2nd_deriv)" << endl paramsDerivsFile
<< "function [rp, gp, rpp, gpp, hp, g3p] = dynamic_params_derivs(y, x, params, "
"steady_state, it_, ss_param_deriv, ss_param_2nd_deriv)"
<< endl
<< "%" << endl << "%" << endl
<< "% Compute the derivatives of the dynamic model with respect to the parameters" << endl << "% Compute the derivatives of the dynamic model with respect to the parameters" << endl
<< "% Inputs :" << endl << "% Inputs :" << endl
<< "% y [#dynamic variables by 1] double vector of endogenous variables in the order stored" << endl << "% y [#dynamic variables by 1] double vector of endogenous variables in "
<< "% in M_.lead_lag_incidence; see the Manual" << endl "the order stored"
<< "% x [nperiods by M_.exo_nbr] double matrix of exogenous variables (in declaration order)" << endl << endl
<< "% in M_.lead_lag_incidence; see the "
"Manual"
<< endl
<< "% x [nperiods by M_.exo_nbr] double matrix of exogenous variables (in "
"declaration order)"
<< endl
<< "% for all simulation periods" << endl << "% for all simulation periods" << endl
<< "% params [M_.param_nbr by 1] double vector of parameter values in declaration order" << endl << "% params [M_.param_nbr by 1] double vector of parameter values in "
<< "% steady_state [M_.endo_nbr by 1] double vector of steady state values" << endl "declaration order"
<< "% it_ scalar double time period for exogenous variables for which to evaluate the model" << endl << endl
<< "% ss_param_deriv [M_.eq_nbr by #params] Jacobian matrix of the steady states values with respect to the parameters" << endl << "% steady_state [M_.endo_nbr by 1] double vector of steady state values"
<< "% ss_param_2nd_deriv [M_.eq_nbr by #params by #params] Hessian matrix of the steady states values with respect to the parameters" << endl << endl
<< "% it_ scalar double time period for exogenous "
"variables for which to evaluate the model"
<< endl
<< "% ss_param_deriv [M_.eq_nbr by #params] Jacobian matrix of the steady "
"states values with respect to the parameters"
<< endl
<< "% ss_param_2nd_deriv [M_.eq_nbr by #params by #params] Hessian matrix of the "
"steady states values with respect to the parameters"
<< endl
<< "%" << endl << "%" << endl
<< "% Outputs:" << endl << "% Outputs:" << endl
<< "% rp [M_.eq_nbr by #params] double Jacobian matrix of dynamic model equations with respect to parameters " << endl << "% rp [M_.eq_nbr by #params] double Jacobian matrix of dynamic model "
<< "% Dynare may prepend or append auxiliary equations, see M_.aux_vars" << endl "equations with respect to parameters "
<< "% gp [M_.endo_nbr by #dynamic variables by #params] double Derivative of the Jacobian matrix of the dynamic model equations with respect to the parameters" << endl << endl
<< "% rows: equations in order of declaration" << endl << "% Dynare may prepend or append "
<< "% columns: variables in order stored in M_.lead_lag_incidence" << endl "auxiliary equations, see M_.aux_vars"
<< "% rpp [#second_order_residual_terms by 4] double Hessian matrix of second derivatives of residuals with respect to parameters;" << endl << endl
<< "% rows: respective derivative term" << endl << "% gp [M_.endo_nbr by #dynamic variables by #params] double Derivative of "
<< "% 1st column: equation number of the term appearing" << endl "the Jacobian matrix of the dynamic model equations with respect to the parameters"
<< "% 2nd column: number of the first parameter in derivative" << endl << endl
<< "% 3rd column: number of the second parameter in derivative" << endl << "% rows: equations in order "
<< "% 4th column: value of the Hessian term" << endl "of declaration"
<< "% gpp [#second_order_Jacobian_terms by 5] double Hessian matrix of second derivatives of the Jacobian with respect to the parameters;" << endl << endl
<< "% rows: respective derivative term" << endl << "% columns: variables in "
<< "% 1st column: equation number of the term appearing" << endl "order stored in M_.lead_lag_incidence"
<< "% 2nd column: column number of variable in Jacobian of the dynamic model" << endl << endl
<< "% 3rd column: number of the first parameter in derivative" << endl << "% rpp [#second_order_residual_terms by 4] double Hessian matrix of second "
<< "% 4th column: number of the second parameter in derivative" << endl "derivatives of residuals with respect to parameters;"
<< "% 5th column: value of the Hessian term" << endl << endl
<< "% hp [#first_order_Hessian_terms by 5] double Jacobian matrix of derivatives of the dynamic Hessian with respect to the parameters;" << endl << "% rows: respective "
<< "% rows: respective derivative term" << endl "derivative term"
<< "% 1st column: equation number of the term appearing" << endl << endl
<< "% 2nd column: column number of first variable in Hessian of the dynamic model" << endl << "% 1st column: equation "
<< "% 3rd column: column number of second variable in Hessian of the dynamic model" << endl "number of the term appearing"
<< "% 4th column: number of the parameter in derivative" << endl << endl
<< "% 5th column: value of the Hessian term" << endl << "% 2nd column: number of "
<< "% g3p [#first_order_g3_terms by 6] double Jacobian matrix of derivatives of g3 (dynamic 3rd derivs) with respect to the parameters;" << endl "the first parameter in derivative"
<< "% rows: respective derivative term" << endl << endl
<< "% 1st column: equation number of the term appearing" << endl << "% 3rd column: number of "
<< "% 2nd column: column number of first variable in g3 of the dynamic model" << endl "the second parameter in derivative"
<< "% 3rd column: column number of second variable in g3 of the dynamic model" << endl << endl
<< "% 4th column: column number of third variable in g3 of the dynamic model" << endl << "% 4th column: value of "
<< "% 5th column: number of the parameter in derivative" << endl "the Hessian term"
<< "% 6th column: value of the Hessian term" << endl << endl
<< "% gpp [#second_order_Jacobian_terms by 5] double Hessian matrix of second "
"derivatives of the Jacobian with respect to the parameters;"
<< endl
<< "% rows: respective "
"derivative term"
<< endl
<< "% 1st column: equation "
"number of the term appearing"
<< endl
<< "% 2nd column: column "
"number of variable in Jacobian of the dynamic model"
<< endl
<< "% 3rd column: number of "
"the first parameter in derivative"
<< endl
<< "% 4th column: number of "
"the second parameter in derivative"
<< endl
<< "% 5th column: value of "
"the Hessian term"
<< endl
<< "% hp [#first_order_Hessian_terms by 5] double Jacobian matrix of "
"derivatives of the dynamic Hessian with respect to the parameters;"
<< endl
<< "% rows: respective "
"derivative term"
<< endl
<< "% 1st column: equation "
"number of the term appearing"
<< endl
<< "% 2nd column: column "
"number of first variable in Hessian of the dynamic model"
<< endl
<< "% 3rd column: column "
"number of second variable in Hessian of the dynamic model"
<< endl
<< "% 4th column: number of "
"the parameter in derivative"
<< endl
<< "% 5th column: value of "
"the Hessian term"
<< endl
<< "% g3p [#first_order_g3_terms by 6] double Jacobian matrix of derivatives of "
"g3 (dynamic 3rd derivs) with respect to the parameters;"
<< endl
<< "% rows: respective "
"derivative term"
<< endl
<< "% 1st column: equation "
"number of the term appearing"
<< endl
<< "% 2nd column: column "
"number of first variable in g3 of the dynamic model"
<< endl
<< "% 3rd column: column "
"number of second variable in g3 of the dynamic model"
<< endl
<< "% 4th column: column "
"number of third variable in g3 of the dynamic model"
<< endl
<< "% 5th column: number of "
"the parameter in derivative"
<< endl
<< "% 6th column: value of "
"the Hessian term"
<< endl
<< "%" << endl << "%" << endl
<< "%" << endl << "%" << endl
<< "% Warning : this file is generated automatically by Dynare" << endl << "% Warning : this file is generated automatically by Dynare" << endl
<< "% from model file (.mod)" << endl << endl << "% from model file (.mod)" << endl
<< endl
<< "T = NaN(" << params_derivs_temporary_terms_idxs.size() << ",1);" << endl << "T = NaN(" << params_derivs_temporary_terms_idxs.size() << ",1);" << endl
<< tt_output.str() << tt_output.str() << "rp = zeros(" << equations.size() << ", "
<< "rp = zeros(" << equations.size() << ", "
<< symbol_table.param_nbr() << ");" << endl << symbol_table.param_nbr() << ");" << endl
<< rp_output.str() << rp_output.str() << "gp = zeros(" << equations.size() << ", "
<< "gp = zeros(" << equations.size() << ", " << getJacobianColsNbr(false) << ", " << symbol_table.param_nbr() << ");" << endl << getJacobianColsNbr(false) << ", " << symbol_table.param_nbr() << ");" << endl
<< gp_output.str() << gp_output.str() << "if nargout >= 3" << endl
<< "if nargout >= 3" << endl
<< "rpp = zeros(" << params_derivatives.at({0, 2}).size() << ",4);" << endl << "rpp = zeros(" << params_derivatives.at({0, 2}).size() << ",4);" << endl
<< rpp_output.str() << rpp_output.str() << "gpp = zeros(" << params_derivatives.at({1, 2}).size() << ",5);"
<< "gpp = zeros(" << params_derivatives.at({ 1, 2 }).size() << ",5);" << endl << endl
<< gpp_output.str() << gpp_output.str() << "end" << endl
<< "end" << endl
<< "if nargout >= 5" << endl << "if nargout >= 5" << endl
<< "hp = zeros(" << params_derivatives.at({2, 1}).size() << ",5);" << endl << "hp = zeros(" << params_derivatives.at({2, 1}).size() << ",5);" << endl
<< hp_output.str() << hp_output.str() << "end" << endl
<< "end" << endl
<< "if nargout >= 6" << endl << "if nargout >= 6" << endl
<< "g3p = zeros(" << params_derivatives.at({3, 1}).size() << ",6);" << endl << "g3p = zeros(" << params_derivatives.at({3, 1}).size() << ",6);" << endl
<< g3p_output.str() << g3p_output.str() << "end" << endl
<< "end" << endl
<< "end" << endl; << "end" << endl;
paramsDerivsFile.close(); paramsDerivsFile.close();
} }
...@@ -793,25 +941,24 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const ...@@ -793,25 +941,24 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const
<< "function dynamic_params_derivs(y, x, params, steady_state, it_," << "function dynamic_params_derivs(y, x, params, steady_state, it_,"
<< "ss_param_deriv, ss_param_2nd_deriv)" << endl << "ss_param_deriv, ss_param_2nd_deriv)" << endl
<< "@inbounds begin" << endl << "@inbounds begin" << endl
<< tt_output.str() << tt_output.str() << "rp = zeros(" << equations.size() << ", "
<< "rp = zeros(" << equations.size() << ", "
<< symbol_table.param_nbr() << ");" << endl << symbol_table.param_nbr() << ");" << endl
<< rp_output.str() << rp_output.str() << "gp = zeros(" << equations.size() << ", "
<< "gp = zeros(" << equations.size() << ", " << getJacobianColsNbr(false) << ", " << symbol_table.param_nbr() << ");" << endl << getJacobianColsNbr(false) << ", " << symbol_table.param_nbr() << ");" << endl
<< gp_output.str() << gp_output.str() << "rpp = zeros(" << params_derivatives.at({0, 2}).size() << ",4);"
<< "rpp = zeros(" << params_derivatives.at({ 0, 2 }).size() << ",4);" << endl << endl
<< rpp_output.str() << rpp_output.str() << "gpp = zeros(" << params_derivatives.at({1, 2}).size() << ",5);"
<< "gpp = zeros(" << params_derivatives.at({ 1, 2 }).size() << ",5);" << endl << endl
<< gpp_output.str() << gpp_output.str() << "hp = zeros(" << params_derivatives.at({2, 1}).size() << ",5);"
<< "hp = zeros(" << params_derivatives.at({ 2, 1 }).size() << ",5);" << endl << endl
<< hp_output.str() << hp_output.str() << "g3p = zeros(" << params_derivatives.at({3, 1}).size() << ",6);"
<< "g3p = zeros(" << params_derivatives.at({ 3, 1 }).size() << ",6);" << endl << endl
<< g3p_output.str() << g3p_output.str() << "end" << endl
<< "end" << endl
<< "return (rp, gp, rpp, gpp, hp, g3p)" << endl << "return (rp, gp, rpp, gpp, hp, g3p)" << endl
<< "end" << endl; << "end" << endl;
writeToFileIfModified(output, filesystem::path{basename} / "model" / "julia" / "DynamicParamsDerivs.jl"); writeToFileIfModified(output, filesystem::path {basename} / "model" / "julia"
/ "DynamicParamsDerivs.jl");
} }
} }
......
// -*- C++ -*- // -*- C++ -*-
/* /*
* Copyright © 2003-2023 Dynare Team * Copyright © 2003-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -28,20 +28,20 @@ ...@@ -28,20 +28,20 @@
%define parse.error verbose %define parse.error verbose
%define parse.trace %define parse.trace
%code top {
class ParsingDriver;
}
%code requires { %code requires {
// Only headers needed for the value and location types go here
// Headers needed by the Bison file itself go in the unqualified %code section
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include <utility>
#include <tuple> #include <tuple>
#include <variant> #include <variant>
#include "CommonEnums.hh" #include "CommonEnums.hh"
#include "ExprNode.hh" #include "ExprNode.hh"
#include "Shocks.hh"
class ParsingDriver;
} }
%param { ParsingDriver &driver } %param { ParsingDriver &driver }
...@@ -54,11 +54,15 @@ class ParsingDriver; ...@@ -54,11 +54,15 @@ class ParsingDriver;
} }
%code { %code {
#include <ranges>
#include <utility>
/* Little hack: we redefine the macro which computes the locations, because /* Little hack: we redefine the macro which computes the locations, because
we need to access the location from within the parsing driver for error we need to access the location from within the parsing driver for error
and warning messages. */ and warning messages. */
#define YYLLOC_DEFAULT(Current, Rhs, N) \ #define YYLLOC_DEFAULT(Current, Rhs, N) \
do { \ do \
{ \
if (N) \ if (N) \
{ \ { \
(Current).begin = YYRHSLOC(Rhs, 1).begin; \ (Current).begin = YYRHSLOC(Rhs, 1).begin; \
...@@ -69,7 +73,8 @@ class ParsingDriver; ...@@ -69,7 +73,8 @@ class ParsingDriver;
(Current).begin = (Current).end = YYRHSLOC(Rhs, 0).end; \ (Current).begin = (Current).end = YYRHSLOC(Rhs, 0).end; \
} \ } \
driver.location = (Current); \ driver.location = (Current); \
} while(false) } \
while (false)
#include "ParsingDriver.hh" #include "ParsingDriver.hh"
...@@ -85,7 +90,7 @@ string ...@@ -85,7 +90,7 @@ string
str_tolower(string s) str_tolower(string s)
{ {
// Converting to unsigned char is needed, see https://en.cppreference.com/w/cpp/string/byte/tolower // Converting to unsigned char is needed, see https://en.cppreference.com/w/cpp/string/byte/tolower
transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::tolower(c); }); ranges::transform(s, s.begin(), [](unsigned char c){ return std::tolower(c); });
return s; return s;
} }
} }
...@@ -98,15 +103,15 @@ str_tolower(string s) ...@@ -98,15 +103,15 @@ str_tolower(string s)
%token BVAR_REPLIC BYTECODE ALL_VALUES_REQUIRED PROPOSAL_DISTRIBUTION REALTIME VINTAGE %token BVAR_REPLIC BYTECODE ALL_VALUES_REQUIRED PROPOSAL_DISTRIBUTION REALTIME VINTAGE
%token CALIB_SMOOTHER CHANGE_TYPE CHECK CONDITIONAL_FORECAST CONDITIONAL_FORECAST_PATHS CONF_SIG CONSTANT CONTROLLED_VAREXO CORR CUTOFF CYCLE_REDUCTION LOGARITHMIC_REDUCTION %token CALIB_SMOOTHER CHANGE_TYPE CHECK CONDITIONAL_FORECAST CONDITIONAL_FORECAST_PATHS CONF_SIG CONSTANT CONTROLLED_VAREXO CORR CUTOFF CYCLE_REDUCTION LOGARITHMIC_REDUCTION
%token COMMA CONSIDER_ALL_ENDOGENOUS CONSIDER_ALL_ENDOGENOUS_AND_AUXILIARY CONSIDER_ONLY_OBSERVED INITIAL_CONDITION_DECOMPOSITION %token COMMA CONSIDER_ALL_ENDOGENOUS CONSIDER_ALL_ENDOGENOUS_AND_AUXILIARY CONSIDER_ONLY_OBSERVED INITIAL_CONDITION_DECOMPOSITION
%token DATAFILE FILE SERIES DOUBLING DR_CYCLE_REDUCTION_TOL DR_LOGARITHMIC_REDUCTION_TOL DR_LOGARITHMIC_REDUCTION_MAXITER DR_ALGO DROP DSAMPLE DYNASAVE DYNATYPE CALIBRATION DIFFERENTIATE_FORWARD_VARS %token DATAFILE FILE SERIES DOUBLING DR_CYCLE_REDUCTION_TOL DR_CYCLE_REDUCTION_MAXITER DR_LOGARITHMIC_REDUCTION_TOL DR_LOGARITHMIC_REDUCTION_MAXITER DR_ALGO DROP DSAMPLE DYNASAVE DYNATYPE CALIBRATION DIFFERENTIATE_FORWARD_VARS
%token END ENDVAL EQUAL ESTIMATION ESTIMATED_PARAMS ESTIMATED_PARAMS_BOUNDS ESTIMATED_PARAMS_INIT EXTENDED_PATH ENDOGENOUS_PRIOR EXPRESSION %token END ENDVAL EQUAL ESTIMATION ESTIMATED_PARAMS ESTIMATED_PARAMS_BOUNDS ESTIMATED_PARAMS_INIT EXTENDED_PATH ENDOGENOUS_PRIOR EXPRESSION
%token FILENAME DIRNAME FILTER_STEP_AHEAD FILTERED_VARS FIRST_OBS FIRST_SIMULATION_PERIOD LAST_SIMULATION_PERIOD LAST_OBS %token FILENAME DIRNAME FILTER_STEP_AHEAD FILTERED_VARS FIRST_OBS FIRST_SIMULATION_PERIOD LAST_SIMULATION_PERIOD LAST_OBS
%token SET_TIME OSR_PARAMS_BOUNDS KEEP_KALMAN_ALGO_IF_SINGULARITY_IS_DETECTED %token SET_TIME OSR_PARAMS_BOUNDS KEEP_KALMAN_ALGO_IF_SINGULARITY_IS_DETECTED
%token <string> FALSE FLOAT_NUMBER DATES %token <string> FALSE FLOAT_NUMBER DATE
%token DEFAULT FIXED_POINT FLIP OPT_ALGO COMPILATION_SETUP COMPILER ADD_FLAGS SUBSTITUTE_FLAGS ADD_LIBS SUBSTITUTE_LIBS %token DEFAULT FIXED_POINT FLIP OPT_ALGO COMPILATION_SETUP COMPILER ADD_FLAGS SUBSTITUTE_FLAGS ADD_LIBS SUBSTITUTE_LIBS
%token FORECAST K_ORDER_SOLVER INSTRUMENTS SHIFT MEAN STDEV VARIANCE MODE INTERVAL SHAPE DOMAINN %token FORECAST K_ORDER_SOLVER INSTRUMENTS SHIFT MEAN STDEV VARIANCE MODE INTERVAL SHAPE DOMAINN
%token GAMMA_PDF GRAPH GRAPH_FORMAT CONDITIONAL_VARIANCE_DECOMPOSITION NOCHECK STD %token GAMMA_PDF GRAPH GRAPH_FORMAT CONDITIONAL_VARIANCE_DECOMPOSITION NOCHECK STD
%token HISTVAL HISTVAL_FILE HOMOTOPY_SETUP HOMOTOPY_MODE HOMOTOPY_STEPS HOMOTOPY_FORCE_CONTINUE HP_FILTER HP_NGRID FILTERED_THEORETICAL_MOMENTS_GRID HYBRID ONE_SIDED_HP_FILTER %token HISTVAL HISTVAL_FILE HOMOTOPY_SETUP HOMOTOPY_MODE HOMOTOPY_STEPS HOMOTOPY_FORCE_CONTINUE HP_FILTER HP_NGRID FILTERED_THEORETICAL_MOMENTS_GRID HYBRID USE_FIRST_ORDER_SOLUTION ONE_SIDED_HP_FILTER
%token IDENTIFICATION INF_CONSTANT INITVAL INITVAL_FILE BOUNDS JSCALE INIT INFILE INVARS %token IDENTIFICATION INF_CONSTANT INITVAL INITVAL_FILE BOUNDS JSCALE INIT INFILE INVARS
%token <string> INT_NUMBER %token <string> INT_NUMBER
%token CONDITIONAL_LIKELIHOOD %token CONDITIONAL_LIKELIHOOD
...@@ -115,11 +120,11 @@ str_tolower(string s) ...@@ -115,11 +120,11 @@ str_tolower(string s)
%token LAPLACE LIK_INIT LINEAR LINEAR_DECOMPOSITION LOAD_IDENT_FILES LOAD_MH_FILE LOAD_RESULTS_AFTER_LOAD_MH LOAD_PARAMS_AND_STEADY_STATE LOGLINEAR LOGDATA LYAPUNOV LINEAR_APPROXIMATION %token LAPLACE LIK_INIT LINEAR LINEAR_DECOMPOSITION LOAD_IDENT_FILES LOAD_MH_FILE LOAD_RESULTS_AFTER_LOAD_MH LOAD_PARAMS_AND_STEADY_STATE LOGLINEAR LOGDATA LYAPUNOV LINEAR_APPROXIMATION
%token LYAPUNOV_COMPLEX_THRESHOLD LYAPUNOV_FIXED_POINT_TOL LYAPUNOV_DOUBLING_TOL LOG_DEFLATOR LOG_TREND_VAR LOG_GROWTH_FACTOR %token LYAPUNOV_COMPLEX_THRESHOLD LYAPUNOV_FIXED_POINT_TOL LYAPUNOV_DOUBLING_TOL LOG_DEFLATOR LOG_TREND_VAR LOG_GROWTH_FACTOR
%token MATCHED_MOMENTS MARKOWITZ MARGINAL_DENSITY MAX MAXIT %token MATCHED_MOMENTS MARKOWITZ MARGINAL_DENSITY MAX MAXIT
%token MFS MH_CONF_SIG MH_DROP MH_INIT_SCALE MH_INIT_SCALE_FACTOR MH_JSCALE MH_TUNE_JSCALE MH_TUNE_GUESS MH_POSTERIOR_MODE_ESTIMATION MH_NBLOCKS MH_REPLIC MH_RECOVER MH_INITIALIZE_FROM_PREVIOUS_MCMC MH_INITIALIZE_FROM_PREVIOUS_MCMC_DIRECTORY MH_INITIALIZE_FROM_PREVIOUS_MCMC_RECORD MH_INITIALIZE_FROM_PREVIOUS_MCMC_PRIOR %token MH_CONF_SIG MH_DROP MH_INIT_SCALE MH_INIT_SCALE_FACTOR MH_JSCALE MH_TUNE_JSCALE MH_TUNE_GUESS MH_POSTERIOR_MODE_ESTIMATION MH_NBLOCKS MH_REPLIC MH_RECOVER MH_INITIALIZE_FROM_PREVIOUS_MCMC MH_INITIALIZE_FROM_PREVIOUS_MCMC_DIRECTORY MH_INITIALIZE_FROM_PREVIOUS_MCMC_RECORD MH_INITIALIZE_FROM_PREVIOUS_MCMC_PRIOR
%token POSTERIOR_MAX_SUBSAMPLE_DRAWS MIN MINIMAL_SOLVING_PERIODS %token POSTERIOR_MAX_SUBSAMPLE_DRAWS MIN MINIMAL_SOLVING_PERIODS
%token MODE_CHECK MODE_CHECK_NEIGHBOURHOOD_SIZE MODE_CHECK_SYMMETRIC_PLOTS MODE_CHECK_NUMBER_OF_POINTS MODE_COMPUTE MODE_FILE MODEL MODEL_COMPARISON MODEL_INFO MSHOCKS ABS SIGN %token MODE_CHECK MODE_CHECK_NEIGHBOURHOOD_SIZE MODE_CHECK_SYMMETRIC_PLOTS MODE_CHECK_NUMBER_OF_POINTS MODE_COMPUTE MODE_FILE MODEL MODEL_COMPARISON MODEL_INFO MSHOCKS ABS SIGN
%token MODEL_DIAGNOSTICS MODIFIEDHARMONICMEAN MOMENTS_VARENDO CONTEMPORANEOUS_CORRELATION DIFFUSE_FILTER SUB_DRAWS TAPER_STEPS GEWEKE_INTERVAL RAFTERY_LEWIS_QRS RAFTERY_LEWIS_DIAGNOSTICS BROOKS_GELMAN_PLOTROWS MCMC_JUMPING_COVARIANCE MOMENT_CALIBRATION %token MODEL_DIAGNOSTICS MODIFIEDHARMONICMEAN MOMENTS_VARENDO CONTEMPORANEOUS_CORRELATION DIFFUSE_FILTER SUB_DRAWS TAPER_STEPS GEWEKE_INTERVAL RAFTERY_LEWIS_QRS RAFTERY_LEWIS_DIAGNOSTICS BROOKS_GELMAN_PLOTROWS MCMC_JUMPING_COVARIANCE MOMENT_CALIBRATION
%token NUMBER_OF_PARTICLES RESAMPLING SYSTEMATIC GENERIC RESAMPLING_THRESHOLD RESAMPLING_METHOD KITAGAWA STRATIFIED SMOOTH %token NUMBER_OF_PARTICLES RESAMPLING SYSTEMATIC GENERIC RESAMPLING_THRESHOLD RESAMPLING_METHOD KITAGAWA STRATIFIED SMOOTH MULTINOMIAL
%token CPF_WEIGHTS AMISANOTRISTANI MURRAYJONESPARSLOW WRITE_EQUATION_TAGS FILTER_INITIAL_STATE %token CPF_WEIGHTS AMISANOTRISTANI MURRAYJONESPARSLOW WRITE_EQUATION_TAGS FILTER_INITIAL_STATE
%token NONLINEAR_FILTER_INITIALIZATION FILTER_ALGORITHM PROPOSAL_APPROXIMATION CUBATURE UNSCENTED MONTECARLO DISTRIBUTION_APPROXIMATION %token NONLINEAR_FILTER_INITIALIZATION FILTER_ALGORITHM PROPOSAL_APPROXIMATION CUBATURE UNSCENTED MONTECARLO DISTRIBUTION_APPROXIMATION
%token <string> NAME %token <string> NAME
...@@ -136,7 +141,7 @@ str_tolower(string s) ...@@ -136,7 +141,7 @@ str_tolower(string s)
%token RELATIVE_IRF REPLIC SIMUL_REPLIC RPLOT SAVE_PARAMS_AND_STEADY_STATE PARAMETER_UNCERTAINTY TARGETS %token RELATIVE_IRF REPLIC SIMUL_REPLIC RPLOT SAVE_PARAMS_AND_STEADY_STATE PARAMETER_UNCERTAINTY TARGETS
%token SHOCKS HETEROSKEDASTIC_SHOCKS SHOCK_DECOMPOSITION SHOCK_GROUPS USE_SHOCK_GROUPS SIMUL SIMUL_ALGO SIMUL_SEED ENDOGENOUS_TERMINAL_PERIOD %token SHOCKS HETEROSKEDASTIC_SHOCKS SHOCK_DECOMPOSITION SHOCK_GROUPS USE_SHOCK_GROUPS SIMUL SIMUL_ALGO SIMUL_SEED ENDOGENOUS_TERMINAL_PERIOD
%token SMOOTHER SMOOTHER2HISTVAL SQUARE_ROOT_SOLVER STACK_SOLVE_ALGO STEADY_STATE_MODEL SOLVE_ALGO SOLVER_PERIODS ROBUST_LIN_SOLVE %token SMOOTHER SMOOTHER2HISTVAL SQUARE_ROOT_SOLVER STACK_SOLVE_ALGO STEADY_STATE_MODEL SOLVE_ALGO SOLVER_PERIODS ROBUST_LIN_SOLVE
%token STDERR STEADY STOCH_SIMUL SYLVESTER SYLVESTER_FIXED_POINT_TOL REGIMES REGIME REALTIME_SHOCK_DECOMPOSITION CONDITIONAL UNCONDITIONAL %token STDERR STEADY STOCH_SIMUL REGIMES REGIME REALTIME_SHOCK_DECOMPOSITION CONDITIONAL UNCONDITIONAL
%token TEX RAMSEY_MODEL RAMSEY_POLICY RAMSEY_CONSTRAINTS PLANNER_DISCOUNT PLANNER_DISCOUNT_LATEX_NAME %token TEX RAMSEY_MODEL RAMSEY_POLICY RAMSEY_CONSTRAINTS PLANNER_DISCOUNT PLANNER_DISCOUNT_LATEX_NAME
%token DISCRETIONARY_POLICY DISCRETIONARY_TOL EVALUATE_PLANNER_OBJECTIVE %token DISCRETIONARY_POLICY DISCRETIONARY_TOL EVALUATE_PLANNER_OBJECTIVE
%token OCCBIN_SETUP OCCBIN_SOLVER OCCBIN_WRITE_REGIMES OCCBIN_GRAPH SIMUL_MAXIT LIKELIHOOD_MAXIT SMOOTHER_MAXIT SIMUL_PERIODS LIKELIHOOD_PERIODS SMOOTHER_PERIODS %token OCCBIN_SETUP OCCBIN_SOLVER OCCBIN_WRITE_REGIMES OCCBIN_GRAPH SIMUL_MAXIT LIKELIHOOD_MAXIT SMOOTHER_MAXIT SIMUL_PERIODS LIKELIHOOD_PERIODS SMOOTHER_PERIODS
...@@ -159,7 +164,7 @@ str_tolower(string s) ...@@ -159,7 +164,7 @@ str_tolower(string s)
%token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN SINH COSH TANH ASINH ACOSH ATANH ERF ERFC DIFF ADL AUXILIARY_MODEL_NAME %token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN SINH COSH TANH ASINH ACOSH ATANH ERF ERFC DIFF ADL AUXILIARY_MODEL_NAME
%token SQRT CBRT NORMCDF NORMPDF STEADY_STATE EXPECTATION %token SQRT CBRT NORMCDF NORMPDF STEADY_STATE EXPECTATION
/* GSA analysis */ /* GSA analysis */
%token DYNARE_SENSITIVITY MORRIS STAB REDFORM PPRIOR PRIOR_RANGE PPOST ILPTAU MORRIS_NLIV %token SENSITIVITY DYNARE_SENSITIVITY MORRIS STAB REDFORM PPRIOR PRIOR_RANGE PPOST ILPTAU MORRIS_NLIV
%token MORRIS_NTRA NSAM LOAD_REDFORM LOAD_RMSE LOAD_STAB ALPHA2_STAB LOGTRANS_REDFORM THRESHOLD_REDFORM %token MORRIS_NTRA NSAM LOAD_REDFORM LOAD_RMSE LOAD_STAB ALPHA2_STAB LOGTRANS_REDFORM THRESHOLD_REDFORM
%token KSSTAT_REDFORM ALPHA2_REDFORM NAMENDO NAMLAGENDO NAMEXO RMSE LIK_ONLY VAR_RMSE PFILT_RMSE ISTART_RMSE %token KSSTAT_REDFORM ALPHA2_REDFORM NAMENDO NAMLAGENDO NAMEXO RMSE LIK_ONLY VAR_RMSE PFILT_RMSE ISTART_RMSE
%token ALPHA_RMSE ALPHA2_RMSE %token ALPHA_RMSE ALPHA2_RMSE
...@@ -168,7 +173,8 @@ str_tolower(string s) ...@@ -168,7 +173,8 @@ str_tolower(string s)
%token VLISTLOG VLISTPER SPECTRAL_DENSITY INIT2SHOCKS %token VLISTLOG VLISTPER SPECTRAL_DENSITY INIT2SHOCKS
%token RESTRICTION RESTRICTION_FNAME CROSS_RESTRICTIONS NLAGS CONTEMP_REDUCED_FORM REAL_PSEUDO_FORECAST %token RESTRICTION RESTRICTION_FNAME CROSS_RESTRICTIONS NLAGS CONTEMP_REDUCED_FORM REAL_PSEUDO_FORECAST
%token DUMMY_OBS NSTATES INDXSCALESSTATES NO_BAYESIAN_PRIOR SPECIFICATION SIMS_ZHA %token DUMMY_OBS NSTATES INDXSCALESSTATES NO_BAYESIAN_PRIOR SPECIFICATION SIMS_ZHA
%token <string> ALPHA BETA ABAND NINV CMS NCMS CNUM GAMMA INV_GAMMA INV_GAMMA1 INV_GAMMA2 NORMAL UNIFORM EPS PDF FIG DR NONE PRIOR PRIOR_VARIANCE HESSIAN IDENTITY_MATRIX DIRICHLET DIAGONAL OPTIMAL %token <string> ALPHA BETA ABAND NINV CMS NCMS CNUM GAMMA INV_GAMMA INV_GAMMA1 INV_GAMMA2 NORMAL UNIFORM EPS PDF FIG DR NONE PRIOR DIRICHLET MFS RESIDUAL
%token PRIOR_VARIANCE HESSIAN IDENTITY_MATRIX
%token GSIG2_LMDM Q_DIAG FLAT_PRIOR NCSK NSTD WEIBULL WEIBULL_PDF %token GSIG2_LMDM Q_DIAG FLAT_PRIOR NCSK NSTD WEIBULL WEIBULL_PDF
%token INDXPARR INDXOVR INDXAP APBAND INDXIMF INDXFORE FOREBAND INDXGFOREHAT INDXGIMFHAT %token INDXPARR INDXOVR INDXAP APBAND INDXIMF INDXFORE FOREBAND INDXGFOREHAT INDXGIMFHAT
%token INDXESTIMA INDXGDLS EQ_MS FILTER_COVARIANCE UPDATED_COVARIANCE FILTER_DECOMPOSITION SMOOTHED_STATE_UNCERTAINTY SMOOTHER_REDUX %token INDXESTIMA INDXGDLS EQ_MS FILTER_COVARIANCE UPDATED_COVARIANCE FILTER_DECOMPOSITION SMOOTHED_STATE_UNCERTAINTY SMOOTHER_REDUX
...@@ -212,14 +218,17 @@ str_tolower(string s) ...@@ -212,14 +218,17 @@ str_tolower(string s)
%token FSOLVE_OPTIONS %token FSOLVE_OPTIONS
%token ENDVAL_STEADY STEADY_SOLVE_ALGO STEADY_MAXIT STEADY_TOLF STEADY_TOLX STEADY_MARKOWITZ %token ENDVAL_STEADY STEADY_SOLVE_ALGO STEADY_MAXIT STEADY_TOLF STEADY_TOLX STEADY_MARKOWITZ
%token HOMOTOPY_MAX_COMPLETION_SHARE HOMOTOPY_MIN_STEP_SIZE HOMOTOPY_INITIAL_STEP_SIZE HOMOTOPY_STEP_SIZE_INCREASE_SUCCESS_COUNT %token HOMOTOPY_MAX_COMPLETION_SHARE HOMOTOPY_MIN_STEP_SIZE HOMOTOPY_INITIAL_STEP_SIZE HOMOTOPY_STEP_SIZE_INCREASE_SUCCESS_COUNT
%token HOMOTOPY_LINEARIZATION_FALLBACK HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK FROM_INITVAL_TO_ENDVAL %token HOMOTOPY_LINEARIZATION_FALLBACK HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK HOMOTOPY_EXCLUDE_VAREXO FROM_INITVAL_TO_ENDVAL
%token STATIC_MFS RELATIVE_TO_INITVAL %token STATIC_MFS RELATIVE_TO_INITVAL MATCHED_IRFS MATCHED_IRFS_WEIGHTS WEIGHTS PERPENDICULAR
%token HETEROGENEITY HETEROGENEITY_DIMENSION SUM PERFECT_FORESIGHT_CONTROLLED_PATHS EXOGENIZE ENDOGENIZE
%token PRECONDITIONER UMFITER ITERSTACK ILU ITER_TOL ITER_MAXIT GMRES_RESTART ITERSTACK_MAXLU ITERSTACK_NPERIODS ITERSTACK_NLU ITERSTACK_RELU
CHECK_JACOBIAN_SINGULARITY
%token <vector<string>> SYMBOL_VEC %token <vector<string>> SYMBOL_VEC
%type <expr_t> expression expression_or_empty %type <expr_t> expression expression_or_empty
%type <expr_t> equation hand_side %type <expr_t> equation hand_side
%type <string> non_negative_number signed_number signed_integer date_str %type <string> non_negative_number signed_number signed_integer
%type <string> filename symbol namespace_qualified_filename namespace_qualified_symbol %type <string> filename symbol namespace_qualified_filename namespace_qualified_symbol
%type <string> date_expr signed_inf signed_number_w_inf range %type <string> date_expr signed_inf signed_number_w_inf range
%type <string> integer_range signed_integer_range boolean %type <string> integer_range signed_integer_range boolean
...@@ -234,21 +243,31 @@ str_tolower(string s) ...@@ -234,21 +243,31 @@ str_tolower(string s)
%type <vector<int>> vec_int_elem vec_int_1 vec_int vec_int_number %type <vector<int>> vec_int_elem vec_int_1 vec_int vec_int_number
%type <PriorDistributions> prior_pdf prior_distribution %type <PriorDistributions> prior_pdf prior_distribution
%type <pair<expr_t,expr_t>> calibration_range %type <pair<expr_t,expr_t>> calibration_range
%type <pair<string,string>> partition_elem subsamples_eq_opt integer_range_w_inf tag_pair %type <pair<string,string>> partition_elem subsamples_eq_opt integer_range_w_inf tag_pair matched_irfs_elem_var_varexo
%type <vector<pair<string,string>>> partition partition_1 symbol_list_with_tex %type <vector<pair<string,string>>> partition partition_1 symbol_list_with_tex
%type <vector<map<string, string>>> tag_pair_list_for_selection %type <vector<map<string, string>>> tag_pair_list_for_selection
%type <map<string, string>> tag_pair_list %type <map<string, string>> tag_pair_list
%type <tuple<string,string,string,string>> prior_eq_opt options_eq_opt %type <tuple<string,string,string,string>> prior_eq_opt options_eq_opt
%type <vector<pair<int, int>>> period_list %type <AbstractShocksStatement::period_range_t> period_range
%type <vector<expr_t>> matched_moments_list value_list %type <vector<AbstractShocksStatement::period_range_t>> period_list
%type <vector<expr_t>> matched_moments_list value_list ramsey_constraints_list
%type <tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> occbin_constraints_regime %type <tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> occbin_constraints_regime
%type <vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>>> occbin_constraints_regimes_list %type <vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>>> occbin_constraints_regimes_list
%type <map<string, expr_t>> occbin_constraints_regime_options_list %type <map<string, expr_t>> occbin_constraints_regime_options_list
%type <pair<string, expr_t>> occbin_constraints_regime_option %type <pair<string, expr_t>> occbin_constraints_regime_option
%type <PacTargetKind> pac_target_kind %type <PacTargetKind> pac_target_kind
%type <vector<tuple<string, string, vector<pair<string, string>>>>> symbol_list_with_tex_and_partition %type <vector<tuple<string, string, vector<pair<string, string>>>>> symbol_list_with_tex_and_partition
%type <map<string, variant<bool, string>>> mshocks_options_list %type <variant<int, string>> integer_or_date
%type <pair<string, variant<bool, string>>> mshocks_option %type <map<string, variant<bool, variant<int, string>>>> mshocks_options_list
%type <pair<string, variant<bool, variant<int, string>>>> mshocks_option
%type <pair<vector<expr_t>, vector<expr_t>>> matched_irfs_elem_values_weights
%type <pair<pair<string, string>, vector<tuple<int, int, expr_t, expr_t>>>> matched_irfs_elem
%type <map<pair<string, string>, vector<tuple<int, int, expr_t, expr_t>>>> matched_irfs_list
%type <tuple<string, string, string>> matched_irfs_weights_elem_var_varexo
%type <pair<tuple<string, string, string, string, string, string>, expr_t>> matched_irfs_weights_elem
%type <map<tuple<string, string, string, string, string, string>, expr_t>> matched_irfs_weights_list
%type <tuple<string, vector<AbstractShocksStatement::period_range_t>, vector<expr_t>, string>> perfect_foresight_controlled_paths_elem
%type <vector<tuple<string, vector<AbstractShocksStatement::period_range_t>, vector<expr_t>, string>>> perfect_foresight_controlled_paths_list
%% %%
%start statement_list; %start statement_list;
...@@ -264,6 +283,7 @@ statement : parameters ...@@ -264,6 +283,7 @@ statement : parameters
| predetermined_variables | predetermined_variables
| model_local_variable | model_local_variable
| change_type | change_type
| heterogeneity_dimension
| model | model
| initval | initval
| initval_file | initval_file
...@@ -324,7 +344,7 @@ statement : parameters ...@@ -324,7 +344,7 @@ statement : parameters
| bvar_forecast | bvar_forecast
| bvar_irf | bvar_irf
| sbvar | sbvar
| dynare_sensitivity | sensitivity
| homotopy_setup | homotopy_setup
| forecast | forecast
| load_params_and_steady_state | load_params_and_steady_state
...@@ -369,6 +389,7 @@ statement : parameters ...@@ -369,6 +389,7 @@ statement : parameters
| perfect_foresight_solver | perfect_foresight_solver
| perfect_foresight_with_expectation_errors_setup | perfect_foresight_with_expectation_errors_setup
| perfect_foresight_with_expectation_errors_solver | perfect_foresight_with_expectation_errors_solver
| perfect_foresight_controlled_paths
| prior_function | prior_function
| posterior_function | posterior_function
| method_of_moments | method_of_moments
...@@ -384,6 +405,8 @@ statement : parameters ...@@ -384,6 +405,8 @@ statement : parameters
| var_remove | var_remove
| pac_target_info | pac_target_info
| resid | resid
| matched_irfs
| matched_irfs_weights
; ;
dsample : DSAMPLE INT_NUMBER ';' dsample : DSAMPLE INT_NUMBER ';'
...@@ -521,9 +544,9 @@ log_trend_var : LOG_TREND_VAR '(' LOG_GROWTH_FACTOR EQUAL { driver.begin_model() ...@@ -521,9 +544,9 @@ log_trend_var : LOG_TREND_VAR '(' LOG_GROWTH_FACTOR EQUAL { driver.begin_model()
; ;
var : VAR symbol_list_with_tex_and_partition ';' var : VAR symbol_list_with_tex_and_partition ';'
{ driver.var($2, false); } { driver.var($2, {}, false); }
| VAR '(' LOG ')' symbol_list_with_tex_and_partition ';' | VAR '(' LOG ')' symbol_list_with_tex_and_partition ';'
{ driver.var($5, true); } { driver.var($5, {}, true); }
| VAR '(' DEFLATOR EQUAL { driver.begin_model(); } hand_side ')' symbol_list_with_tex_and_partition ';' | VAR '(' DEFLATOR EQUAL { driver.begin_model(); } hand_side ')' symbol_list_with_tex_and_partition ';'
{ driver.end_nonstationary_var(false, $6, $8, false); } { driver.end_nonstationary_var(false, $6, $8, false); }
| VAR '(' LOG COMMA DEFLATOR EQUAL { driver.begin_model(); } hand_side ')' symbol_list_with_tex_and_partition ';' | VAR '(' LOG COMMA DEFLATOR EQUAL { driver.begin_model(); } hand_side ')' symbol_list_with_tex_and_partition ';'
...@@ -532,6 +555,8 @@ var : VAR symbol_list_with_tex_and_partition ';' ...@@ -532,6 +555,8 @@ var : VAR symbol_list_with_tex_and_partition ';'
{ driver.end_nonstationary_var(true, $6, $8, false); } { driver.end_nonstationary_var(true, $6, $8, false); }
/* The case LOG + LOG_DEFLATOR is omitted, because it does not make much sense /* The case LOG + LOG_DEFLATOR is omitted, because it does not make much sense
from an economic point of view (amounts to taking the log two times) */ from an economic point of view (amounts to taking the log two times) */
| VAR '(' HETEROGENEITY EQUAL symbol ')' symbol_list_with_tex_and_partition ';'
{ driver.var($7, $5, false); }
; ;
var_remove : VAR_REMOVE symbol_list ';' { driver.var_remove($2); }; var_remove : VAR_REMOVE symbol_list ';' { driver.var_remove($2); };
...@@ -605,7 +630,9 @@ var_expectation_model_option : VARIABLE EQUAL symbol ...@@ -605,7 +630,9 @@ var_expectation_model_option : VARIABLE EQUAL symbol
; ;
varexo : VAREXO symbol_list_with_tex_and_partition ';' varexo : VAREXO symbol_list_with_tex_and_partition ';'
{ driver.varexo($2); } { driver.varexo($2, {}); }
| VAREXO '(' HETEROGENEITY EQUAL symbol ')' symbol_list_with_tex_and_partition ';'
{ driver.varexo($7, $5); }
; ;
varexo_det : VAREXO_DET symbol_list_with_tex_and_partition ';' varexo_det : VAREXO_DET symbol_list_with_tex_and_partition ';'
...@@ -617,7 +644,9 @@ predetermined_variables : PREDETERMINED_VARIABLES symbol_list ';' ...@@ -617,7 +644,9 @@ predetermined_variables : PREDETERMINED_VARIABLES symbol_list ';'
; ;
parameters : PARAMETERS symbol_list_with_tex_and_partition ';' parameters : PARAMETERS symbol_list_with_tex_and_partition ';'
{ driver.parameters($2); } { driver.parameters($2, {}); }
| PARAMETERS '(' HETEROGENEITY EQUAL symbol ')' symbol_list_with_tex_and_partition ';'
{ driver.parameters($7, $5); }
; ;
model_local_variable : MODEL_LOCAL_VARIABLE symbol_list_with_tex ';' model_local_variable : MODEL_LOCAL_VARIABLE symbol_list_with_tex ';'
...@@ -638,6 +667,10 @@ change_type_arg : PARAMETERS ...@@ -638,6 +667,10 @@ change_type_arg : PARAMETERS
{ $$ = SymbolType::exogenousDet; } { $$ = SymbolType::exogenousDet; }
; ;
heterogeneity_dimension : HETEROGENEITY_DIMENSION symbol_list ';'
{ driver.heterogeneity_dimension($2); }
;
init_param : symbol EQUAL expression ';' { driver.init_param($1, $3); }; init_param : symbol EQUAL expression ';' { driver.init_param($1, $3); };
expression : '(' expression ')' expression : '(' expression ')'
...@@ -774,20 +807,24 @@ h_options: o_filename ...@@ -774,20 +807,24 @@ h_options: o_filename
| o_first_obs | o_first_obs
| o_data_first_obs | o_data_first_obs
| o_first_simulation_period | o_first_simulation_period
| o_date_first_simulation_period
| o_last_simulation_period | o_last_simulation_period
| o_date_last_simulation_period
| o_last_obs | o_last_obs
| o_data_last_obs | o_data_last_obs
| o_nobs | o_nobs
| o_series | o_series
; ;
integer_or_date : INT_NUMBER
{ $$.emplace<int>(stoi($1)); }
| date_expr
{ $$.emplace<string>($1); }
;
endval : ENDVAL ';' endval_list END ';' endval : ENDVAL ';' endval_list END ';'
{ driver.end_endval(false); } { driver.end_endval(false); }
| ENDVAL '(' ALL_VALUES_REQUIRED ')' ';' endval_list END ';' | ENDVAL '(' ALL_VALUES_REQUIRED ')' ';' endval_list END ';'
{ driver.end_endval(true); } { driver.end_endval(true); }
| ENDVAL '(' LEARNT_IN EQUAL INT_NUMBER ')' ';' endval_list END ';' | ENDVAL '(' LEARNT_IN EQUAL integer_or_date ')' ';' endval_list END ';'
{ driver.end_endval_learnt_in($5); } { driver.end_endval_learnt_in($5); }
; ;
...@@ -985,6 +1022,8 @@ model : MODEL ';' { driver.begin_model(); } ...@@ -985,6 +1022,8 @@ model : MODEL ';' { driver.begin_model(); }
equation_list END ';' { driver.end_model(); } equation_list END ';' { driver.end_model(); }
| MODEL '(' model_options_list ')' ';' { driver.begin_model(); } | MODEL '(' model_options_list ')' ';' { driver.begin_model(); }
equation_list END ';' { driver.end_model(); } equation_list END ';' { driver.end_model(); }
| MODEL '(' HETEROGENEITY EQUAL symbol ')' { driver.begin_heterogeneous_model($5); }';'
equation_list END ';' { driver.end_model(); }
; ;
equation_list : equation_list equation equation_list : equation_list equation
...@@ -1001,6 +1040,14 @@ equation : hand_side EQUAL hand_side ';' ...@@ -1001,6 +1040,14 @@ equation : hand_side EQUAL hand_side ';'
{ $$ = driver.add_model_equal($4, $6, $2); } { $$ = driver.add_model_equal($4, $6, $2); }
| '[' tag_pair_list ']' hand_side ';' | '[' tag_pair_list ']' hand_side ';'
{ $$ = driver.add_model_equal_with_zero_rhs($4, $2); } { $$ = driver.add_model_equal_with_zero_rhs($4, $2); }
| hand_side EQUAL hand_side PERPENDICULAR hand_side ';'
{ $$ = driver.add_model_equal($1, $3, {}, $5); }
| hand_side PERPENDICULAR hand_side ';'
{ $$ = driver.add_model_equal_with_zero_rhs($1, {}, $3); }
| '[' tag_pair_list ']' hand_side EQUAL hand_side PERPENDICULAR hand_side ';'
{ $$ = driver.add_model_equal($4, $6, $2, $8); }
| '[' tag_pair_list ']' hand_side PERPENDICULAR hand_side ';'
{ $$ = driver.add_model_equal_with_zero_rhs($4, $2, $6); }
; ;
tag_pair_list : tag_pair_list COMMA tag_pair tag_pair_list : tag_pair_list COMMA tag_pair
...@@ -1134,6 +1181,8 @@ hand_side : '(' hand_side ')' ...@@ -1134,6 +1181,8 @@ hand_side : '(' hand_side ')'
{ $$ = driver.add_erfc($3); } { $$ = driver.add_erfc($3); }
| STEADY_STATE '(' hand_side ')' | STEADY_STATE '(' hand_side ')'
{ $$ = driver.add_steady_state($3); } { $$ = driver.add_steady_state($3); }
| SUM '(' hand_side ')'
{ $$ = driver.add_sum($3); }
; ;
comma_hand_side : hand_side comma_hand_side : hand_side
...@@ -1184,9 +1233,15 @@ shocks : SHOCKS ';' shock_list END ';' { driver.end_shocks(false); } ...@@ -1184,9 +1233,15 @@ shocks : SHOCKS ';' shock_list END ';' { driver.end_shocks(false); }
| SHOCKS '(' SURPRISE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(false); } | SHOCKS '(' SURPRISE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(false); }
| SHOCKS '(' SURPRISE COMMA OVERWRITE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(true); } | SHOCKS '(' SURPRISE COMMA OVERWRITE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(true); }
| SHOCKS '(' OVERWRITE COMMA SURPRISE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(true); } | SHOCKS '(' OVERWRITE COMMA SURPRISE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(true); }
| SHOCKS '(' LEARNT_IN EQUAL INT_NUMBER ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($5, false); } | SHOCKS '(' LEARNT_IN EQUAL integer_or_date ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($5, false); }
| SHOCKS '(' LEARNT_IN EQUAL INT_NUMBER COMMA OVERWRITE ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($5, true); } | SHOCKS '(' LEARNT_IN EQUAL integer_or_date COMMA OVERWRITE ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($5, true); }
| SHOCKS '(' OVERWRITE COMMA LEARNT_IN EQUAL INT_NUMBER ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($7, true); } | SHOCKS '(' OVERWRITE COMMA LEARNT_IN EQUAL integer_or_date ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($7, true); }
| SHOCKS '(' HETEROGENEITY EQUAL symbol ')' ';' stoch_shock_list END ';'
{ driver.end_heterogeneous_shocks($5, false); }
| SHOCKS '(' HETEROGENEITY EQUAL symbol COMMA OVERWRITE ')' ';' stoch_shock_list END ';'
{ driver.end_heterogeneous_shocks($5, true); }
| SHOCKS '(' OVERWRITE COMMA HETEROGENEITY EQUAL symbol ')' ';' stoch_shock_list END ';'
{ driver.end_heterogeneous_shocks($7, true); }
; ;
shock_list : shock_list shock_elem shock_list : shock_list shock_elem
...@@ -1194,7 +1249,10 @@ shock_list : shock_list shock_elem ...@@ -1194,7 +1249,10 @@ shock_list : shock_list shock_elem
; ;
shock_elem : det_shock_elem shock_elem : det_shock_elem
| VAR symbol ';' STDERR expression ';' | stoch_shock_elem
;
stoch_shock_elem : VAR symbol ';' STDERR expression ';'
{ driver.add_stderr_shock($2, $5); } { driver.add_stderr_shock($2, $5); }
| VAR symbol EQUAL expression ';' | VAR symbol EQUAL expression ';'
{ driver.add_var_shock($2, $4); } { driver.add_var_shock($2, $4); }
...@@ -1204,6 +1262,10 @@ shock_elem : det_shock_elem ...@@ -1204,6 +1262,10 @@ shock_elem : det_shock_elem
{ driver.add_correl_shock($2, $4, $6); } { driver.add_correl_shock($2, $4, $6); }
; ;
stoch_shock_list : stoch_shock_list stoch_shock_elem
| stoch_shock_elem
;
det_shock_elem : VAR symbol ';' PERIODS period_list ';' VALUES value_list ';' det_shock_elem : VAR symbol ';' PERIODS period_list ';' VALUES value_list ';'
{ driver.add_det_shock($2, $5, $8, ParsingDriver::DetShockType::standard); } { driver.add_det_shock($2, $5, $8, ParsingDriver::DetShockType::standard); }
| VAR symbol ';' PERIODS period_list ';' ADD value_list ';' | VAR symbol ';' PERIODS period_list ';' ADD value_list ';'
...@@ -1319,11 +1381,13 @@ mshocks : MSHOCKS ';' mshock_list END ';' ...@@ -1319,11 +1381,13 @@ mshocks : MSHOCKS ';' mshock_list END ';'
{ driver.end_mshocks(false, false); } { driver.end_mshocks(false, false); }
| MSHOCKS '(' mshocks_options_list ')' ';' mshock_list END ';' | MSHOCKS '(' mshocks_options_list ')' ';' mshock_list END ';'
{ {
/* NB: the following relies of the fact that bool is the first /* NB: the following relies on the fact that bool is the first
alternative in the variant, so that default initialization of the alternative in the variant, so that default initialization of the
variant by the [] operator will give false */ variant by the [] operator will give false */
if ($3.contains("learnt_in")) if ($3.contains("learnt_in"))
driver.end_mshocks_learnt_in(get<string>($3.at("learnt_in")), get<bool>($3["overwrite"]), get<bool>($3["relative_to_initval"])); driver.end_mshocks_learnt_in(get<variant<int, string>>($3.at("learnt_in")),
get<bool>($3["overwrite"]),
get<bool>($3["relative_to_initval"]));
else else
driver.end_mshocks(get<bool>($3["overwrite"]), get<bool>($3["relative_to_initval"])); driver.end_mshocks(get<bool>($3["overwrite"]), get<bool>($3["relative_to_initval"]));
} }
...@@ -1342,7 +1406,7 @@ mshocks_options_list : mshocks_option ...@@ -1342,7 +1406,7 @@ mshocks_options_list : mshocks_option
mshocks_option : OVERWRITE mshocks_option : OVERWRITE
{ $$ = {"overwrite", true}; } { $$ = {"overwrite", true}; }
| LEARNT_IN EQUAL INT_NUMBER | LEARNT_IN EQUAL integer_or_date
{ $$ = {"learnt_in", $3}; } { $$ = {"learnt_in", $3}; }
| RELATIVE_TO_INITVAL | RELATIVE_TO_INITVAL
{ $$ = {"relative_to_initval", true}; } { $$ = {"relative_to_initval", true}; }
...@@ -1352,46 +1416,36 @@ mshock_list : mshock_list det_shock_elem ...@@ -1352,46 +1416,36 @@ mshock_list : mshock_list det_shock_elem
| det_shock_elem | det_shock_elem
; ;
period_list : period_list COMMA INT_NUMBER period_list : period_range
{ { $$ = { $1 }; }
$$ = $1; | period_list period_range
int p = stoi($3);
$$.emplace_back(p, p);
}
| period_list INT_NUMBER
{ {
$$ = $1; $$ = $1;
int p = stoi($2); $$.emplace_back($2);
$$.emplace_back(p, p);
} }
| period_list COMMA INT_NUMBER ':' INT_NUMBER | period_list COMMA period_range
{ {
$$ = $1; $$ = $1;
int p1 = stoi($3), p2 = stoi($5); $$.emplace_back($3);
if (p1 > p2)
driver.error("Can't have first period index greater than second index in range specification");
$$.emplace_back(p1, p2);
} }
| period_list INT_NUMBER ':' INT_NUMBER ;
period_range : INT_NUMBER
{ {
$$ = $1; int p = stoi($1);
int p1 = stoi($2), p2 = stoi($4); $$.emplace<pair<int, int>>(p, p);
if (p1 > p2)
driver.error("Can't have first period index greater than second index in range specification");
$$.emplace_back(p1, p2);
} }
| INT_NUMBER ':' INT_NUMBER | INT_NUMBER ':' INT_NUMBER
{ {
int p1 = stoi($1), p2 = stoi($3); int p1 = stoi($1), p2 = stoi($3);
if (p1 > p2) if (p1 > p2)
driver.error("Can't have first period index greater than second index in range specification"); driver.error("Can't have first period index greater than second index in range specification");
$$ = { { p1, p2 } }; $$.emplace<pair<int, int>>(p1, p2);
}
| INT_NUMBER
{
int p = stoi($1);
$$ = { { p, p } };
} }
| date_expr
{ $$.emplace<pair<string, string>>($1, $1); }
| date_expr ':' date_expr
{ $$.emplace<pair<string, string>>($1, $3); }
; ;
value_list : value_list COMMA '(' expression ')' value_list : value_list COMMA '(' expression ')'
...@@ -1409,22 +1463,22 @@ value_list : value_list COMMA '(' expression ')' ...@@ -1409,22 +1463,22 @@ value_list : value_list COMMA '(' expression ')'
| value_list COMMA signed_number | value_list COMMA signed_number
{ {
$$ = $1; $$ = $1;
$$.push_back($3.at(0) == '-' ? $$.push_back($3.at(0) == '-'
driver.add_uminus(driver.add_non_negative_constant($3.substr(1))) : ? driver.add_uminus(driver.add_non_negative_constant($3.substr(1)))
driver.add_non_negative_constant($3)); : driver.add_non_negative_constant($3));
} }
| value_list signed_number | value_list signed_number
{ {
$$ = $1; $$ = $1;
$$.push_back($2.at(0) == '-' ? $$.push_back($2.at(0) == '-'
driver.add_uminus(driver.add_non_negative_constant($2.substr(1))) : ? driver.add_uminus(driver.add_non_negative_constant($2.substr(1)))
driver.add_non_negative_constant($2)); : driver.add_non_negative_constant($2));
} }
| signed_number | signed_number
{ {
$$ = { $1.at(0) == '-' ? $$ = {$1.at(0) == '-'
driver.add_uminus(driver.add_non_negative_constant($1.substr(1))) : ? driver.add_uminus(driver.add_non_negative_constant($1.substr(1)))
driver.add_non_negative_constant($1) }; : driver.add_non_negative_constant($1)};
} }
; ;
...@@ -1445,9 +1499,11 @@ steady_options : o_solve_algo ...@@ -1445,9 +1499,11 @@ steady_options : o_solve_algo
| o_markowitz | o_markowitz
| o_steady_maxit | o_steady_maxit
| o_nocheck | o_nocheck
| o_noprint
| o_steady_tolf | o_steady_tolf
| o_steady_tolx | o_steady_tolx
| o_fsolve_options | o_fsolve_options
| o_non_zero
; ;
check : CHECK ';' check : CHECK ';'
...@@ -1492,6 +1548,8 @@ perfect_foresight_setup_options_list : perfect_foresight_setup_options_list COMM ...@@ -1492,6 +1548,8 @@ perfect_foresight_setup_options_list : perfect_foresight_setup_options_list COMM
perfect_foresight_setup_options : o_periods perfect_foresight_setup_options : o_periods
| o_datafile | o_datafile
| o_endval_steady | o_endval_steady
| o_pf_first_simulation_period
| o_pf_last_simulation_period
; ;
perfect_foresight_solver : PERFECT_FORESIGHT_SOLVER ';' perfect_foresight_solver : PERFECT_FORESIGHT_SOLVER ';'
...@@ -1529,6 +1587,16 @@ perfect_foresight_solver_options : o_stack_solve_algo ...@@ -1529,6 +1587,16 @@ perfect_foresight_solver_options : o_stack_solve_algo
| o_homotopy_step_size_increase_success_count | o_homotopy_step_size_increase_success_count
| o_homotopy_linearization_fallback | o_homotopy_linearization_fallback
| o_homotopy_marginal_linearization_fallback | o_homotopy_marginal_linearization_fallback
| o_homotopy_exclude_varexo
| o_preconditioner
| o_iter_tol
| o_iter_maxit
| o_gmres_restart
| o_iterstack_maxlu
| o_iterstack_nperiods
| o_iterstack_nlu
| o_iterstack_relu
| o_check_jacobian_singularity
; ;
perfect_foresight_with_expectation_errors_setup : PERFECT_FORESIGHT_WITH_EXPECTATION_ERRORS_SETUP ';' perfect_foresight_with_expectation_errors_setup : PERFECT_FORESIGHT_WITH_EXPECTATION_ERRORS_SETUP ';'
...@@ -1543,6 +1611,8 @@ perfect_foresight_with_expectation_errors_setup_options_list : perfect_foresight ...@@ -1543,6 +1611,8 @@ perfect_foresight_with_expectation_errors_setup_options_list : perfect_foresight
perfect_foresight_with_expectation_errors_setup_options : o_periods perfect_foresight_with_expectation_errors_setup_options : o_periods
| o_datafile | o_datafile
| o_pf_first_simulation_period
| o_pf_last_simulation_period
; ;
perfect_foresight_with_expectation_errors_solver : PERFECT_FORESIGHT_WITH_EXPECTATION_ERRORS_SOLVER ';' perfect_foresight_with_expectation_errors_solver : PERFECT_FORESIGHT_WITH_EXPECTATION_ERRORS_SOLVER ';'
...@@ -1559,6 +1629,31 @@ perfect_foresight_with_expectation_errors_solver_options : o_pfwee_constant_simu ...@@ -1559,6 +1629,31 @@ perfect_foresight_with_expectation_errors_solver_options : o_pfwee_constant_simu
| perfect_foresight_solver_options | perfect_foresight_solver_options
; ;
perfect_foresight_controlled_paths : PERFECT_FORESIGHT_CONTROLLED_PATHS ';' perfect_foresight_controlled_paths_list END ';'
{ driver.perfect_foresight_controlled_paths($3, 1); }
| PERFECT_FORESIGHT_CONTROLLED_PATHS '(' LEARNT_IN EQUAL integer_or_date ')' ';' perfect_foresight_controlled_paths_list END ';'
{ driver.perfect_foresight_controlled_paths($8, $5); }
;
perfect_foresight_controlled_paths_list : perfect_foresight_controlled_paths_list perfect_foresight_controlled_paths_elem
{
$$ = $1;
$$.push_back($2);
}
| perfect_foresight_controlled_paths_elem
{ $$ = { $1 }; }
;
perfect_foresight_controlled_paths_elem : EXOGENIZE symbol ';' PERIODS period_list ';' VALUES value_list ';' ENDOGENIZE symbol ';'
{
driver.check_symbol_is_endogenous($2);
driver.check_symbol_is_exogenous($11, false);
if ($5.size() != $8.size())
driver.error("The number of periods is different from the number of values");
$$ = { $2, $5, $8, $11};
}
;
method_of_moments : METHOD_OF_MOMENTS ';' method_of_moments : METHOD_OF_MOMENTS ';'
{ driver.method_of_moments(); } { driver.method_of_moments(); }
| METHOD_OF_MOMENTS '(' method_of_moments_options_list ')' ';' | METHOD_OF_MOMENTS '(' method_of_moments_options_list ')' ';'
...@@ -1581,6 +1676,7 @@ method_of_moments_option : o_add_tiny_number_to_cholesky ...@@ -1581,6 +1676,7 @@ method_of_moments_option : o_add_tiny_number_to_cholesky
| o_datafile | o_datafile
| o_dirname | o_dirname
| o_dr | o_dr
| o_dr_cycle_reduction_maxiter
| o_dr_cycle_reduction_tol | o_dr_cycle_reduction_tol
| o_dr_logarithmic_reduction_maxiter | o_dr_logarithmic_reduction_maxiter
| o_dr_logarithmic_reduction_tol | o_dr_logarithmic_reduction_tol
...@@ -1650,8 +1746,6 @@ method_of_moments_option : o_add_tiny_number_to_cholesky ...@@ -1650,8 +1746,6 @@ method_of_moments_option : o_add_tiny_number_to_cholesky
| o_simulation_method | o_simulation_method
| o_simulation_multiple | o_simulation_multiple
| o_sub_draws | o_sub_draws
| o_sylvester
| o_sylvester_fixed_point_tol
| o_taper_steps | o_taper_steps
| o_tex | o_tex
| o_use_penalized_objective_for_hessian | o_use_penalized_objective_for_hessian
...@@ -1758,10 +1852,9 @@ stoch_simul_primary_options : o_solve_algo ...@@ -1758,10 +1852,9 @@ stoch_simul_primary_options : o_solve_algo
| o_conditional_variance_decomposition | o_conditional_variance_decomposition
| o_k_order_solver | o_k_order_solver
| o_pruning | o_pruning
| o_sylvester
| o_sylvester_fixed_point_tol
| o_dr | o_dr
| o_dr_cycle_reduction_tol | o_dr_cycle_reduction_tol
| o_dr_cycle_reduction_maxiter
| o_dr_logarithmic_reduction_tol | o_dr_logarithmic_reduction_tol
| o_dr_logarithmic_reduction_maxiter | o_dr_logarithmic_reduction_maxiter
| o_irf_plot_threshold | o_irf_plot_threshold
...@@ -2044,9 +2137,8 @@ prior_pdf : BETA_PDF ...@@ -2044,9 +2137,8 @@ prior_pdf : BETA_PDF
{ $$ = PriorDistributions::weibull; } { $$ = PriorDistributions::weibull; }
; ;
date_str : DATES date_expr : DATE
{ $$ = "dates('" + $1 + "')"; }
date_expr : date_str
| date_expr PLUS INT_NUMBER | date_expr PLUS INT_NUMBER
{ $$ = $1 + '+' + $3; } { $$ = $1 + '+' + $3; }
; ;
...@@ -2293,13 +2385,12 @@ estimation_options : o_datafile ...@@ -2293,13 +2385,12 @@ estimation_options : o_datafile
| o_cova_compute | o_cova_compute
| o_irf_shocks | o_irf_shocks
| o_sub_draws | o_sub_draws
| o_sylvester
| o_sylvester_fixed_point_tol
| o_lyapunov | o_lyapunov
| o_lyapunov_fixed_point_tol | o_lyapunov_fixed_point_tol
| o_lyapunov_doubling_tol | o_lyapunov_doubling_tol
| o_dr | o_dr
| o_dr_cycle_reduction_tol | o_dr_cycle_reduction_tol
| o_dr_cycle_reduction_maxiter
| o_dr_logarithmic_reduction_tol | o_dr_logarithmic_reduction_tol
| o_dr_logarithmic_reduction_maxiter | o_dr_logarithmic_reduction_maxiter
| o_analytic_derivation | o_analytic_derivation
...@@ -2422,13 +2513,17 @@ trend_list : trend_list trend_element ...@@ -2422,13 +2513,17 @@ trend_list : trend_list trend_element
trend_element : symbol '(' expression ')' ';' { driver.set_trend_element($1, $3); }; trend_element : symbol '(' expression ')' ';' { driver.set_trend_element($1, $3); };
filter_initial_state : FILTER_INITIAL_STATE ';' filter_initial_state_list END ';' { driver.set_filter_initial_state(); }; filter_initial_state : FILTER_INITIAL_STATE ';' filter_initial_state_list END ';'
{ driver.set_filter_initial_state(); }
;
filter_initial_state_list : filter_initial_state_list filter_initial_state_element filter_initial_state_list : filter_initial_state_list filter_initial_state_element
| filter_initial_state_element | filter_initial_state_element
; ;
filter_initial_state_element : symbol '(' signed_integer ')' EQUAL expression ';' { driver.set_filter_initial_state_element($1, $3, $6); }; filter_initial_state_element : symbol '(' signed_integer ')' EQUAL expression ';'
{ driver.set_filter_initial_state_element($1, $3, $6); }
;
unit_root_vars : UNIT_ROOT_VARS symbol_list ';' { driver.set_unit_root_vars(); }; unit_root_vars : UNIT_ROOT_VARS symbol_list ';' { driver.set_unit_root_vars(); };
...@@ -2597,22 +2692,19 @@ ramsey_policy : RAMSEY_POLICY ';' ...@@ -2597,22 +2692,19 @@ ramsey_policy : RAMSEY_POLICY ';'
{ driver.ramsey_policy($5); } { driver.ramsey_policy($5); }
; ;
ramsey_constraints : RAMSEY_CONSTRAINTS ';' ramsey_constraints_list END ';' ramsey_constraints : RAMSEY_CONSTRAINTS ';'
{ driver.add_ramsey_constraints_statement(); } { driver.begin_ramsey_constraints(); }
; ramsey_constraints_list END ';'
{ driver.end_ramsey_constraints($4); }
ramsey_constraints_list : ramsey_constraints_list ramsey_constraint
| ramsey_constraint
; ;
ramsey_constraint : NAME LESS expression ';' ramsey_constraints_list : ramsey_constraints_list hand_side ';'
{ driver.ramsey_constraint_add_less($1,$3); } {
| NAME GREATER expression ';' $$ = $1;
{ driver.ramsey_constraint_add_greater($1,$3); } $$.push_back($2);
| NAME LESS_EQUAL expression ';' }
{ driver.ramsey_constraint_add_less_equal($1,$3); } | hand_side ';'
| NAME GREATER_EQUAL expression ';' { $$ = { $1 }; }
{ driver.ramsey_constraint_add_greater_equal($1,$3); }
; ;
evaluate_planner_objective : EVALUATE_PLANNER_OBJECTIVE ';' evaluate_planner_objective : EVALUATE_PLANNER_OBJECTIVE ';'
...@@ -3117,17 +3209,27 @@ ms_estimation : MS_ESTIMATION ';' ...@@ -3117,17 +3209,27 @@ ms_estimation : MS_ESTIMATION ';'
{ driver.ms_estimation(); } { driver.ms_estimation(); }
; ;
dynare_sensitivity : DYNARE_SENSITIVITY ';' sensitivity : SENSITIVITY ';'
{ driver.dynare_sensitivity(); } { driver.sensitivity(); }
| DYNARE_SENSITIVITY '(' dynare_sensitivity_options_list ')' ';' | SENSITIVITY '(' sensitivity_options_list ')' ';'
{ driver.dynare_sensitivity(); } { driver.sensitivity(); }
| DYNARE_SENSITIVITY ';'
{
driver.warning("The 'dynare_sensitivity' command is deprecated. It has been renamed 'sensitivity'.");
driver.sensitivity();
}
| DYNARE_SENSITIVITY '(' sensitivity_options_list ')' ';'
{
driver.warning("The 'dynare_sensitivity' command is deprecated. It has been renamed 'sensitivity'.");
driver.sensitivity();
}
; ;
dynare_sensitivity_options_list : dynare_sensitivity_option COMMA dynare_sensitivity_options_list sensitivity_options_list : sensitivity_option COMMA sensitivity_options_list
| dynare_sensitivity_option | sensitivity_option
; ;
dynare_sensitivity_option : o_gsa_identification sensitivity_option : o_gsa_identification
| o_gsa_morris | o_gsa_morris
| o_gsa_stab | o_gsa_stab
| o_gsa_redform | o_gsa_redform
...@@ -3336,7 +3438,9 @@ conditional_forecast_paths_shock_list : conditional_forecast_paths_shock_elem ...@@ -3336,7 +3438,9 @@ conditional_forecast_paths_shock_list : conditional_forecast_paths_shock_elem
; ;
conditional_forecast_paths_shock_elem : VAR symbol ';' PERIODS period_list ';' VALUES value_list ';' conditional_forecast_paths_shock_elem : VAR symbol ';' PERIODS period_list ';' VALUES value_list ';'
{ driver.add_det_shock($2, $5, $8, ParsingDriver::DetShockType::conditional_forecast); } { driver.add_det_shock(
$2, $5, $8,
ParsingDriver::DetShockType::conditional_forecast); }
; ;
steady_state_model : STEADY_STATE_MODEL ';' { driver.begin_steady_state_model(); } steady_state_model : STEADY_STATE_MODEL ';' { driver.begin_steady_state_model(); }
...@@ -3434,6 +3538,7 @@ extended_path_option : o_periods ...@@ -3434,6 +3538,7 @@ extended_path_option : o_periods
| o_solver_periods | o_solver_periods
| o_extended_path_order | o_extended_path_order
| o_hybrid | o_hybrid
| o_use_first_order_solution
| o_lmmcp | o_lmmcp
; ;
...@@ -3446,7 +3551,8 @@ calibration_range : '[' expression COMMA expression ']' ...@@ -3446,7 +3551,8 @@ calibration_range : '[' expression COMMA expression ']'
| PLUS | PLUS
{ $$ = {driver.add_non_negative_constant("0"), driver.add_inf_constant()}; } { $$ = {driver.add_non_negative_constant("0"), driver.add_inf_constant()}; }
| MINUS | MINUS
{ $$ = { driver.add_uminus(driver.add_inf_constant()), driver.add_non_negative_constant("0") }; } { $$ = {driver.add_uminus(driver.add_inf_constant()),
driver.add_non_negative_constant("0")}; }
; ;
moment_calibration : MOMENT_CALIBRATION ';' moment_calibration_list END ';' moment_calibration : MOMENT_CALIBRATION ';' moment_calibration_list END ';'
...@@ -3533,6 +3639,116 @@ init2shocks_element : symbol symbol ';' { driver.add_init2shocks($1, $2); } ...@@ -3533,6 +3639,116 @@ init2shocks_element : symbol symbol ';' { driver.add_init2shocks($1, $2); }
| symbol COMMA symbol ';' { driver.add_init2shocks($1, $3); } | symbol COMMA symbol ';' { driver.add_init2shocks($1, $3); }
; ;
matched_irfs : MATCHED_IRFS ';' matched_irfs_list END ';'
{ driver.matched_irfs($3, false); }
| MATCHED_IRFS '(' OVERWRITE ')' ';' matched_irfs_list END ';'
{ driver.matched_irfs($6, true); }
;
matched_irfs_list : matched_irfs_elem
{ $$ = {$1}; }
| matched_irfs_list matched_irfs_elem
{
$$ = $1;
auto [it, success] = $$.insert($2);
if (!success)
driver.error("matched_irfs: the pair endogenous " + $2.first.first + " with exogenous " + $2.first.second + " appears two times");
}
;
matched_irfs_elem : matched_irfs_elem_var_varexo
PERIODS period_list ';'
matched_irfs_elem_values_weights
{
if ($3.size() != $5.first.size())
driver.error("matched_irfs: the 'periods' and 'values' keywords are not followed by the same number of elements");
if ($3.size() != $5.second.size())
driver.error("matched_irfs: the 'periods' and 'values' keywords are not followed by the same number of elements");
vector<tuple<int, int, expr_t, expr_t>> v;
v.reserve($3.size());
for (size_t i {0}; i < $3.size(); i++)
try
{
auto [p1, p2] = get<pair<int, int>>($3[i]);
v.emplace_back(p1, p2, $5.first[i], $5.second[i]);
}
catch (bad_variant_access&)
{
driver.error("matched_irfs: dates are not allowed in the 'periods' keyword");
}
$$ = {$1, v};
}
;
matched_irfs_elem_var_varexo : VAR symbol ';' VAREXO symbol ';'
{
driver.check_symbol_is_endogenous($2);
driver.check_symbol_is_exogenous($5, false);
$$ = {$2, $5};
}
| VAREXO symbol ';' VAR symbol ';'
{
driver.check_symbol_is_endogenous($5);
driver.check_symbol_is_exogenous($2, false);
$$ = {$5, $2};
}
;
matched_irfs_elem_values_weights : VALUES value_list ';'
{
$$ = {$2, vector($2.size(),
driver.add_non_negative_constant("1"))};
}
| VALUES value_list ';' WEIGHTS value_list ';'
{ $$ = {$2, $5}; }
| WEIGHTS value_list ';' VALUES value_list ';'
{ $$ = {$5, $2}; }
;
matched_irfs_weights : MATCHED_IRFS_WEIGHTS ';' matched_irfs_weights_list END ';'
{ driver.matched_irfs_weights($3, false); }
| MATCHED_IRFS_WEIGHTS '(' OVERWRITE ')' ';' matched_irfs_weights_list END ';'
{ driver.matched_irfs_weights($6, true); }
;
matched_irfs_weights_list : matched_irfs_weights_elem
{ $$ = {$1}; }
| matched_irfs_weights_list matched_irfs_weights_elem
{
$$ = $1;
auto [it, success] = $$.insert($2);
if (!success)
driver.error("matched_irfs: the tuple (" + get<0>($2.first)
+ "(" + get<1>($2.first) + ")," + get<2>($2.first)
+ "," + get<3>($2.first) + "(" + get<4>($2.first) + "),"
+ get<5>($2.first) + ") appears two times");
}
;
matched_irfs_weights_elem : matched_irfs_weights_elem_var_varexo COMMA
matched_irfs_weights_elem_var_varexo COMMA
expression ';'
{
$$ = {{get<0>($1), get<1>($1), get<2>($1),
get<0>($3), get<1>($3), get<2>($3)},
$5};
}
;
matched_irfs_weights_elem_var_varexo : symbol '(' INT_NUMBER ')' COMMA symbol
{
driver.check_symbol_is_endogenous($1);
driver.check_symbol_is_exogenous($6, false);
$$ = {$1, $3, $6};
}
| symbol '(' integer_range ')' COMMA symbol
{
driver.check_symbol_is_endogenous($1);
driver.check_symbol_is_exogenous($6, false);
$$ = {$1, $3, $6};
}
;
o_solve_algo : SOLVE_ALGO EQUAL INT_NUMBER { driver.option_num("solve_algo", $3); }; o_solve_algo : SOLVE_ALGO EQUAL INT_NUMBER { driver.option_num("solve_algo", $3); };
o_stack_solve_algo : STACK_SOLVE_ALGO EQUAL INT_NUMBER { driver.option_num("stack_solve_algo", $3); }; o_stack_solve_algo : STACK_SOLVE_ALGO EQUAL INT_NUMBER { driver.option_num("stack_solve_algo", $3); };
o_robust_lin_solve : ROBUST_LIN_SOLVE { driver.option_num("simul.robust_lin_solve", "true"); }; o_robust_lin_solve : ROBUST_LIN_SOLVE { driver.option_num("simul.robust_lin_solve", "true"); };
...@@ -3558,6 +3774,7 @@ o_periods : PERIODS EQUAL INT_NUMBER { driver.option_num("periods", $3); }; ...@@ -3558,6 +3774,7 @@ o_periods : PERIODS EQUAL INT_NUMBER { driver.option_num("periods", $3); };
o_solver_periods : SOLVER_PERIODS EQUAL INT_NUMBER { driver.option_num("ep.periods", $3); }; o_solver_periods : SOLVER_PERIODS EQUAL INT_NUMBER { driver.option_num("ep.periods", $3); };
o_extended_path_order : ORDER EQUAL INT_NUMBER { driver.option_num("ep.stochastic.order", $3); }; o_extended_path_order : ORDER EQUAL INT_NUMBER { driver.option_num("ep.stochastic.order", $3); };
o_hybrid : HYBRID { driver.option_num("ep.stochastic.hybrid_order", "2"); }; o_hybrid : HYBRID { driver.option_num("ep.stochastic.hybrid_order", "2"); };
o_use_first_order_solution : USE_FIRST_ORDER_SOLUTION { driver.option_num("ep.use_first_order_solution_as_initial_guess", "true"); };
o_steady_maxit : MAXIT EQUAL INT_NUMBER { driver.option_num("steady.maxit", $3); }; o_steady_maxit : MAXIT EQUAL INT_NUMBER { driver.option_num("steady.maxit", $3); };
o_simul_maxit : MAXIT EQUAL INT_NUMBER { driver.option_num("simul.maxit", $3); }; o_simul_maxit : MAXIT EQUAL INT_NUMBER { driver.option_num("simul.maxit", $3); };
o_bandpass_filter : BANDPASS_FILTER { driver.option_num("bandpass.indicator", "true"); } o_bandpass_filter : BANDPASS_FILTER { driver.option_num("bandpass.indicator", "true"); }
...@@ -3626,13 +3843,17 @@ o_est_first_obs : FIRST_OBS EQUAL vec_int ...@@ -3626,13 +3843,17 @@ o_est_first_obs : FIRST_OBS EQUAL vec_int
o_posterior_sampling_method : POSTERIOR_SAMPLING_METHOD EQUAL QUOTED_STRING o_posterior_sampling_method : POSTERIOR_SAMPLING_METHOD EQUAL QUOTED_STRING
{ driver.option_str("posterior_sampler_options.posterior_sampling_method", $3); } ; { driver.option_str("posterior_sampler_options.posterior_sampling_method", $3); } ;
o_first_obs : FIRST_OBS EQUAL INT_NUMBER { driver.option_num("first_obs", $3); }; o_first_obs : FIRST_OBS EQUAL INT_NUMBER { driver.option_num("first_obs", $3); };
o_data_first_obs : FIRST_OBS EQUAL date_expr { driver.option_date("firstobs", $3); } ; o_data_first_obs : FIRST_OBS EQUAL date_expr { driver.option_date("first_obs", $3); } ;
o_first_simulation_period : FIRST_SIMULATION_PERIOD EQUAL INT_NUMBER { driver.option_num("first_simulation_period", $3); }; o_first_simulation_period : FIRST_SIMULATION_PERIOD EQUAL INT_NUMBER { driver.option_num("first_simulation_period", $3); }
o_date_first_simulation_period : FIRST_SIMULATION_PERIOD EQUAL date_expr { driver.option_date("firstsimulationperiod", $3); } ; | FIRST_SIMULATION_PERIOD EQUAL date_expr { driver.option_date("first_simulation_period", $3); }
o_last_simulation_period : LAST_SIMULATION_PERIOD EQUAL INT_NUMBER { driver.option_num("last_simulation_period", $3); }; ;
o_date_last_simulation_period : LAST_SIMULATION_PERIOD EQUAL date_expr { driver.option_date("lastsimulationperiod", $3); } ; o_last_simulation_period : LAST_SIMULATION_PERIOD EQUAL INT_NUMBER { driver.option_num("last_simulation_period", $3); }
| LAST_SIMULATION_PERIOD EQUAL date_expr { driver.option_date("last_simulation_period", $3); }
;
o_pf_first_simulation_period : FIRST_SIMULATION_PERIOD EQUAL date_expr { driver.option_date("simul.first_simulation_period", $3); };
o_pf_last_simulation_period : LAST_SIMULATION_PERIOD EQUAL date_expr { driver.option_date("simul.last_simulation_period", $3); };
o_last_obs : LAST_OBS EQUAL INT_NUMBER { driver.option_num("last_obs", $3); }; o_last_obs : LAST_OBS EQUAL INT_NUMBER { driver.option_num("last_obs", $3); };
o_data_last_obs : LAST_OBS EQUAL date_expr { driver.option_date("lastobs", $3); } ; o_data_last_obs : LAST_OBS EQUAL date_expr { driver.option_date("last_obs", $3); } ;
o_keep_kalman_algo_if_singularity_is_detected : KEEP_KALMAN_ALGO_IF_SINGULARITY_IS_DETECTED { driver.option_num("kalman.keep_kalman_algo_if_singularity_is_detected", "true"); } ; o_keep_kalman_algo_if_singularity_is_detected : KEEP_KALMAN_ALGO_IF_SINGULARITY_IS_DETECTED { driver.option_num("kalman.keep_kalman_algo_if_singularity_is_detected", "true"); } ;
o_data_nobs : NOBS EQUAL INT_NUMBER { driver.option_num("nobs", $3); }; o_data_nobs : NOBS EQUAL INT_NUMBER { driver.option_num("nobs", $3); };
o_shift : SHIFT EQUAL signed_number { driver.option_num("shift", $3); }; o_shift : SHIFT EQUAL signed_number { driver.option_num("shift", $3); };
...@@ -3807,9 +4028,6 @@ o_partial_information : PARTIAL_INFORMATION {driver.option_num("partial_informat ...@@ -3807,9 +4028,6 @@ o_partial_information : PARTIAL_INFORMATION {driver.option_num("partial_informat
o_sub_draws: SUB_DRAWS EQUAL INT_NUMBER { driver.option_num("sub_draws", $3); }; o_sub_draws: SUB_DRAWS EQUAL INT_NUMBER { driver.option_num("sub_draws", $3); };
o_planner_discount : PLANNER_DISCOUNT EQUAL expression { driver.set_planner_discount($3); }; o_planner_discount : PLANNER_DISCOUNT EQUAL expression { driver.set_planner_discount($3); };
o_planner_discount_latex_name : PLANNER_DISCOUNT_LATEX_NAME EQUAL TEX_NAME { driver.set_planner_discount_latex_name($3); }; o_planner_discount_latex_name : PLANNER_DISCOUNT_LATEX_NAME EQUAL TEX_NAME { driver.set_planner_discount_latex_name($3); };
o_sylvester : SYLVESTER EQUAL FIXED_POINT {driver.option_num("sylvester_fp", "true"); }
| SYLVESTER EQUAL DEFAULT {driver.option_num("sylvester_fp", "false"); };
o_sylvester_fixed_point_tol : SYLVESTER_FIXED_POINT_TOL EQUAL non_negative_number {driver.option_num("sylvester_fixed_point_tol",$3);};
o_lyapunov : LYAPUNOV EQUAL FIXED_POINT { driver.option_num("lyapunov_fp", "true"); } o_lyapunov : LYAPUNOV EQUAL FIXED_POINT { driver.option_num("lyapunov_fp", "true"); }
| LYAPUNOV EQUAL DOUBLING { driver.option_num("lyapunov_db", "true"); } | LYAPUNOV EQUAL DOUBLING { driver.option_num("lyapunov_db", "true"); }
| LYAPUNOV EQUAL SQUARE_ROOT_SOLVER { driver.option_num("lyapunov_srs", "true"); } | LYAPUNOV EQUAL SQUARE_ROOT_SOLVER { driver.option_num("lyapunov_srs", "true"); }
...@@ -3821,6 +4039,7 @@ o_dr : DR EQUAL CYCLE_REDUCTION {driver.option_num("dr_cycle_reduction", "true") ...@@ -3821,6 +4039,7 @@ o_dr : DR EQUAL CYCLE_REDUCTION {driver.option_num("dr_cycle_reduction", "true")
| DR EQUAL LOGARITHMIC_REDUCTION { driver.option_num("dr_logarithmic_reduction", "true"); } | DR EQUAL LOGARITHMIC_REDUCTION { driver.option_num("dr_logarithmic_reduction", "true"); }
| DR EQUAL DEFAULT { driver.option_num("dr_cycle_reduction", "false"); driver.option_num("dr_logarithmic_reduction", "false"); }; | DR EQUAL DEFAULT { driver.option_num("dr_cycle_reduction", "false"); driver.option_num("dr_logarithmic_reduction", "false"); };
o_dr_cycle_reduction_tol : DR_CYCLE_REDUCTION_TOL EQUAL non_negative_number { driver.option_num("dr_cycle_reduction_tol", $3); }; o_dr_cycle_reduction_tol : DR_CYCLE_REDUCTION_TOL EQUAL non_negative_number { driver.option_num("dr_cycle_reduction_tol", $3); };
o_dr_cycle_reduction_maxiter : DR_CYCLE_REDUCTION_MAXITER EQUAL INT_NUMBER { driver.option_num("dr_cycle_reduction_maxiter", $3); };
o_dr_logarithmic_reduction_tol : DR_LOGARITHMIC_REDUCTION_TOL EQUAL non_negative_number { driver.option_num("dr_logarithmic_reduction_tol", $3); }; o_dr_logarithmic_reduction_tol : DR_LOGARITHMIC_REDUCTION_TOL EQUAL non_negative_number { driver.option_num("dr_logarithmic_reduction_tol", $3); };
o_dr_logarithmic_reduction_maxiter : DR_LOGARITHMIC_REDUCTION_MAXITER EQUAL INT_NUMBER { driver.option_num("dr_logarithmic_reduction_maxiter", $3); }; o_dr_logarithmic_reduction_maxiter : DR_LOGARITHMIC_REDUCTION_MAXITER EQUAL INT_NUMBER { driver.option_num("dr_logarithmic_reduction_maxiter", $3); };
o_psd_detail_plot : DETAIL_PLOT { driver.option_num("plot_shock_decomp.detail_plot", "true"); }; o_psd_detail_plot : DETAIL_PLOT { driver.option_num("plot_shock_decomp.detail_plot", "true"); };
...@@ -3873,9 +4092,11 @@ o_resampling : RESAMPLING EQUAL SYSTEMATIC ...@@ -3873,9 +4092,11 @@ o_resampling : RESAMPLING EQUAL SYSTEMATIC
| RESAMPLING EQUAL NONE { driver.option_num("particle.resampling.status.systematic", "false"); driver.option_num("particle.resampling.status.none", "true"); } | RESAMPLING EQUAL NONE { driver.option_num("particle.resampling.status.systematic", "false"); driver.option_num("particle.resampling.status.none", "true"); }
| RESAMPLING EQUAL GENERIC { driver.option_num("particle.resampling.status.systematic", "false"); driver.option_num("particle.resampling.status.generic", "true"); }; | RESAMPLING EQUAL GENERIC { driver.option_num("particle.resampling.status.systematic", "false"); driver.option_num("particle.resampling.status.generic", "true"); };
o_resampling_threshold : RESAMPLING_THRESHOLD EQUAL non_negative_number { driver.option_num("particle.resampling.threshold", $3); }; o_resampling_threshold : RESAMPLING_THRESHOLD EQUAL non_negative_number { driver.option_num("particle.resampling.threshold", $3); };
o_resampling_method : RESAMPLING_METHOD EQUAL KITAGAWA {driver.option_num("particle.resampling.method.kitagawa", "true"); driver.option_num("particle.resampling.method.smooth", "false"); driver.option_num("particle.resampling.smethod.stratified", "false"); } o_resampling_method : RESAMPLING_METHOD EQUAL KITAGAWA { driver.option_num("particle.resampling.method.kitagawa", "true"); driver.option_num("particle.resampling.method.smooth", "false"); driver.option_num("particle.resampling.method.stratified", "false"); driver.option_num("particle.resampling.method.residual", "false"); driver.option_num("particle.resampling.method.multinomial", "false") ;}
| RESAMPLING_METHOD EQUAL SMOOTH {driver.option_num("particle.resampling.method.kitagawa", "false"); driver.option_num("particle.resampling.method.smooth", "true"); driver.option_num("particle.resampling.smethod.stratified", "false"); } | RESAMPLING_METHOD EQUAL SMOOTH { driver.option_num("particle.resampling.method.kitagawa", "false"); driver.option_num("particle.resampling.method.smooth", "true"); driver.option_num("particle.resampling.method.stratified", "false"); driver.option_num("particle.resampling.method.residual", "false"); driver.option_num("particle.resampling.method.multinomial", "false"); };
| RESAMPLING_METHOD EQUAL STRATIFIED {driver.option_num("particle.resampling.method.kitagawa", "false"); driver.option_num("particle.resampling.method.smooth", "false"); driver.option_num("particle.resampling.method.stratified", "true"); }; | RESAMPLING_METHOD EQUAL STRATIFIED { driver.option_num("particle.resampling.method.kitagawa", "false"); driver.option_num("particle.resampling.method.smooth", "false"); driver.option_num("particle.resampling.method.stratified", "true"); driver.option_num("particle.resampling.method.residual", "false"); driver.option_num("particle.resampling.method.multinomial", "false"); };
| RESAMPLING_METHOD EQUAL RESIDUAL { driver.option_num("particle.resampling.method.kitagawa", "false"); driver.option_num("particle.resampling.method.smooth", "false"); driver.option_num("particle.resampling.method.stratified", "false"); driver.option_num("particle.resampling.method.residual", "true"); driver.option_num("particle.resampling.method.multinomial", "false"); };
| RESAMPLING_METHOD EQUAL MULTINOMIAL { driver.option_num("particle.resampling.method.kitagawa", "false"); driver.option_num("particle.resampling.method.smooth", "false"); driver.option_num("particle.resampling.method.stratified", "false"); driver.option_num("particle.resampling.method.residual", "false"); driver.option_num("particle.resampling.method.multinomial", "true"); };
o_cpf_weights : CPF_WEIGHTS EQUAL AMISANOTRISTANI { driver.option_num("particle.cpf_weights_method.amisanotristani", "true"); driver.option_num("particle.cpf_weights_method.murrayjonesparslow", "false"); } o_cpf_weights : CPF_WEIGHTS EQUAL AMISANOTRISTANI { driver.option_num("particle.cpf_weights_method.amisanotristani", "true"); driver.option_num("particle.cpf_weights_method.murrayjonesparslow", "false"); }
| CPF_WEIGHTS EQUAL MURRAYJONESPARSLOW { driver.option_num("particle.cpf_weights_method.amisanotristani", "false"); driver.option_num("particle.cpf_weights_method.murrayjonesparslow", "true"); }; | CPF_WEIGHTS EQUAL MURRAYJONESPARSLOW { driver.option_num("particle.cpf_weights_method.amisanotristani", "false"); driver.option_num("particle.cpf_weights_method.murrayjonesparslow", "true"); };
o_filter_algorithm : FILTER_ALGORITHM EQUAL symbol { driver.option_str("particle.filter_algorithm", $3); }; o_filter_algorithm : FILTER_ALGORITHM EQUAL symbol { driver.option_str("particle.filter_algorithm", $3); };
...@@ -3932,6 +4153,21 @@ o_max_dim_cova_group : MAX_DIM_COVA_GROUP EQUAL INT_NUMBER { driver.option_num(" ...@@ -3932,6 +4153,21 @@ o_max_dim_cova_group : MAX_DIM_COVA_GROUP EQUAL INT_NUMBER { driver.option_num("
o_homotopy_mode : HOMOTOPY_MODE EQUAL INT_NUMBER { driver.option_num("homotopy_mode", $3); }; o_homotopy_mode : HOMOTOPY_MODE EQUAL INT_NUMBER { driver.option_num("homotopy_mode", $3); };
o_homotopy_steps : HOMOTOPY_STEPS EQUAL INT_NUMBER { driver.option_num("homotopy_steps", $3); }; o_homotopy_steps : HOMOTOPY_STEPS EQUAL INT_NUMBER { driver.option_num("homotopy_steps", $3); };
o_homotopy_force_continue: HOMOTOPY_FORCE_CONTINUE EQUAL INT_NUMBER { driver.option_num("homotopy_force_continue", $3); }; o_homotopy_force_continue: HOMOTOPY_FORCE_CONTINUE EQUAL INT_NUMBER { driver.option_num("homotopy_force_continue", $3); };
o_preconditioner : PRECONDITIONER EQUAL UMFITER
{ driver.option_str("simul.preconditioner", "umfiter"); }
| PRECONDITIONER EQUAL ITERSTACK
{ driver.option_str("simul.preconditioner", "iterstack"); }
| PRECONDITIONER EQUAL ILU
{ driver.option_str("simul.preconditioner", "ilu"); };
;
o_iter_tol : ITER_TOL EQUAL non_negative_number { driver.option_num("simul.iter_tol", $3); };
o_iter_maxit : ITER_MAXIT EQUAL INT_NUMBER { driver.option_num("simul.iter_maxit", $3); };
o_gmres_restart : GMRES_RESTART EQUAL INT_NUMBER { driver.option_num("simul.gmres_restart", $3); };
o_iterstack_maxlu : ITERSTACK_MAXLU EQUAL INT_NUMBER { driver.option_num("simul.iterstack_maxlu", $3); };
o_iterstack_nperiods : ITERSTACK_NPERIODS EQUAL INT_NUMBER { driver.option_num("simul.iterstack_nperiods", $3); };
o_iterstack_nlu : ITERSTACK_NLU EQUAL INT_NUMBER { driver.option_num("simul.iterstack_nlu", $3); };
o_iterstack_relu : ITERSTACK_RELU EQUAL non_negative_number { driver.option_num("simul.iterstack_relu", $3); };
o_check_jacobian_singularity : CHECK_JACOBIAN_SINGULARITY { driver.option_num("simul.check_jacobian_singularity", "true"); };
o_nocheck : NOCHECK { driver.option_num("steadystate.nocheck", "true"); }; o_nocheck : NOCHECK { driver.option_num("steadystate.nocheck", "true"); };
o_controlled_varexo : CONTROLLED_VAREXO EQUAL '(' symbol_list ')' { driver.option_symbol_list("controlled_varexo", $4); }; o_controlled_varexo : CONTROLLED_VAREXO EQUAL '(' symbol_list ')' { driver.option_symbol_list("controlled_varexo", $4); };
...@@ -4146,10 +4382,11 @@ o_analytic_derivation_mode : ANALYTIC_DERIVATION_MODE EQUAL signed_number { driv ...@@ -4146,10 +4382,11 @@ o_analytic_derivation_mode : ANALYTIC_DERIVATION_MODE EQUAL signed_number { driv
o_endogenous_prior : ENDOGENOUS_PRIOR { driver.option_num("endogenous_prior", "true"); } o_endogenous_prior : ENDOGENOUS_PRIOR { driver.option_num("endogenous_prior", "true"); }
o_use_univariate_filters_if_singularity_is_detected : USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED EQUAL INT_NUMBER { driver.option_num("use_univariate_filters_if_singularity_is_detected", $3); } o_use_univariate_filters_if_singularity_is_detected : USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED EQUAL INT_NUMBER { driver.option_num("use_univariate_filters_if_singularity_is_detected", $3); }
o_mcmc_jumping_covariance : MCMC_JUMPING_COVARIANCE EQUAL HESSIAN o_mcmc_jumping_covariance : MCMC_JUMPING_COVARIANCE EQUAL HESSIAN
{ driver.option_str("MCMC_jumping_covariance", $3); } | MCMC_JUMPING_COVARIANCE EQUAL PRIOR_VARIANCE { driver.option_str("MCMC_jumping_covariance", "hessian"); }
{ driver.option_str("MCMC_jumping_covariance", $3); } | MCMC_JUMPING_COVARIANCE EQUAL PRIOR_VARIANCE
{ driver.option_str("MCMC_jumping_covariance", "prior_variance"); }
| MCMC_JUMPING_COVARIANCE EQUAL IDENTITY_MATRIX | MCMC_JUMPING_COVARIANCE EQUAL IDENTITY_MATRIX
{ driver.option_str("MCMC_jumping_covariance", $3); } { driver.option_str("MCMC_jumping_covariance", "identity_matrix"); }
| MCMC_JUMPING_COVARIANCE EQUAL filename | MCMC_JUMPING_COVARIANCE EQUAL filename
{ driver.option_str("MCMC_jumping_covariance", $3); } { driver.option_str("MCMC_jumping_covariance", $3); }
; ;
...@@ -4169,6 +4406,7 @@ o_homotopy_step_size_increase_success_count : HOMOTOPY_STEP_SIZE_INCREASE_SUCCES ...@@ -4169,6 +4406,7 @@ o_homotopy_step_size_increase_success_count : HOMOTOPY_STEP_SIZE_INCREASE_SUCCES
o_homotopy_linearization_fallback : HOMOTOPY_LINEARIZATION_FALLBACK { driver.option_num("simul.homotopy_linearization_fallback", "true"); } o_homotopy_linearization_fallback : HOMOTOPY_LINEARIZATION_FALLBACK { driver.option_num("simul.homotopy_linearization_fallback", "true"); }
o_homotopy_marginal_linearization_fallback : HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK { driver.option_num("simul.homotopy_marginal_linearization_fallback", "0.01"); } o_homotopy_marginal_linearization_fallback : HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK { driver.option_num("simul.homotopy_marginal_linearization_fallback", "0.01"); }
| HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK EQUAL non_negative_number { driver.option_num("simul.homotopy_marginal_linearization_fallback", $3); } | HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK EQUAL non_negative_number { driver.option_num("simul.homotopy_marginal_linearization_fallback", $3); }
o_homotopy_exclude_varexo : HOMOTOPY_EXCLUDE_VAREXO EQUAL '(' symbol_list ')' { driver.option_symbol_list("simul.homotopy_exclude_varexo", $4); };
o_infile : INFILE EQUAL filename { driver.option_str("infile", $3); }; o_infile : INFILE EQUAL filename { driver.option_str("infile", $3); };
o_invars : INVARS EQUAL '(' symbol_list ')' { driver.option_symbol_list("invars", $4); }; o_invars : INVARS EQUAL '(' symbol_list ')' { driver.option_symbol_list("invars", $4); };
...@@ -4219,7 +4457,7 @@ o_emas_girf : EMAS_GIRF { driver.option_num("irf_opt.ergodic_mean_irf", "true"); ...@@ -4219,7 +4457,7 @@ o_emas_girf : EMAS_GIRF { driver.option_num("irf_opt.ergodic_mean_irf", "true");
o_emas_drop : EMAS_DROP EQUAL INT_NUMBER { driver.option_num("irf_opt.EM.drop", $3); }; o_emas_drop : EMAS_DROP EQUAL INT_NUMBER { driver.option_num("irf_opt.EM.drop", $3); };
o_emas_tolf : EMAS_TOLF EQUAL non_negative_number { driver.option_num("irf_opt.EM.tolf", $3); }; o_emas_tolf : EMAS_TOLF EQUAL non_negative_number { driver.option_num("irf_opt.EM.tolf", $3); };
o_emas_max_iter : EMAS_MAX_ITER EQUAL INT_NUMBER { driver.option_num("irf_opt.EM.iter", $3); }; o_emas_max_iter : EMAS_MAX_ITER EQUAL INT_NUMBER { driver.option_num("irf_opt.EM.iter", $3); };
o_non_zero : NON_ZERO { driver.option_num("non_zero", "true"); }; o_non_zero : NON_ZERO { driver.option_num("steady.non_zero", "true"); };
// Some options to "identification" // Some options to "identification"
o_no_identification_strength : NO_IDENTIFICATION_STRENGTH { driver.option_num("no_identification_strength", "true"); }; o_no_identification_strength : NO_IDENTIFICATION_STRENGTH { driver.option_num("no_identification_strength", "true"); };
...@@ -4309,9 +4547,8 @@ vec_int_number : INT_NUMBER ...@@ -4309,9 +4547,8 @@ vec_int_number : INT_NUMBER
vec_int_elem : vec_int_number vec_int_elem : vec_int_number
| INT_NUMBER ':' INT_NUMBER | INT_NUMBER ':' INT_NUMBER
{ {
$$ = {}; auto v = views::iota(stoi($1), stoi($3) + 1);
for (int i = stoi($1); i <= stoi($3); i++) $$ = {v.begin(), v.end()};
$$.push_back(i);
} }
; ;
...@@ -4438,13 +4675,14 @@ symbol : NAME ...@@ -4438,13 +4675,14 @@ symbol : NAME
| DD | DD
| ADD | ADD
| MULTIPLY | MULTIPLY
| MFS
| RESIDUAL
; ;
%% %%
void void
Dynare::parser::error(const Dynare::parser::location_type &l, Dynare::parser::error(const Dynare::parser::location_type& l, const string& m)
const string &m)
{ {
driver.error(l, m); driver.error(l, m);
} }