Reformat C++ source code using clang-format 15

master
Sébastien Villemot 2023-11-30 15:28:57 +01:00
parent 529ec50337
commit d463607e90
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
57 changed files with 13381 additions and 11084 deletions

View File

@ -17,10 +17,10 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <ios>
#include <cstdlib>
#include <algorithm>
#include <cstdlib>
#include <ios>
#include <iostream>
#include "Bytecode.hh"
@ -40,8 +40,7 @@ operator<<(BytecodeWriter &code_file, const FCALL_ &instr)
{
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);
};
@ -71,8 +70,7 @@ operator<<(BytecodeWriter &code_file, const FBEGINBLOCK_ &instr)
{
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);
};

View File

@ -20,12 +20,12 @@
#ifndef _BYTECODE_HH
#define _BYTECODE_HH
#include <fstream>
#include <vector>
#include <utility>
#include <ios>
#include <filesystem>
#include <fstream>
#include <ios>
#include <type_traits>
#include <utility>
#include <vector>
#include "CommonEnums.hh"
@ -38,22 +38,35 @@ enum class Tags
FLDC, // Loads a constant term onto the stack
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 hasnt to be indicated)
FDIMST, // Defines the number of temporary terms - static context (the period hasnt 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 hasnt to be indicated)
FSTPT, // Stores a temporary term from the stack - dynamic context (the period has to be indicated)
FSTPST, // Stores a temporary term from the stack - static context (the period hasnt to be indicated)
FLDST, // Loads a temporary term onto the stack - static context (the period hasnt to be
// indicated)
FSTPT, // Stores a temporary term from the stack - dynamic context (the period has to be
// indicated)
FSTPST, // Stores a temporary term from the stack - static context (the period hasnt to be
// indicated)
FLDU, // Loads an element of the vector U 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 hasnt to be 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 hasnt to be indicated)
FLDU, // Loads an element of the vector U 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 hasnt to
// be 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 hasnt 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 hasnt to be indicated)
FLDVS, // Loads a variable (described in SymbolType) onto the stack - dynamic context but inside the STEADY_STATE operator (the period hasnt 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 hasnt 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
// hasnt to be indicated)
FLDVS, // Loads a variable (described in SymbolType) onto the stack - dynamic context but inside
// the STEADY_STATE operator (the period hasnt 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
// hasnt to be indicated)
FLDR, // Loads a residual onto the stack
FSTPR, // Stores a residual from the stack
@ -71,7 +84,8 @@ enum class Tags
FBEGINBLOCK, // Marks the beginning 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
FNUMEXPR, // Stores the expression type and references
@ -115,10 +129,10 @@ class BytecodeWriter;
struct BytecodeInstruction
{
const Tags op_code;
explicit BytecodeInstruction(Tags op_code_arg) :
op_code {op_code_arg}
explicit BytecodeInstruction(Tags op_code_arg) : op_code {op_code_arg}
{
}
protected:
/* 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
@ -133,11 +147,13 @@ class TagWithOneArgument : public BytecodeInstruction
{
protected:
T1 arg1;
public:
TagWithOneArgument(Tags op_code_arg, T1 arg_arg1) : BytecodeInstruction{op_code_arg},
arg1{arg_arg1}
TagWithOneArgument(Tags op_code_arg, T1 arg_arg1) :
BytecodeInstruction {op_code_arg}, arg1 {arg_arg1}
{
};
}
protected:
// See BytecodeInstruction destructor for the rationale
~TagWithOneArgument() = default;
@ -149,11 +165,13 @@ class TagWithTwoArguments : public BytecodeInstruction
protected:
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;
@ -166,11 +184,13 @@ 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;
@ -184,12 +204,17 @@ protected:
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}
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;
@ -200,7 +225,7 @@ class FLDZ_ final : public BytecodeInstruction
public:
FLDZ_() : BytecodeInstruction {Tags::FLDZ}
{
};
}
};
class FEND_ final : public BytecodeInstruction
@ -208,7 +233,7 @@ class FEND_ final : public BytecodeInstruction
public:
FEND_() : BytecodeInstruction {Tags::FEND}
{
};
}
};
class FENDBLOCK_ final : public BytecodeInstruction
@ -216,7 +241,7 @@ class FENDBLOCK_ final : public BytecodeInstruction
public:
FENDBLOCK_() : BytecodeInstruction {Tags::FENDBLOCK}
{
};
}
};
class FENDEQU_ final : public BytecodeInstruction
@ -224,7 +249,7 @@ class FENDEQU_ final : public BytecodeInstruction
public:
FENDEQU_() : BytecodeInstruction {Tags::FENDEQU}
{
};
}
};
class FDIMT_ final : public TagWithOneArgument<int>
@ -232,7 +257,7 @@ class FDIMT_ final : public TagWithOneArgument<int>
public:
explicit FDIMT_(int size_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FDIMT, size_arg}
{
};
}
int
get_size()
{
@ -245,7 +270,7 @@ class FDIMST_ final : public TagWithOneArgument<int>
public:
explicit FDIMST_(int size_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FDIMST, size_arg}
{
};
}
int
get_size()
{
@ -258,7 +283,7 @@ class FLDC_ final : public TagWithOneArgument<double>
public:
explicit FLDC_(double value_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FLDC, value_arg}
{
};
}
double
get_value()
{
@ -271,7 +296,7 @@ class FLDU_ final : public TagWithOneArgument<int>
public:
explicit FLDU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FLDU, pos_arg}
{
};
}
int
get_pos()
{
@ -284,7 +309,7 @@ class FLDSU_ final : public TagWithOneArgument<int>
public:
explicit FLDSU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FLDSU, pos_arg}
{
};
}
int
get_pos()
{
@ -297,7 +322,7 @@ class FLDR_ final : public TagWithOneArgument<int>
public:
explicit FLDR_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FLDR, pos_arg}
{
};
}
int
get_pos()
{
@ -310,7 +335,7 @@ class FLDT_ final : public TagWithOneArgument<int>
public:
explicit FLDT_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FLDT, pos_arg}
{
};
}
int
get_pos()
{
@ -323,7 +348,7 @@ class FLDST_ final : public TagWithOneArgument<int>
public:
explicit FLDST_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FLDST, pos_arg}
{
};
}
int
get_pos()
{
@ -336,7 +361,7 @@ class FSTPT_ final : public TagWithOneArgument<int>
public:
explicit FSTPT_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPT, pos_arg}
{
};
}
int
get_pos()
{
@ -349,7 +374,7 @@ class FSTPST_ final : public TagWithOneArgument<int>
public:
explicit FSTPST_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPST, pos_arg}
{
};
}
int
get_pos()
{
@ -362,7 +387,7 @@ class FSTPR_ final : public TagWithOneArgument<int>
public:
explicit FSTPR_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPR, pos_arg}
{
};
}
int
get_pos()
{
@ -375,7 +400,7 @@ class FSTPU_ final : public TagWithOneArgument<int>
public:
explicit FSTPU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPU, pos_arg}
{
};
}
int
get_pos()
{
@ -388,7 +413,7 @@ class FSTPSU_ final : public TagWithOneArgument<int>
public:
explicit FSTPSU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPSU, pos_arg}
{
};
}
int
get_pos()
{
@ -401,7 +426,7 @@ class FSTPG_ final : public TagWithOneArgument<int>
public:
explicit FSTPG_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPG, pos_arg}
{
};
}
int
get_pos()
{
@ -412,9 +437,10 @@ public:
class FSTPG2_ final : public TagWithTwoArguments<int, int>
{
public:
FSTPG2_(int row_arg, int col_arg) : TagWithTwoArguments::TagWithTwoArguments{Tags::FSTPG2, row_arg, col_arg}
FSTPG2_(int row_arg, int col_arg) :
TagWithTwoArguments::TagWithTwoArguments {Tags::FSTPG2, row_arg, col_arg}
{
};
}
int
get_row()
{
@ -430,9 +456,11 @@ public:
class FSTPG3_ final : public TagWithFourArguments<int, int, int, int>
{
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}
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()
{
@ -458,9 +486,10 @@ public:
class FUNARY_ final : public TagWithOneArgument<UnaryOpcode>
{
public:
explicit FUNARY_(UnaryOpcode op_type_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FUNARY, op_type_arg}
explicit FUNARY_(UnaryOpcode op_type_arg) :
TagWithOneArgument::TagWithOneArgument {Tags::FUNARY, op_type_arg}
{
};
}
UnaryOpcode
get_op_type()
{
@ -471,9 +500,10 @@ public:
class FBINARY_ final : public TagWithOneArgument<BinaryOpcode>
{
public:
explicit FBINARY_(BinaryOpcode op_type_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FBINARY, op_type_arg}
explicit FBINARY_(BinaryOpcode op_type_arg) :
TagWithOneArgument::TagWithOneArgument {Tags::FBINARY, op_type_arg}
{
};
}
BinaryOpcode
get_op_type()
{
@ -484,9 +514,10 @@ public:
class FTRINARY_ final : public TagWithOneArgument<TrinaryOpcode>
{
public:
explicit FTRINARY_(TrinaryOpcode op_type_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FTRINARY, op_type_arg}
explicit FTRINARY_(TrinaryOpcode op_type_arg) :
TagWithOneArgument::TagWithOneArgument {Tags::FTRINARY, op_type_arg}
{
};
}
TrinaryOpcode
get_op_type()
{
@ -497,9 +528,10 @@ public:
class FJMPIFEVAL_ final : public TagWithOneArgument<int>
{
public:
explicit FJMPIFEVAL_(int arg_pos) : TagWithOneArgument::TagWithOneArgument{Tags::FJMPIFEVAL, arg_pos}
explicit FJMPIFEVAL_(int arg_pos) :
TagWithOneArgument::TagWithOneArgument {Tags::FJMPIFEVAL, arg_pos}
{
};
}
int
get_pos()
{
@ -512,7 +544,7 @@ class FJMP_ final : public TagWithOneArgument<int>
public:
explicit FJMP_(int arg_pos) : TagWithOneArgument::TagWithOneArgument {Tags::FJMP, arg_pos}
{
};
}
int
get_pos()
{
@ -525,7 +557,7 @@ class FLDTEF_ final : public TagWithOneArgument<int>
public:
explicit FLDTEF_(int number) : TagWithOneArgument::TagWithOneArgument {Tags::FLDTEF, number}
{
};
}
int
get_number()
{
@ -538,7 +570,7 @@ class FSTPTEF_ final : public TagWithOneArgument<int>
public:
explicit FSTPTEF_(int number) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPTEF, number}
{
};
}
int
get_number()
{
@ -551,7 +583,7 @@ class FLDTEFD_ final : public TagWithTwoArguments<int, int>
public:
FLDTEFD_(int indx, int row) : TagWithTwoArguments::TagWithTwoArguments {Tags::FLDTEFD, indx, row}
{
};
}
int
get_indx()
{
@ -567,9 +599,10 @@ public:
class FSTPTEFD_ final : public TagWithTwoArguments<int, int>
{
public:
FSTPTEFD_(int indx, int row) : TagWithTwoArguments::TagWithTwoArguments{Tags::FSTPTEFD, indx, row}
FSTPTEFD_(int indx, int row) :
TagWithTwoArguments::TagWithTwoArguments {Tags::FSTPTEFD, indx, row}
{
};
}
int
get_indx()
{
@ -585,9 +618,10 @@ public:
class FLDTEFDD_ final : public TagWithThreeArguments<int, int, int>
{
public:
FLDTEFDD_(int indx, int row, int col) : TagWithThreeArguments::TagWithThreeArguments{Tags::FLDTEFDD, indx, row, col}
FLDTEFDD_(int indx, int row, int col) :
TagWithThreeArguments::TagWithThreeArguments {Tags::FLDTEFDD, indx, row, col}
{
};
}
int
get_indx()
{
@ -608,9 +642,10 @@ public:
class FSTPTEFDD_ final : public TagWithThreeArguments<int, int, int>
{
public:
FSTPTEFDD_(int indx, int row, int col) : TagWithThreeArguments::TagWithThreeArguments{Tags::FSTPTEF, indx, row, col}
FSTPTEFDD_(int indx, int row, int col) :
TagWithThreeArguments::TagWithThreeArguments {Tags::FSTPTEF, indx, row, col}
{
};
}
int
get_indx()
{
@ -631,9 +666,10 @@ public:
class FLDVS_ final : public TagWithTwoArguments<SymbolType, int>
{
public:
FLDVS_(SymbolType type_arg, int pos_arg) : TagWithTwoArguments::TagWithTwoArguments{Tags::FLDVS, type_arg, pos_arg}
FLDVS_(SymbolType type_arg, int pos_arg) :
TagWithTwoArguments::TagWithTwoArguments {Tags::FLDVS, type_arg, pos_arg}
{
};
}
SymbolType
get_type()
{
@ -649,9 +685,10 @@ public:
class FLDSV_ final : public TagWithTwoArguments<SymbolType, int>
{
public:
FLDSV_(SymbolType type_arg, int pos_arg) : TagWithTwoArguments::TagWithTwoArguments{Tags::FLDSV, type_arg, pos_arg}
FLDSV_(SymbolType type_arg, int pos_arg) :
TagWithTwoArguments::TagWithTwoArguments {Tags::FLDSV, type_arg, pos_arg}
{
};
}
SymbolType
get_type()
{
@ -667,9 +704,10 @@ public:
class FSTPSV_ final : public TagWithTwoArguments<SymbolType, int>
{
public:
FSTPSV_(SymbolType type_arg, int pos_arg) : TagWithTwoArguments::TagWithTwoArguments{Tags::FSTPSV, type_arg, pos_arg}
FSTPSV_(SymbolType type_arg, int pos_arg) :
TagWithTwoArguments::TagWithTwoArguments {Tags::FSTPSV, type_arg, pos_arg}
{
};
}
SymbolType
get_type()
{
@ -688,7 +726,7 @@ 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()
{
@ -712,7 +750,7 @@ 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()
{
@ -734,14 +772,17 @@ class FCALL_ final : public BytecodeInstruction
{
template<typename B>
friend BytecodeWriter& operator<<(BytecodeWriter& code_file, const B& instr);
private:
int nb_output_arguments, nb_input_arguments, indx;
string func_name;
string arg_func_name;
int add_input_arguments {0}, row {0}, col {0};
ExternalFunctionCallType call_type;
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, ExternalFunctionCallType call_type_arg) :
BytecodeInstruction {Tags::FCALL},
nb_output_arguments {nb_output_arguments_arg},
nb_input_arguments {nb_input_arguments_arg},
@ -749,16 +790,14 @@ public:
func_name {move(func_name_arg)},
call_type {call_type_arg}
{
};
}
/* Deserializing constructor.
Updates the code pointer to point beyond the bytes read. */
FCALL_(char *&code) :
BytecodeInstruction{Tags::FCALL}
FCALL_(char*& code) : BytecodeInstruction {Tags::FCALL}
{
code += sizeof(op_code);
auto read_member = [&code](auto &member)
{
auto read_member = [&code](auto& member) {
member = *reinterpret_cast<add_pointer_t<decltype(member)>>(code);
code += sizeof member;
};
@ -853,7 +892,8 @@ class FNUMEXPR_ final : public BytecodeInstruction
{
private:
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 lag1; // For derivatives, lead/lag of the derivation variable
public:
@ -864,7 +904,7 @@ public:
dvariable1 {0},
lag1 {0}
{
};
}
FNUMEXPR_(const ExpressionType expression_type_arg, int equation_arg, int dvariable1_arg) :
BytecodeInstruction {Tags::FNUMEXPR},
expression_type {expression_type_arg},
@ -872,15 +912,16 @@ public:
dvariable1 {dvariable1_arg},
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,
int lag1_arg) :
BytecodeInstruction {Tags::FNUMEXPR},
expression_type {expression_type_arg},
equation {equation_arg},
dvariable1 {dvariable1_arg},
lag1 {lag1_arg}
{
};
}
ExpressionType
get_expression_type()
{
@ -907,6 +948,7 @@ class FBEGINBLOCK_ final : public BytecodeInstruction
{
template<typename B>
friend BytecodeWriter& operator<<(BytecodeWriter& code_file, const B& instr);
private:
int size {0};
BlockSimulationType type;
@ -919,20 +961,22 @@ private:
int u_count_int {0};
int nb_col_jacob {0};
int det_exo_size, exo_size;
public:
/* Constructor when derivatives w.r.t. exogenous are present (only makes
sense when there is no block-decomposition, since there is no provision for
derivatives w.r.t. endogenous not belonging to the block) */
FBEGINBLOCK_(int size_arg, BlockSimulationType type_arg, int first_element, int block_size,
const vector<int> &variable_arg, const vector<int> &equation_arg,
bool is_linear_arg, int u_count_int_arg, int nb_col_jacob_arg,
int det_exo_size_arg, int exo_size_arg,
const vector<int>& variable_arg, const vector<int>& equation_arg, bool is_linear_arg,
int u_count_int_arg, int nb_col_jacob_arg, int det_exo_size_arg, int exo_size_arg,
vector<int> det_exogenous_arg, vector<int> exogenous_arg) :
BytecodeInstruction {Tags::FBEGINBLOCK},
size {size_arg},
type {type_arg},
variable{variable_arg.begin()+first_element, variable_arg.begin()+(first_element+block_size)},
equation{equation_arg.begin()+first_element, equation_arg.begin()+(first_element+block_size)},
variable {variable_arg.begin() + first_element,
variable_arg.begin() + (first_element + block_size)},
equation {equation_arg.begin() + first_element,
equation_arg.begin() + (first_element + block_size)},
exogenous {move(exogenous_arg)},
det_exogenous {move(det_exogenous_arg)},
is_linear {is_linear_arg},
@ -944,13 +988,15 @@ public:
}
// Constructor when derivatives w.r.t. exogenous are absent
FBEGINBLOCK_(int size_arg, BlockSimulationType type_arg, int first_element, int block_size,
const vector<int> &variable_arg, const vector<int> &equation_arg,
bool is_linear_arg, int u_count_int_arg, int nb_col_jacob_arg) :
const vector<int>& variable_arg, const vector<int>& equation_arg, bool is_linear_arg,
int u_count_int_arg, int nb_col_jacob_arg) :
BytecodeInstruction {Tags::FBEGINBLOCK},
size {size_arg},
type {type_arg},
variable{variable_arg.begin()+first_element, variable_arg.begin()+(first_element+block_size)},
equation{equation_arg.begin()+first_element, equation_arg.begin()+(first_element+block_size)},
variable {variable_arg.begin() + first_element,
variable_arg.begin() + (first_element + block_size)},
equation {equation_arg.begin() + first_element,
equation_arg.begin() + (first_element + block_size)},
is_linear {is_linear_arg},
u_count_int {u_count_int_arg},
nb_col_jacob {nb_col_jacob_arg},
@ -960,13 +1006,11 @@ public:
}
/* Deserializing constructor.
Updates the code pointer to point beyond the bytes read. */
FBEGINBLOCK_(char *&code) :
BytecodeInstruction{Tags::FBEGINBLOCK}
FBEGINBLOCK_(char*& code) : BytecodeInstruction {Tags::FBEGINBLOCK}
{
code += sizeof(op_code);
auto read_member = [&code](auto &member)
{
auto read_member = [&code](auto& member) {
member = *reinterpret_cast<add_pointer_t<decltype(member)>>(code);
code += sizeof member;
};
@ -1063,9 +1107,11 @@ class BytecodeWriter : private ofstream
{
template<typename B>
friend BytecodeWriter& operator<<(BytecodeWriter& code_file, const B& instr);
private:
// Stores the positions of all instructions in the byte stream
vector<pos_type> instructions_positions;
public:
BytecodeWriter(const filesystem::path& filename);
// Returns the number of the next instruction to be written

View File

@ -21,7 +21,8 @@
#define _COMMON_ENUMS_HH
//! 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
{
endogenous = 0, //!< Endogenous
@ -32,9 +33,11 @@ enum class SymbolType
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)
statementDeclaredVariable
= 14, //!< Local variable assigned within a Statement (see subsample statement for example)
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)
@ -66,7 +69,8 @@ enum class UnaryOpcode
sign,
steadyState,
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,
erf,
erfc,
@ -119,8 +123,10 @@ enum class PriorDistributions
enum class EquationType
{
evaluate, //!< Simple evaluation, normalized variable on left-hand side (written as such by the user)
evaluateRenormalized, //!< Simple evaluation, normalized variable on left-hand side (normalization computed by the preprocessor)
evaluate, //!< Simple evaluation, normalized variable on left-hand side (written as such by the
//!< 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
};
@ -133,7 +139,8 @@ enum class BlockSimulationType
solveTwoBoundariesSimple, //!< Block of one equation, Newton solver needed, forward and backward
solveForwardComplete, //!< Block of several equations, Newton solver needed, forward
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

File diff suppressed because it is too large Load Diff

View File

@ -20,20 +20,21 @@
#ifndef _COMPUTINGTASKS_HH
#define _COMPUTINGTASKS_HH
#include <ostream>
#include <optional>
#include <ostream>
#include "SymbolList.hh"
#include "SymbolTable.hh"
#include "Statement.hh"
#include "StaticModel.hh"
#include "DynamicModel.hh"
#include "ModelEquationBlock.hh"
#include "Statement.hh"
#include "StaticModel.hh"
#include "SymbolList.hh"
#include "SymbolTable.hh"
class SteadyStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit SteadyStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -45,6 +46,7 @@ class CheckStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit CheckStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -56,6 +58,7 @@ class SimulStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit SimulStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -67,6 +70,7 @@ class PerfectForesightSetupStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit PerfectForesightSetupStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -77,6 +81,7 @@ class PerfectForesightSolverStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit PerfectForesightSolverStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -88,6 +93,7 @@ class PerfectForesightWithExpectationErrorsSetupStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit PerfectForesightWithExpectationErrorsSetupStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -98,6 +104,7 @@ class PerfectForesightWithExpectationErrorsSolverStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit PerfectForesightWithExpectationErrorsSolverStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -110,6 +117,7 @@ class PriorPosteriorFunctionStatement : public Statement
private:
const bool prior_func;
const OptionsList options_list;
public:
PriorPosteriorFunctionStatement(const bool prior_func_arg, OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -121,6 +129,7 @@ class ModelInfoStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit ModelInfoStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -133,6 +142,7 @@ private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
StochSimulStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
@ -147,6 +157,7 @@ private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
ForecastStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
@ -159,6 +170,7 @@ class RamseyModelStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit RamseyModelStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -176,9 +188,11 @@ public:
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;
@ -192,6 +206,7 @@ private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
RamseyPolicyStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
@ -204,6 +219,7 @@ class EvaluatePlannerObjectiveStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit EvaluatePlannerObjectiveStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -214,6 +230,7 @@ class OccbinSetupStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit OccbinSetupStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -224,6 +241,7 @@ class OccbinSolverStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit OccbinSolverStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -234,6 +252,7 @@ class OccbinWriteRegimesStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit OccbinWriteRegimesStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -245,9 +264,9 @@ class OccbinGraphStatement : public Statement
private:
const SymbolList symbol_list;
const OptionsList options_list;
public:
OccbinGraphStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg);
OccbinGraphStatement(SymbolList symbol_list_arg, OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
@ -258,6 +277,7 @@ private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
DiscretionaryPolicyStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
@ -271,6 +291,7 @@ class RplotStatement : public Statement
private:
const SymbolList symbol_list;
const SymbolTable& symbol_table;
public:
RplotStatement(SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -289,6 +310,7 @@ class DsampleStatement : public Statement
{
private:
const int val1, val2;
public:
explicit DsampleStatement(int val1_arg);
DsampleStatement(int val1_arg, int val2_arg);
@ -302,9 +324,9 @@ private:
const SymbolTable& symbol_table;
const SymbolList symbol_list;
const OptionsList options_list;
public:
EstimationStatement(const SymbolTable &symbol_table_arg,
SymbolList symbol_list_arg,
EstimationStatement(const SymbolTable& symbol_table_arg, SymbolList symbol_list_arg,
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;
@ -315,6 +337,7 @@ class DynareSensitivityStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit DynareSensitivityStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -326,9 +349,11 @@ class ObservationTrendsStatement : public Statement
{
public:
using trend_elements_t = map<string, expr_t>;
private:
const trend_elements_t trend_elements;
const SymbolTable& symbol_table;
public:
ObservationTrendsStatement(trend_elements_t trend_elements_arg,
const SymbolTable& symbol_table_arg);
@ -340,9 +365,11 @@ class DeterministicTrendsStatement : public Statement
{
public:
using trend_elements_t = map<string, expr_t>;
private:
const trend_elements_t trend_elements;
const SymbolTable& symbol_table;
public:
DeterministicTrendsStatement(trend_elements_t trend_elements_arg,
const SymbolTable& symbol_table_arg);
@ -354,9 +381,11 @@ class FilterInitialStateStatement : public Statement
{
public:
using filter_initial_state_elements_t = map<pair<int, int>, expr_t>;
private:
const filter_initial_state_elements_t filter_initial_state_elements;
const SymbolTable& symbol_table;
public:
FilterInitialStateStatement(filter_initial_state_elements_t filter_initial_state_elements_arg,
const SymbolTable& symbol_table_arg);
@ -369,6 +398,7 @@ class OsrParamsStatement : public Statement
private:
const SymbolList symbol_list;
const SymbolTable& symbol_table;
public:
OsrParamsStatement(SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -382,6 +412,7 @@ private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
OsrStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
@ -410,6 +441,7 @@ class OsrParamsBoundsStatement : public Statement
{
private:
const vector<OsrParams> osr_params_list;
public:
explicit OsrParamsBoundsStatement(vector<OsrParams> osr_params_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -423,6 +455,7 @@ private:
const SymbolList symbol_list;
const string filename;
const SymbolTable& symbol_table;
public:
DynaTypeStatement(SymbolList symbol_list_arg, string filename_arg,
const SymbolTable& symbol_table_arg);
@ -437,6 +470,7 @@ private:
const SymbolList symbol_list;
const string filename;
const SymbolTable& symbol_table;
public:
DynaSaveStatement(SymbolList symbol_list_arg, string filename_arg,
const SymbolTable& symbol_table_arg);
@ -449,12 +483,13 @@ class ModelComparisonStatement : public Statement
{
public:
using filename_list_t = vector<pair<string, string>>;
private:
filename_list_t filename_list;
OptionsList options_list;
public:
ModelComparisonStatement(filename_list_t filename_list_arg,
OptionsList options_list_arg);
ModelComparisonStatement(filename_list_t filename_list_arg, OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
@ -502,11 +537,15 @@ class EstimatedParamsStatement : public AbstractEstimatedParamsStatement
{
private:
const bool overwrite;
public:
EstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg,
bool overwrite_arg);
string blockName() const override { return "estimated_params"; };
const SymbolTable& symbol_table_arg, bool overwrite_arg);
string
blockName() const override
{
return "estimated_params";
};
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;
@ -516,11 +555,15 @@ class EstimatedParamsInitStatement : public AbstractEstimatedParamsStatement
{
private:
const bool use_calibration;
public:
EstimatedParamsInitStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg,
const bool use_calibration_arg);
string blockName() const override { return "estimated_params_init"; };
const SymbolTable& symbol_table_arg, const bool use_calibration_arg);
string
blockName() const override
{
return "estimated_params_init";
};
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;
@ -531,7 +574,11 @@ class EstimatedParamsBoundsStatement : public AbstractEstimatedParamsStatement
public:
EstimatedParamsBoundsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable& symbol_table_arg);
string blockName() const override { return "estimated_params_bounds"; };
string
blockName() const override
{
return "estimated_params_bounds";
};
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;
@ -554,13 +601,14 @@ class OptimWeightsStatement : public Statement
public:
using var_weights_t = map<string, expr_t>;
using covar_weights_t = map<pair<string, string>, expr_t>;
private:
const var_weights_t var_weights;
const covar_weights_t covar_weights;
const SymbolTable& symbol_table;
public:
OptimWeightsStatement(var_weights_t var_weights_arg,
covar_weights_t covar_weights_arg,
OptimWeightsStatement(var_weights_t var_weights_arg, covar_weights_t covar_weights_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -572,6 +620,7 @@ class PlannerObjectiveStatement : public Statement
private:
PlannerObjective model_tree;
bool computing_pass_called {false};
public:
explicit PlannerObjectiveStatement(const PlannerObjective& model_tree_arg);
/*! \todo check there are only endogenous variables at the current period in the objective
@ -590,6 +639,7 @@ class BVARDensityStatement : public Statement
private:
const int maxnlags;
const OptionsList options_list;
public:
BVARDensityStatement(int maxnlags_arg, OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -602,6 +652,7 @@ class BVARForecastStatement : public Statement
private:
const int nlags;
const OptionsList options_list;
public:
BVARForecastStatement(int nlags_arg, OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -614,6 +665,7 @@ class BVARIRFStatement : public Statement
private:
const int nirf;
const string identificationname;
public:
BVARIRFStatement(int nirf_arg, string identificationname_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -625,6 +677,7 @@ class SBVARStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit SBVARStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -636,6 +689,7 @@ class MSSBVAREstimationStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MSSBVAREstimationStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -647,6 +701,7 @@ class MSSBVARSimulationStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MSSBVARSimulationStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -658,6 +713,7 @@ class MSSBVARComputeMDDStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MSSBVARComputeMDDStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -669,6 +725,7 @@ class MSSBVARComputeProbabilitiesStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MSSBVARComputeProbabilitiesStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -682,6 +739,7 @@ private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
MSSBVARIrfStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
@ -694,6 +752,7 @@ class MSSBVARForecastStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MSSBVARForecastStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -705,6 +764,7 @@ class MSSBVARVarianceDecompositionStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MSSBVARVarianceDecompositionStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -716,6 +776,7 @@ class IdentificationStatement : public Statement
{
private:
OptionsList options_list;
public:
explicit IdentificationStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -728,8 +789,10 @@ class WriteLatexDynamicModelStatement : public Statement
private:
const DynamicModel& dynamic_model;
const bool write_equation_tags;
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 writeJsonOutput(ostream& output) const override;
};
@ -739,6 +802,7 @@ class WriteLatexStaticModelStatement : public Statement
private:
const StaticModel& static_model;
const bool write_equation_tags;
public:
WriteLatexStaticModelStatement(const StaticModel& static_model_arg, bool write_equation_tags_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -750,8 +814,10 @@ class WriteLatexOriginalModelStatement : public Statement
private:
const DynamicModel& original_model;
const bool write_equation_tags;
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 writeJsonOutput(ostream& output) const override;
};
@ -760,6 +826,7 @@ class WriteLatexSteadyStateModelStatement : public Statement
{
private:
const SteadyStateModel& steady_state_model;
public:
explicit WriteLatexSteadyStateModelStatement(const SteadyStateModel& steady_state_model_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -773,6 +840,7 @@ private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
ShockDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
@ -787,6 +855,7 @@ private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
RealtimeShockDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
@ -801,6 +870,7 @@ private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
PlotShockDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
@ -815,6 +885,7 @@ private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
InitialConditionDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
@ -828,6 +899,7 @@ class SqueezeShockDecompositionStatement : public Statement
private:
const SymbolList symbol_list;
const SymbolTable& symbol_table;
public:
SqueezeShockDecompositionStatement(SymbolList symbol_list_arg,
const SymbolTable& symbol_table_arg);
@ -840,6 +912,7 @@ class ConditionalForecastStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit ConditionalForecastStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -853,6 +926,7 @@ private:
const optional<int> periods; // The user is allowed not to declare periods
const SymbolList symbol_list;
const SymbolTable& symbol_table;
public:
PlotConditionalForecastStatement(optional<int> periods_arg, SymbolList symbol_list_arg,
const SymbolTable& symbol_table_arg);
@ -867,6 +941,7 @@ private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
CalibSmootherStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
@ -879,6 +954,7 @@ class ExtendedPathStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit ExtendedPathStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -900,15 +976,16 @@ public:
};
using svar_identification_restrictions_t = vector<svar_identification_restriction>;
private:
const svar_identification_restrictions_t restrictions;
const bool upper_cholesky_present, lower_cholesky_present, constants_exclusion_present;
const SymbolTable& symbol_table;
int getMaxLag() const;
public:
SvarIdentificationStatement(svar_identification_restrictions_t restrictions_arg,
bool upper_cholesky_present_arg,
bool lower_cholesky_present_arg,
bool upper_cholesky_present_arg, bool lower_cholesky_present_arg,
bool constants_exclusion_present_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -921,6 +998,7 @@ class MarkovSwitchingStatement : public Statement
private:
const OptionsList options_list;
map<pair<int, int>, double> restriction_map;
public:
explicit MarkovSwitchingStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -932,6 +1010,7 @@ class SvarStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit SvarStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -950,6 +1029,7 @@ class SetTimeStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit SetTimeStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -960,6 +1040,7 @@ class EstimationDataStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit EstimationDataStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -972,13 +1053,14 @@ class SubsamplesStatement : public Statement
public:
//! Storage for declaring subsamples: map<subsample_name, <date1, date2 >
using subsample_declaration_map_t = map<string, pair<string, string>>;
private:
const string name1, name2;
const subsample_declaration_map_t subsample_declaration_map;
const SymbolTable& symbol_table;
public:
SubsamplesStatement(string name1_arg,
string name2_arg,
SubsamplesStatement(string name1_arg, string name2_arg,
subsample_declaration_map_t subsample_declaration_map_arg,
const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -990,12 +1072,10 @@ class SubsamplesEqualStatement : public Statement
private:
const string to_name1, to_name2, from_name1, from_name2;
const SymbolTable& symbol_table;
public:
SubsamplesEqualStatement(string to_name1_arg,
string to_name2_arg,
string from_name1_arg,
string from_name2_arg,
const SymbolTable &symbol_table_arg);
SubsamplesEqualStatement(string to_name1_arg, string to_name2_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 writeJsonOutput(ostream& output) const override;
};
@ -1007,9 +1087,9 @@ private:
const PriorDistributions prior_shape;
const OptionsList options_list;
void writeOutputHelper(ostream& output, const string& field, const string& lhs_field) const;
public:
JointPriorStatement(vector<string> joint_parameters_arg,
PriorDistributions prior_shape_arg,
JointPriorStatement(vector<string> joint_parameters_arg, PriorDistributions prior_shape_arg,
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;
@ -1023,10 +1103,8 @@ protected:
const PriorDistributions prior_shape;
const expr_t variance;
const OptionsList options_list;
BasicPriorStatement(string name_arg,
string subsample_name_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
BasicPriorStatement(string name_arg, string subsample_name_arg,
PriorDistributions prior_shape_arg, expr_t variance_arg,
OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void get_base_name(const SymbolType symb_type, string& lhs_field) const;
@ -1045,11 +1123,8 @@ protected:
class PriorStatement : public BasicPriorStatement
{
public:
PriorStatement(string name_arg,
string subsample_name_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg);
PriorStatement(string name_arg, string subsample_name_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 writeJsonOutput(ostream& output) const override;
};
@ -1058,12 +1133,10 @@ class StdPriorStatement : public BasicPriorStatement
{
private:
const SymbolTable& symbol_table;
public:
StdPriorStatement(string name_arg,
string subsample_name_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg,
StdPriorStatement(string name_arg, string subsample_name_arg, PriorDistributions prior_shape_arg,
expr_t variance_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
@ -1074,14 +1147,11 @@ class CorrPriorStatement : public BasicPriorStatement
private:
const string name1;
const SymbolTable& symbol_table;
public:
CorrPriorStatement(string name_arg1,
string name_arg2,
string subsample_name_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg,
const SymbolTable &symbol_table_arg);
CorrPriorStatement(string name_arg1, string name_arg2, string subsample_name_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 writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
@ -1093,15 +1163,11 @@ private:
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 SymbolTable& symbol_table;
public:
PriorEqualStatement(string to_declaration_type_arg,
string to_name1_arg,
string to_name2_arg,
string to_subsample_name_arg,
string from_declaration_type_arg,
string from_name1_arg,
string from_name2_arg,
string from_subsample_name_arg,
PriorEqualStatement(string to_declaration_type_arg, string to_name1_arg, string to_name2_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);
void get_base_name(const SymbolType symb_type, string& lhs_field) const;
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -1114,9 +1180,7 @@ class BasicOptionsStatement : public Statement
protected:
const string name, subsample_name;
const OptionsList options_list;
BasicOptionsStatement(string name_arg,
string subsample_name_arg,
OptionsList options_list_arg);
BasicOptionsStatement(string name_arg, string subsample_name_arg, OptionsList options_list_arg);
void get_base_name(const SymbolType symb_type, string& lhs_field) const;
void writeOptionsOutput(ostream& output, string& lhs_field, const string& name2) const;
void writeCommonOutput(ostream& output, const string& lhs_field) const;
@ -1139,10 +1203,9 @@ class StdOptionsStatement : public BasicOptionsStatement
{
private:
const SymbolTable& symbol_table;
public:
StdOptionsStatement(string name_arg,
string subsample_name_arg,
OptionsList options_list_arg,
StdOptionsStatement(string name_arg, string subsample_name_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
@ -1153,11 +1216,10 @@ class CorrOptionsStatement : public BasicOptionsStatement
private:
const string name1;
const SymbolTable& symbol_table;
public:
CorrOptionsStatement(string name_arg1, string name_arg2,
string subsample_name_arg,
OptionsList options_list_arg,
const SymbolTable &symbol_table_arg);
CorrOptionsStatement(string name_arg1, string name_arg2, string subsample_name_arg,
OptionsList options_list_arg, const SymbolTable& symbol_table_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;
@ -1169,16 +1231,12 @@ private:
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 SymbolTable& symbol_table;
public:
OptionsEqualStatement(string to_declaration_type_arg,
string to_name1_arg,
string to_name2_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);
OptionsEqualStatement(string to_declaration_type_arg, string to_name1_arg, string to_name2_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);
void get_base_name(const SymbolType symb_type, string& lhs_field) const;
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -1196,6 +1254,7 @@ class Smoother2histvalStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit Smoother2histvalStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -1206,6 +1265,7 @@ class MethodOfMomentsStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MethodOfMomentsStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -1220,9 +1280,9 @@ private:
const OptionsList options_list;
const vector<string> generate_irf_names;
const vector<map<string, double>> generate_irf_elements;
public:
GenerateIRFsStatement(OptionsList options_list_arg,
vector<string> generate_irf_names_arg,
GenerateIRFsStatement(OptionsList options_list_arg, vector<string> generate_irf_names_arg,
vector<map<string, double>> generate_irf_elements_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
@ -1232,6 +1292,7 @@ class MatchedMomentsStatement : public Statement
{
private:
const SymbolTable& symbol_table;
public:
/* Each moment is represented by a three vectors: symb_ids, lags, powers.
See the definition of ExprNode::matchMatchedMoment() for more details */
@ -1246,10 +1307,13 @@ class OccbinConstraintsStatement : public Statement
{
private:
DataTree data_tree;
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;
OccbinConstraintsStatement(const DataTree &data_tree_arg,
OccbinConstraintsStatement(
const DataTree& data_tree_arg,
vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> constraints_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -1260,6 +1324,7 @@ class ResidStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit ResidStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;

View File

@ -17,8 +17,8 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <fstream>
#include <iostream>
#include <utility>
#include <vector>
@ -26,8 +26,8 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/tokenizer.hpp>
#pragma GCC diagnostic pop
@ -53,9 +53,11 @@ Path::Path(vector<string> includepath_arg)
paths["include"] = move(includepath_arg);
}
FollowerNode::FollowerNode(string computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string userName_arg,
string password_arg, string remoteDrive_arg, string remoteDirectory_arg,
string programPath_arg, string programConfig_arg, string matlabOctavePath_arg, bool singleCompThread_arg,
FollowerNode::FollowerNode(string computerName_arg, string port_arg, int minCpuNbr_arg,
int maxCpuNbr_arg, string userName_arg, string password_arg,
string remoteDrive_arg, string remoteDirectory_arg,
string programPath_arg, string programConfig_arg,
string matlabOctavePath_arg, bool singleCompThread_arg,
int numberOfThreadsPerJob_arg, string operatingSystem_arg) :
computerName {move(computerName_arg)},
port {move(port_arg)},
@ -81,13 +83,13 @@ FollowerNode::FollowerNode(string computerName_arg, string port_arg, int minCpuN
if (!operatingSystem.empty())
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);
}
}
Cluster::Cluster(member_nodes_t member_nodes_arg) :
member_nodes{move(member_nodes_arg)}
Cluster::Cluster(member_nodes_t member_nodes_arg) : member_nodes {move(member_nodes_arg)}
{
if (member_nodes.empty())
{
@ -99,7 +101,8 @@ Cluster::Cluster(member_nodes_t member_nodes_arg) :
ConfigFile::ConfigFile(bool parallel_arg, bool parallel_test_arg,
bool parallel_follower_open_mode_arg, bool parallel_use_psexec_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_use_psexec {parallel_use_psexec_arg},
cluster_name {move(cluster_name_arg)}
@ -117,8 +120,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
filesystem::path defaultConfigFile;
// Test OS and try to open default file
#if defined(_WIN32) || defined(__CYGWIN32__)
if (auto appdata = getenv("APPDATA");
appdata)
if (auto appdata = getenv("APPDATA"); appdata)
defaultConfigFile = filesystem::path {appdata} / "dynare.ini";
else
{
@ -132,8 +134,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
exit(EXIT_FAILURE);
}
#else
if (auto home = getenv("HOME");
home)
if (auto home = getenv("HOME"); home)
defaultConfigFile = filesystem::path {home} / ".dynare";
else
{
@ -151,7 +152,8 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
{
if (parallel || parallel_test)
{
cerr << "ERROR: Could not open the default config file (" << defaultConfigFile.string() << ")" << endl;
cerr << "ERROR: Could not open the default config file ("
<< defaultConfigFile.string() << ")" << endl;
exit(EXIT_FAILURE);
}
else
@ -163,14 +165,14 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
configFile.open(config_file, fstream::in);
if (!configFile.is_open())
{
cerr << "ERROR: Couldn't open file " << config_file.string() << endl;;
cerr << "ERROR: Couldn't open file " << config_file.string() << endl;
;
exit(EXIT_FAILURE);
}
}
string name, computerName, port, userName, password, remoteDrive,
remoteDirectory, programPath, programConfig, matlabOctavePath,
operatingSystem, global_init_file;
string name, computerName, port, userName, password, remoteDrive, remoteDirectory, programPath,
programConfig, matlabOctavePath, operatingSystem, global_init_file;
vector<string> includepath;
int minCpuNbr {0}, maxCpuNbr {0};
int numberOfThreadsPerJob {1};
@ -187,10 +189,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
if (line.empty() || !line.compare(0, 1, "#"))
continue;
if (line == "[node]"
|| line == "[cluster]"
|| line == "[hooks]"
|| line == "[paths]")
if (line == "[node]" || line == "[cluster]" || line == "[hooks]" || line == "[paths]")
{
if (!global_init_file.empty())
// we were just in [hooks]
@ -200,11 +199,10 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
addPathsConfFileElement(includepath);
else
// we were just in [node] or [cluster]
addParallelConfFileElement(inNode, inCluster, member_nodes, name,
computerName, port, minCpuNbr, maxCpuNbr, userName,
password, remoteDrive, remoteDirectory,
programPath, programConfig, matlabOctavePath, singleCompThread,
numberOfThreadsPerJob, operatingSystem);
addParallelConfFileElement(
inNode, inCluster, member_nodes, name, computerName, port, minCpuNbr, maxCpuNbr,
userName, password, remoteDrive, remoteDirectory, programPath, programConfig,
matlabOctavePath, singleCompThread, numberOfThreadsPerJob, operatingSystem);
//! Reset communication vars / option defaults
if (line == "[hooks]")
@ -236,9 +234,9 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
inPaths = false;
}
name = userName = computerName = port = password = remoteDrive
= remoteDirectory = programPath = programConfig = matlabOctavePath
= operatingSystem = global_init_file = "";
name = userName = computerName = port = password = remoteDrive = remoteDirectory
= programPath = programConfig = matlabOctavePath = operatingSystem = global_init_file
= "";
includepath.clear();
minCpuNbr = maxCpuNbr = 0;
numberOfThreadsPerJob = 1;
@ -251,7 +249,8 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
split(tokenizedLine, line, is_any_of("="));
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);
}
trim(tokenizedLine.front());
@ -263,12 +262,15 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
global_init_file = tokenizedLine.back();
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);
}
else
{
cerr << "ERROR: Unrecognized option " << tokenizedLine.front() << " in [hooks] block." << endl;
cerr << "ERROR: Unrecognized option " << tokenizedLine.front()
<< " in [hooks] block." << endl;
exit(EXIT_FAILURE);
}
else if (inPaths)
@ -286,16 +288,17 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
}
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);
}
else
{
cerr << "ERROR: Unrecognized option " << tokenizedLine.front() << " in [paths] block." << endl;
cerr << "ERROR: Unrecognized option " << tokenizedLine.front()
<< " in [paths] block." << endl;
exit(EXIT_FAILURE);
}
else
if (tokenizedLine.front() == "Name")
else if (tokenizedLine.front() == "Name")
name = tokenizedLine.back();
else if (tokenizedLine.front() == "CPUnbr")
{
@ -308,8 +311,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
minCpuNbr = 1;
maxCpuNbr = stoi(tokenizedCpuNbr.front());
}
else if (tokenizedCpuNbr.size() == 2
&& tokenizedCpuNbr[0].at(0) == '['
else if (tokenizedCpuNbr.size() == 2 && tokenizedCpuNbr[0].at(0) == '['
&& tokenizedCpuNbr[1].at(tokenizedCpuNbr[1].size() - 1) == ']')
{
tokenizedCpuNbr[0].erase(0, 1);
@ -354,8 +356,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
remoteDrive = tokenizedLine.back();
else if (tokenizedLine.front() == "RemoteDirectory")
remoteDirectory = tokenizedLine.back();
else if (tokenizedLine.front() == "DynarePath"
|| tokenizedLine.front() == "ProgramPath")
else if (tokenizedLine.front() == "DynarePath" || tokenizedLine.front() == "ProgramPath")
programPath = tokenizedLine.back();
else if (tokenizedLine.front() == "ProgramConfig")
programConfig = tokenizedLine.back();
@ -370,7 +371,9 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
singleCompThread = false;
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);
}
else if (tokenizedLine.front() == "OperatingSystem")
@ -380,8 +383,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
char_separator sep(" ,;", "()", drop_empty_tokens);
tokenizer tokens(tokenizedLine.back(), sep);
string node_name;
for (bool begin_weight{false};
const auto &token : tokens)
for (bool begin_weight {false}; const auto& token : tokens)
{
if (token == "(")
{
@ -401,7 +403,9 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
{
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);
}
else
@ -415,14 +419,18 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
auto weight = stod(token);
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);
}
member_nodes[node_name] = weight;
}
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);
}
}
@ -432,14 +440,17 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
member_nodes[node_name] = 1.0;
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);
}
}
}
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);
}
}
@ -450,9 +461,8 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
else if (!includepath.empty())
addPathsConfFileElement(includepath);
else
addParallelConfFileElement(inNode, inCluster, member_nodes, name,
computerName, port, minCpuNbr, maxCpuNbr, userName,
password, remoteDrive, remoteDirectory,
addParallelConfFileElement(inNode, inCluster, member_nodes, name, computerName, port, minCpuNbr,
maxCpuNbr, userName, password, remoteDrive, remoteDirectory,
programPath, programConfig, matlabOctavePath, singleCompThread,
numberOfThreadsPerJob, operatingSystem);
@ -464,7 +474,8 @@ ConfigFile::addHooksConfFileElement(string global_init_file)
{
if (global_init_file.empty())
{
cerr << "ERROR: The global initialization file must be passed to the GlobalInitFile option." << endl;
cerr << "ERROR: The global initialization file must be passed to the GlobalInitFile option."
<< endl;
exit(EXIT_FAILURE);
}
else
@ -484,11 +495,14 @@ ConfigFile::addPathsConfFileElement(vector<string> includepath)
}
void
ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, const member_nodes_t &member_nodes, const string &name,
const string &computerName, const string &port, int minCpuNbr, int maxCpuNbr,
const string &userName, const string &password, const string &remoteDrive,
const string &remoteDirectory, const string &programPath, const string &programConfig,
const string &matlabOctavePath, bool singleCompThread, int numberOfThreadsPerJob,
ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster,
const member_nodes_t& member_nodes, const string& name,
const string& computerName, const string& port,
int minCpuNbr, int maxCpuNbr, const string& userName,
const string& password, const string& remoteDrive,
const string& remoteDirectory, const string& programPath,
const string& programConfig, const string& matlabOctavePath,
bool singleCompThread, int numberOfThreadsPerJob,
const string& operatingSystem)
{
//! ADD NODE
@ -498,24 +512,22 @@ ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, const member
cerr << "Invalid option passed to [node]." << endl;
exit(EXIT_FAILURE);
}
else
if (name.empty() || follower_nodes.contains(name))
else if (name.empty() || follower_nodes.contains(name))
{
cerr << "ERROR: Every node must be assigned a unique name." << endl;
exit(EXIT_FAILURE);
}
else
follower_nodes.try_emplace(name, computerName, port, minCpuNbr, maxCpuNbr, userName,
password, remoteDrive, remoteDirectory, programPath, programConfig,
follower_nodes.try_emplace(name, computerName, port, minCpuNbr, maxCpuNbr, userName, password,
remoteDrive, remoteDirectory, programPath, programConfig,
matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
operatingSystem);
//! ADD CLUSTER
else if (inCluster)
{
if (minCpuNbr > 0 || maxCpuNbr > 0 || !userName.empty()
|| !password.empty() || !remoteDrive.empty() || !remoteDirectory.empty()
|| !programPath.empty() || !programConfig.empty()
|| !matlabOctavePath.empty() || !operatingSystem.empty())
if (minCpuNbr > 0 || maxCpuNbr > 0 || !userName.empty() || !password.empty()
|| !remoteDrive.empty() || !remoteDirectory.empty() || !programPath.empty()
|| !programConfig.empty() || !matlabOctavePath.empty() || !operatingSystem.empty())
{
cerr << "Invalid option passed to [cluster]." << endl;
exit(EXIT_FAILURE);
@ -537,8 +549,7 @@ ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, const member
void
ConfigFile::checkPass([[maybe_unused]] WarningConsolidation& warnings) const
{
for (bool global_init_file_declared{false};
const auto &hook : hooks)
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))
@ -573,19 +584,22 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
}
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);
}
if (follower_node.second.computerName == "localhost") // We are working locally
{
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);
}
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);
}
}
@ -593,19 +607,26 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
{
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);
}
if (follower_node.second.operatingSystem == "windows")
{
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);
}
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);
}
}
@ -614,19 +635,26 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
{
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);
}
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);
}
}
#endif
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);
}
}
@ -641,7 +669,8 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
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);
}
@ -649,7 +678,8 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
for (const auto& itmn : cluster.second.member_nodes)
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);
}
}
@ -670,7 +700,8 @@ ConfigFile::transformPass()
}
#endif
auto cluster_it = cluster_name.empty() ? clusters.find(firstClusterName) : clusters.find(cluster_name);
auto cluster_it
= cluster_name.empty() ? clusters.find(firstClusterName) : clusters.find(cluster_name);
double weight_denominator {0.0};
for (const auto& it : cluster_it->second.member_nodes)
@ -705,10 +736,10 @@ ConfigFile::writeCluster(ostream &output) const
if (!parallel && !parallel_test)
return;
auto cluster_it = cluster_name.empty() ? clusters.find(firstClusterName) : clusters.find(cluster_name);
auto cluster_it
= cluster_name.empty() ? clusters.find(firstClusterName) : clusters.find(cluster_name);
for (int i{1};
const auto &follower_node : follower_nodes)
for (int i {1}; const auto& follower_node : follower_nodes)
{
bool follower_node_in_member_nodes = false;
for (const auto& itmn : cluster_it->second.member_nodes)
@ -730,17 +761,20 @@ ConfigFile::writeCluster(ostream &output) const
output << "'ComputerName', '" << follower_node.second.computerName << "', "
<< "'Port', '" << follower_node.second.port << "', "
<< "'CPUnbr', [" << follower_node.second.minCpuNbr << ":" << follower_node.second.maxCpuNbr << "], "
<< "'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 << "', "
<< "'RemoteDirectory', '" << follower_node.second.remoteDirectory
<< "', "
// The following should be switched back to “ProgramPath” once we move to Dragonfly
<< "'DynarePath', '" << follower_node.second.programPath << "', "
<< "'ProgramConfig', '" << follower_node.second.programConfig << "', "
<< "'MatlabOctavePath', '" << follower_node.second.matlabOctavePath << "', "
<< "'OperatingSystem', '" << follower_node.second.operatingSystem << "', "
<< "'NodeWeight', '" << cluster_it->second.member_nodes.at(follower_node.first) << "', "
<< "'NodeWeight', '" << cluster_it->second.member_nodes.at(follower_node.first)
<< "', "
<< "'NumberOfThreadsPerJob', " << follower_node.second.numberOfThreadsPerJob << ", ";
if (follower_node.second.singleCompThread)
@ -749,7 +783,8 @@ ConfigFile::writeCluster(ostream &output) const
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)
output << "options_.parallel_info.leaveSlaveOpen = 1;" << endl;
if (!parallel_use_psexec)
@ -759,8 +794,12 @@ ConfigFile::writeCluster(ostream &output) const
output << "InitializeComputationalEnvironment();" << endl;
if (parallel_test)
output << "ErrorCode = AnalyseComputationalEnvironment(options_.parallel, options_.parallel_info);" << endl
<< "disp(['AnalyseComputationalEnvironment returned with Error Code: ' num2str(ErrorCode)]);" << endl
output
<< "ErrorCode = AnalyseComputationalEnvironment(options_.parallel, options_.parallel_info);"
<< endl
<< "disp(['AnalyseComputationalEnvironment returned with Error Code: ' "
"num2str(ErrorCode)]);"
<< endl
<< "diary off;" << endl
<< "return;" << endl;
}

View File

@ -20,9 +20,9 @@
#ifndef _CONFIG_FILE_HH
#define _CONFIG_FILE_HH
#include <filesystem>
#include <map>
#include <vector>
#include <filesystem>
#include "WarningConsolidation.hh"
@ -34,8 +34,10 @@ class Hook
{
public:
explicit Hook(string global_init_file_arg);
private:
map<string, string> hooks;
public:
map<string, string>
get_hooks() const
@ -48,8 +50,10 @@ class Path
{
public:
explicit Path(vector<string> includepath_arg);
private:
map<string, vector<string>> paths;
public:
map<string, vector<string>>
get_paths() const
@ -61,10 +65,12 @@ public:
class FollowerNode
{
friend class ConfigFile;
public:
FollowerNode(string computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string userName_arg,
string password_arg, string remoteDrive_arg, string remoteDirectory_arg,
string programPath_arg, string programConfig_arg, string matlabOctavePath_arg, bool singleCompThread_arg,
FollowerNode(string computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg,
string userName_arg, string password_arg, string remoteDrive_arg,
string remoteDirectory_arg, string programPath_arg, string programConfig_arg,
string matlabOctavePath_arg, bool singleCompThread_arg,
int numberOfThreadsPerJob_arg, string operatingSystem_arg);
protected:
@ -81,6 +87,7 @@ protected:
class Cluster
{
friend class ConfigFile;
public:
explicit Cluster(member_nodes_t member_nodes_arg);
@ -112,12 +119,15 @@ private:
//! Add Paths
void addPathsConfFileElement(vector<string> includepath);
//! Add a FollowerNode or a Cluster object
void addParallelConfFileElement(bool inNode, bool inCluster, const member_nodes_t &member_nodes, const string &name,
const string &computerName, const string &port, int minCpuNbr, int maxCpuNbr,
const string &userName, const string &password, const string &remoteDrive,
const string &remoteDirectory, const string &programPath, const string &programConfig,
const string &matlabOctavePath, bool singleCompThread, int numberOfThreadsPerJob,
const string &operatingSystem);
void addParallelConfFileElement(bool inNode, bool inCluster, const member_nodes_t& member_nodes,
const string& name, const string& computerName,
const string& port, int minCpuNbr, int maxCpuNbr,
const string& userName, const string& password,
const string& remoteDrive, const string& remoteDirectory,
const string& programPath, const string& programConfig,
const string& matlabOctavePath, bool singleCompThread,
int numberOfThreadsPerJob, const string& operatingSystem);
public:
//! Parse config file
void getConfigFileInfo(const filesystem::path& parallel_config_file);

View File

@ -17,13 +17,13 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cassert>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <iterator>
#include "DataTree.hh"
@ -46,10 +46,8 @@ DataTree::initConstants()
Pi = AddNonNegativeConstant("3.141592653589793");
}
DataTree::DataTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg,
bool is_dynamic_arg) :
DataTree::DataTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, bool is_dynamic_arg) :
symbol_table {symbol_table_arg},
num_constants {num_constants_arg},
external_functions_table {external_functions_table_arg},
@ -125,8 +123,7 @@ DataTree::AddNonNegativeConstant(const string &value)
{
int id = num_constants.AddNonNegativeConstant(value);
if (auto it = num_const_node_map.find(id);
it != num_const_node_map.end())
if (auto it = num_const_node_map.find(id); it != num_const_node_map.end())
return it->second;
auto sp = make_unique<NumConstNode>(*this, node_list.size(), id);
@ -145,8 +142,7 @@ DataTree::AddVariable(int symb_id, int lag)
exit(EXIT_FAILURE);
}
if (auto it = variable_node_map.find({ symb_id, lag });
it != variable_node_map.end())
if (auto it = variable_node_map.find({symb_id, lag}); it != variable_node_map.end())
return it->second;
auto sp = make_unique<VariableNode>(*this, node_list.size(), symb_id, lag);
@ -162,7 +158,8 @@ DataTree::getVariable(int symb_id, int lag) const
auto it = variable_node_map.find({symb_id, lag});
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);
}
return it->second;
@ -250,8 +247,7 @@ DataTree::AddUMinus(expr_t iArg1)
return Zero;
// Simplify -(-x) in x
if (auto uarg = dynamic_cast<UnaryOpNode *>(iArg1);
uarg && uarg->op_code == UnaryOpcode::uminus)
if (auto uarg = dynamic_cast<UnaryOpNode*>(iArg1); uarg && uarg->op_code == UnaryOpcode::uminus)
return uarg->arg;
return AddUnaryOp(UnaryOpcode::uminus, iArg1);
@ -668,7 +664,8 @@ DataTree::AddSteadyStateParamDeriv(expr_t iArg1, int param_symb_id)
expr_t
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
@ -680,8 +677,7 @@ DataTree::AddExpectation(int iArg1, expr_t iArg2)
expr_t
DataTree::AddVarExpectation(const string& model_name)
{
if (auto it = var_expectation_node_map.find(model_name);
it != var_expectation_node_map.end())
if (auto it = var_expectation_node_map.find(model_name); it != var_expectation_node_map.end())
return it->second;
auto sp = make_unique<VarExpectationNode>(*this, node_list.size(), model_name);
@ -694,8 +690,7 @@ DataTree::AddVarExpectation(const string &model_name)
expr_t
DataTree::AddPacExpectation(const string& model_name)
{
if (auto it = pac_expectation_node_map.find(model_name);
it != pac_expectation_node_map.end())
if (auto it = pac_expectation_node_map.find(model_name); it != pac_expectation_node_map.end())
return it->second;
auto sp = make_unique<PacExpectationNode>(*this, node_list.size(), model_name);
@ -757,35 +752,42 @@ DataTree::AddExternalFunction(int symb_id, const vector<expr_t> &arguments)
}
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);
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())
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();
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;
}
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);
if (auto it = second_deriv_external_function_node_map.find({ arguments, input_index1, input_index2,
top_level_symb_id });
if (auto it = second_deriv_external_function_node_map.find(
{arguments, input_index1, input_index2, top_level_symb_id});
it != second_deriv_external_function_node_map.end())
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();
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;
}
@ -897,7 +899,9 @@ DataTree::writeCHelpersDefinition(ostream &output) const
<< "inline double" << endl
<< "getPowerDeriv(double x, double p, int k)" << 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
<< " else" << endl
<< " {" << endl
@ -932,8 +936,7 @@ DataTree::strsplit(string_view str, char delim)
while (true)
{
size_t idx {str.find(delim)};
if (auto sub {str.substr(0, idx)};
!sub.empty())
if (auto sub {str.substr(0, idx)}; !sub.empty())
result.emplace_back(sub);
if (idx == string_view::npos)
break;

View File

@ -20,22 +20,22 @@
#ifndef _DATATREE_HH
#define _DATATREE_HH
#include <string>
#include <map>
#include <vector>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <utility>
#include <memory>
#include <filesystem>
#include <iomanip>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "SymbolTable.hh"
#include "NumericalConstants.hh"
#include "ExternalFunctionsTable.hh"
#include "ExprNode.hh"
#include "ExternalFunctionsTable.hh"
#include "NumericalConstants.hh"
#include "SubModel.hh"
#include "SymbolTable.hh"
using namespace std;
@ -60,8 +60,10 @@ private:
using variable_node_map_t = map<pair<int, int>, VariableNode*>;
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
using unary_op_node_map_t = map<tuple<expr_t, UnaryOpcode, int, int, int, string, vector<int>>, UnaryOpNode *>;
//! (arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags) ->
//! 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;
//! ( arg1, arg2, opCode, order of Power Derivative) -> BinaryOpNode
@ -89,11 +91,13 @@ private:
pac_target_nonstationary_node_map_t pac_target_nonstationary_node_map;
// (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;
// (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;
// Flag to disable simplifications related to commutativity of addition and multiplication
@ -102,7 +106,8 @@ private:
protected:
//! Stores local variables value (maps symbol ID to corresponding node)
map<int, expr_t> local_variables_table;
//! Stores the order of appearance of local variables in the model block. Needed following change in #563
//! Stores the order of appearance of local variables in the model block. Needed following change
//! in #563
vector<int> local_variables_vector;
//! Internal implementation of ParamUsedWithLeadLag()
@ -119,18 +124,20 @@ private:
//! The list of nodes
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 AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder = 0);
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 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);
//! Initializes the predefined constants, used only from the constructors
void initConstants();
public:
DataTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg,
bool is_static_args = false);
DataTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, bool is_static_args = false);
virtual ~DataTree() = default;
@ -261,9 +268,11 @@ public:
//! Adds an external function node
expr_t AddExternalFunction(int symb_id, const vector<expr_t>& arguments);
//! Adds an external function node for the first derivative of an external function
expr_t AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index);
expr_t AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index);
//! Adds an external function node for the second derivative of an external function
expr_t AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index1, int input_index2);
expr_t AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index1, int input_index2);
//! Checks if a given symbol is used somewhere in the data tree
bool isSymbolUsed(int symb_id) const;
//! Checks if a given unary op is used somewhere in the data tree
@ -274,7 +283,8 @@ public:
bool isBinaryOpUsed(BinaryOpcode opcode) const;
//! Checks if a given binary op is used somewhere in the data tree on an endogenous variable
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 */
int minLagForSymbol(int symb_id) const;
/* Writes definitions of C function helpers (getPowerDeriv(), sign()) as
@ -335,7 +345,8 @@ public:
//! Adds to the set all the deriv IDs corresponding to parameters
virtual void addAllParamDerivId(set<int>& deriv_id_set);
//! Returns bool indicating whether DataTree represents a Dynamic Model (returns true in DynamicModel.hh)
//! Returns bool indicating whether DataTree represents a Dynamic Model (returns true in
//! DynamicModel.hh)
virtual bool
isDynamic() const
{
@ -404,17 +415,19 @@ DataTree::AddPossiblyNegativeConstant(double v)
}
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 (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())
return it->second;
// 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
if (auto carg = dynamic_cast<NumConstNode *>(arg);
op_code != UnaryOpcode::uminus || !carg)
// Case where arg is a constant and op_code == UnaryOpcode::uminus (i.e. we're adding a negative
// constant) is skipped
if (auto carg = dynamic_cast<NumConstNode*>(arg); op_code != UnaryOpcode::uminus || !carg)
{
try
{
@ -427,10 +440,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();
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;
}
@ -453,7 +469,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();
node_list.push_back(move(sp));
binary_op_node_map.try_emplace({arg1, arg2, op_code, powerDerivOrder}, p);

File diff suppressed because it is too large Load Diff

View File

@ -20,11 +20,11 @@
#ifndef _DYNAMICMODEL_HH
#define _DYNAMICMODEL_HH
#include <fstream>
#include <filesystem>
#include <fstream>
#include "StaticModel.hh"
#include "Bytecode.hh"
#include "StaticModel.hh"
using namespace std;
@ -42,6 +42,7 @@ public:
variable is zero. Controlled by option balanced_growth_test_tol of the
model block. The default should not be too small (see dynare#1389). */
double balanced_growth_test_tol {1e-6};
private:
/* 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
@ -89,7 +90,8 @@ private:
int max_endo_lag_orig {0}, max_endo_lead_orig {0};
//! Maximum lag and lead over exogenous variables (positive values) of original model
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};
// Cross reference information: eq → set of (symb_id, lag) for each symbol type
@ -156,7 +158,8 @@ private:
void testTrendDerivativesEqualToZero(const eval_context_t& eval_context);
//! 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();
/* Compute the Jacobian column indices in the block decomposition case
@ -167,26 +170,28 @@ private:
//! Factorized code for substitutions of leads/lags
/*! \param[in] type determines which type of variables is concerned
\param[in] deterministic_model whether we are in a deterministic model (only for exogenous leads/lags)
\param[in] subset variables to which to apply the transformation (only for diff of forward vars)
\param[in] deterministic_model whether we are in a deterministic model (only for exogenous
leads/lags) \param[in] subset variables to which to apply the transformation (only for diff of
forward vars)
*/
void substituteLeadLagInternal(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)
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
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
derivatives at the same time (legacy representation) */
void writeDynamicMWrapperFunction(const string& name, const string& ending) const;
/* Helper for writing MATLAB/Octave functions for residuals/derivatives and
their temporary terms (legacy representation) */
void writeDynamicMFileHelper(const string &basename,
const string &name, const string &retvalname,
const string &name_tt, size_t ttlen,
const string &previous_tt_name,
void writeDynamicMFileHelper(const string& basename, const string& name, const string& retvalname,
const string& name_tt, size_t ttlen, const string& previous_tt_name,
const ostringstream& init_s, const ostringstream& end_s,
const ostringstream& s, const ostringstream& s_tt) const;
@ -221,7 +226,8 @@ private:
Returns a set of pairs (tag name, tag value) corresponding to the set of
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.
listed_eqs_by_tag describes a list of equations to remove (identified by
@ -240,12 +246,11 @@ private:
Returns a list of excluded variables (empty if
excluded_vars_change_type=false) */
vector<int> removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag,
bool exclude_eqs, bool excluded_vars_change_type,
vector<int> removeEquationsHelper(set<map<string, string>>& listed_eqs_by_tag, bool exclude_eqs,
bool excluded_vars_change_type,
vector<BinaryOpNode*>& all_equations,
vector<optional<int>>& all_equations_lineno,
EquationTags &all_equation_tags,
bool static_equations) const;
EquationTags& all_equation_tags, bool static_equations) const;
//! Compute autoregressive matrices of trend component models
/* The algorithm uses matching rules over expression trees. It cannot handle
@ -254,7 +259,8 @@ private:
//! Compute error component matrices of trend component_models
/*! 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)
lag, returns all the corresponding deriv_ids (by properly dealing with two
@ -278,8 +284,7 @@ protected:
}
public:
DynamicModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
DynamicModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
TrendComponentModelTable& trend_component_model_table_arg,
VarModelTable& var_model_table_arg);
@ -295,10 +300,11 @@ public:
//! 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 paramsDerivsOrder order of derivatives w.r. to a pair (endo/exo/exo_det, parameter) to be computed (>0 implies jacobianExo = true)
\param eval_context evaluation context for normalization
\param no_tmp_terms if true, no temporary terms will be computed in the dynamic files
\param derivsOrder order of derivatives w.r. to exo, exo_det and endo should be computed
(implies jacobianExo = true when order >= 2) \param paramsDerivsOrder order of derivatives w.r.
to a pair (endo/exo/exo_det, parameter) to be computed (>0 implies jacobianExo = true) \param
eval_context evaluation context for normalization \param no_tmp_terms if true, no temporary
terms will be computed in the dynamic files
*/
void computingPass(int derivsOrder, int paramsDerivsOrder, const eval_context_t& eval_context,
bool no_tmp_terms, bool block, bool use_dll);
@ -374,7 +380,8 @@ public:
void updateVarAndTrendModel() const;
//! 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
template<bool julia>
@ -383,7 +390,8 @@ public:
//! Creates mapping for variables and equations they are present in
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();
//! Find endogenous variables not used in model
@ -433,7 +441,8 @@ public:
auxiliary parameters have already been added to the symbol table.
It also assumes that the bind and relax tags have been cleared from
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, optional<int> lineno, map<string, string> eq_tags,
const vector<string>& regimes_bind, const vector<string>& regimes_relax);
//! Writes LaTeX file with the equations of the dynamic model
void writeLatexFile(const string& basename, bool write_equation_tags) const;
@ -471,8 +480,7 @@ public:
}
else
{
if (auto it = dyn_jacobian_cols_table.find(deriv_id);
it == dyn_jacobian_cols_table.end())
if (auto it = dyn_jacobian_cols_table.find(deriv_id); it == dyn_jacobian_cols_table.end())
throw UnknownDerivIDException();
else
return it->second;
@ -481,9 +489,9 @@ public:
int
getJacobianColsNbr(bool sparse) const override
{
return sparse ?
3*symbol_table.endo_nbr() + symbol_table.exo_nbr() + symbol_table.exo_det_nbr() :
dyn_jacobian_ncols;
return sparse
? 3 * symbol_table.endo_nbr() + symbol_table.exo_nbr() + symbol_table.exo_det_nbr()
: dyn_jacobian_ncols;
}
void addAllParamDerivId(set<int>& deriv_id_set) override;
@ -515,7 +523,8 @@ public:
//! Transforms the model by removing all UnaryOpcode::expectation
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();
// Performs the transformations associated to variables declared with “var(log)”
@ -548,20 +557,28 @@ public:
/* 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
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
substitution in growth terms of pac_model/pac_target_info and in
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
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
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()
struct PacTargetNotIdentifiedException
@ -578,26 +595,19 @@ public:
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.
*/
void computePacModelConsistentExpectationSubstitution(const string &name,
int discount_symb_id, int pac_eq_max_lag,
expr_t growth_correction_term,
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,
void computePacModelConsistentExpectationSubstitution(
const string& name, int discount_symb_id, int pac_eq_max_lag, expr_t growth_correction_term,
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);
/* For a PAC backward model, fill pac_expectation_substitution with the
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 ID of the new auxiliary variable is added to pac_aux_var_symb_ids. */
void computePacBackwardExpectationSubstitution(const string &name,
const vector<int> &lhs,
int max_lag,
const string &aux_model_type,
expr_t growth_correction_term,
string auxname,
void 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);
@ -610,10 +620,8 @@ public:
in target_components.
The routine also creates the auxiliary variables for the components, and
adds the corresponding equations. */
void computePacBackwardExpectationSubstitutionWithComponents(const string &name,
const vector<int> &lhs,
int max_lag,
const string &aux_model_type,
void computePacBackwardExpectationSubstitutionWithComponents(
const string& name, const vector<int>& lhs, int max_lag, const string& aux_model_type,
vector<PacModelTable::target_component_t>& pac_target_components,
map<string, expr_t>& pac_expectation_substitution);
@ -650,7 +658,8 @@ public:
auto
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_equations_equation_tags};
};
//! Returns true if a parameter was used in the model block with a lead or lag
@ -658,7 +667,8 @@ public:
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 */
void simplifyEquations();
@ -694,10 +704,11 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const
if (!params_derivatives.size())
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]
{ writeParamsDerivativesFileHelper<output_type>() };
auto [tt_output, rp_output, gp_output, rpp_output, gpp_output, hp_output,
g3p_output] {writeParamsDerivativesFileHelper<output_type>()};
if constexpr (!julia)
{
@ -708,79 +719,159 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
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
<< "% Compute the derivatives of the dynamic model with respect to the parameters" << endl
<< "% Inputs :" << endl
<< "% y [#dynamic variables by 1] double vector of endogenous variables in the order stored" << 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
<< "% y [#dynamic variables by 1] double vector of endogenous variables in "
"the order stored"
<< 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
<< "% params [M_.param_nbr by 1] double vector of parameter values in declaration order" << endl
<< "% steady_state [M_.endo_nbr by 1] double vector of steady state values" << 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
<< "% params [M_.param_nbr by 1] double vector of parameter values in "
"declaration order"
<< endl
<< "% steady_state [M_.endo_nbr by 1] double vector of steady state values"
<< 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
<< "% Outputs:" << endl
<< "% rp [M_.eq_nbr by #params] double Jacobian matrix of dynamic model equations with respect to parameters " << endl
<< "% Dynare may prepend or append auxiliary equations, see M_.aux_vars" << endl
<< "% 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
<< "% rows: equations in order of declaration" << endl
<< "% columns: variables in order stored in M_.lead_lag_incidence" << endl
<< "% rpp [#second_order_residual_terms by 4] double Hessian matrix of second derivatives of residuals with respect to parameters;" << endl
<< "% rows: respective derivative term" << endl
<< "% 1st column: equation number of the term appearing" << endl
<< "% 2nd column: number of the first parameter in derivative" << endl
<< "% 3rd column: number of the second parameter in derivative" << endl
<< "% 4th column: value of the Hessian term" << 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
<< "% rp [M_.eq_nbr by #params] double Jacobian matrix of dynamic model "
"equations with respect to parameters "
<< endl
<< "% Dynare may prepend or append "
"auxiliary equations, see M_.aux_vars"
<< endl
<< "% 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
<< "% rows: equations in order "
"of declaration"
<< endl
<< "% columns: variables in "
"order stored in M_.lead_lag_incidence"
<< endl
<< "% rpp [#second_order_residual_terms by 4] double Hessian matrix of second "
"derivatives of residuals with respect to parameters;"
<< endl
<< "% rows: respective "
"derivative term"
<< endl
<< "% 1st column: equation "
"number of the term appearing"
<< endl
<< "% 2nd column: number of "
"the first parameter in derivative"
<< endl
<< "% 3rd column: number of "
"the second parameter in derivative"
<< endl
<< "% 4th column: value of "
"the Hessian term"
<< 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
<< "% 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
<< tt_output.str()
<< "rp = zeros(" << equations.size() << ", "
<< tt_output.str() << "rp = zeros(" << equations.size() << ", "
<< symbol_table.param_nbr() << ");" << endl
<< rp_output.str()
<< "gp = zeros(" << equations.size() << ", " << getJacobianColsNbr(false) << ", " << symbol_table.param_nbr() << ");" << endl
<< gp_output.str()
<< "if nargout >= 3" << endl
<< rp_output.str() << "gp = zeros(" << equations.size() << ", "
<< getJacobianColsNbr(false) << ", " << symbol_table.param_nbr() << ");" << endl
<< gp_output.str() << "if nargout >= 3" << endl
<< "rpp = zeros(" << params_derivatives.at({0, 2}).size() << ",4);" << endl
<< rpp_output.str()
<< "gpp = zeros(" << params_derivatives.at({ 1, 2 }).size() << ",5);" << endl
<< gpp_output.str()
<< "end" << endl
<< rpp_output.str() << "gpp = zeros(" << params_derivatives.at({1, 2}).size() << ",5);"
<< endl
<< gpp_output.str() << "end" << endl
<< "if nargout >= 5" << endl
<< "hp = zeros(" << params_derivatives.at({2, 1}).size() << ",5);" << endl
<< hp_output.str()
<< "end" << endl
<< hp_output.str() << "end" << endl
<< "if nargout >= 6" << endl
<< "g3p = zeros(" << params_derivatives.at({3, 1}).size() << ",6);" << endl
<< g3p_output.str()
<< "end" << endl
<< g3p_output.str() << "end" << endl
<< "end" << endl;
paramsDerivsFile.close();
}
@ -793,25 +884,24 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const
<< "function dynamic_params_derivs(y, x, params, steady_state, it_,"
<< "ss_param_deriv, ss_param_2nd_deriv)" << endl
<< "@inbounds begin" << endl
<< tt_output.str()
<< "rp = zeros(" << equations.size() << ", "
<< tt_output.str() << "rp = zeros(" << equations.size() << ", "
<< symbol_table.param_nbr() << ");" << endl
<< rp_output.str()
<< "gp = zeros(" << equations.size() << ", " << getJacobianColsNbr(false) << ", " << symbol_table.param_nbr() << ");" << endl
<< gp_output.str()
<< "rpp = zeros(" << params_derivatives.at({ 0, 2 }).size() << ",4);" << endl
<< rpp_output.str()
<< "gpp = zeros(" << params_derivatives.at({ 1, 2 }).size() << ",5);" << endl
<< gpp_output.str()
<< "hp = zeros(" << params_derivatives.at({ 2, 1 }).size() << ",5);" << endl
<< hp_output.str()
<< "g3p = zeros(" << params_derivatives.at({ 3, 1 }).size() << ",6);" << endl
<< g3p_output.str()
<< "end" << endl
<< rp_output.str() << "gp = zeros(" << equations.size() << ", "
<< getJacobianColsNbr(false) << ", " << symbol_table.param_nbr() << ");" << endl
<< gp_output.str() << "rpp = zeros(" << params_derivatives.at({0, 2}).size() << ",4);"
<< endl
<< rpp_output.str() << "gpp = zeros(" << params_derivatives.at({1, 2}).size() << ",5);"
<< endl
<< gpp_output.str() << "hp = zeros(" << params_derivatives.at({2, 1}).size() << ",5);"
<< endl
<< hp_output.str() << "g3p = zeros(" << params_derivatives.at({3, 1}).size() << ",6);"
<< endl
<< g3p_output.str() << "end" << endl
<< "return (rp, gp, rpp, gpp, hp, g3p)" << endl
<< "end" << endl;
writeToFileIfModified(output, filesystem::path{basename} / "model" / "julia" / "DynamicParamsDerivs.jl");
writeToFileIfModified(output, filesystem::path {basename} / "model" / "julia"
/ "DynamicParamsDerivs.jl");
}
}

View File

@ -17,24 +17,24 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
#include <regex>
#include <thread>
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <thread>
#include <vector>
#include <cstdlib>
#include <unistd.h>
#include "ParsingDriver.hh"
#include "ExtendedPreprocessorTypes.hh"
#include "ConfigFile.hh"
#include "ExtendedPreprocessorTypes.hh"
#include "ModFile.hh"
#include "ParsingDriver.hh"
/* Prototype for the function that handles the macro-expansion of the .mod file
Splitting this out was necessary because ParsingDriver.hh and macro/Driver.hh can't be
@ -42,21 +42,27 @@
Function can be found in: MacroExpandModFile.cc
*/
stringstream
macroExpandModFile(const filesystem::path &filename, const istream &modfile,
bool debug, bool save_macro, filesystem::path save_macro_file, bool line_macro,
const vector<pair<string, string>> &defines,
stringstream macroExpandModFile(const filesystem::path& filename, const istream& modfile,
bool debug, bool save_macro, filesystem::path save_macro_file,
bool line_macro, const vector<pair<string, string>>& defines,
vector<filesystem::path> paths);
void
usage()
{
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [linemacro] [notmpterms] [nolog] [warn_uninit]"
<< " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_follower_open_mode] [parallel_test] [parallel_use_psexec=true|false]"
<< " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] [compute_xrefs] [output=second|third] [language=matlab|julia]"
<< " [params_derivs_order=0|1|2] [transform_unary_ops] [exclude_eqs=<equation_tag_list_or_file>] [include_eqs=<equation_tag_list_or_file>]"
<< " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] [nopathchange] [nopreprocessoroutput]"
<< " [mexext=<extension>] [matlabroot=<path>] [onlymodel] [notime] [use_dll] [nocommutativity]"
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] "
"[savemacro[=macro_file]] [onlymacro] [linemacro] [notmpterms] [nolog] [warn_uninit]"
<< " [console] [nograph] [nointeractive] [parallel[=cluster_name]] "
"[conffile=parallel_config_path_and_filename] [parallel_follower_open_mode] "
"[parallel_test] [parallel_use_psexec=true|false]"
<< " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] "
"[compute_xrefs] [output=second|third] [language=matlab|julia]"
<< " [params_derivs_order=0|1|2] [transform_unary_ops] "
"[exclude_eqs=<equation_tag_list_or_file>] [include_eqs=<equation_tag_list_or_file>]"
<< " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] "
"[nopathchange] [nopreprocessoroutput]"
<< " [mexext=<extension>] [matlabroot=<path>] [onlymodel] [notime] [use_dll] "
"[nocommutativity]"
<< endl;
exit(EXIT_FAILURE);
}
@ -75,13 +81,12 @@ parse_options_line(istream &modfile)
while (getline(modfile, first_nonempty_line))
if (!first_nonempty_line.empty())
{
if (regex_search(first_nonempty_line, matches, pat)
&& matches.size() > 1 && matches[1].matched)
if (regex_search(first_nonempty_line, matches, pat) && matches.size() > 1
&& matches[1].matched)
{
regex pat2 {R"([^,\s]+)"};
string s {matches[1]};
for (sregex_iterator p(s.begin(), s.end(), pat2);
p != sregex_iterator{}; ++p)
for (sregex_iterator p(s.begin(), s.end(), pat2); p != sregex_iterator {}; ++p)
options.push_back(p->str());
}
break;
@ -140,7 +145,8 @@ main(int argc, char **argv)
filesystem::path parallel_config_file;
bool parallel = false;
string cluster_name;
bool parallel_follower_open_mode = false; // Must be the same default as in matlab/default_option_values.m
bool parallel_follower_open_mode
= false; // Must be the same default as in matlab/default_option_values.m
bool parallel_test = false;
bool parallel_use_psexec = true; // Must be the same default as in matlab/default_option_values.m
bool nostrict = false;
@ -289,8 +295,7 @@ main(int argc, char **argv)
usage();
}
if (auto equal_index = s.find('=');
equal_index != string::npos)
if (auto equal_index = s.find('='); equal_index != string::npos)
defines.emplace_back(s.substr(2, equal_index - 2), s.substr(equal_index + 1));
else
defines.emplace_back(s.substr(2), "true");
@ -456,7 +461,8 @@ main(int argc, char **argv)
WarningConsolidation warnings(no_warn);
// Process config file
ConfigFile config_file(parallel, parallel_test, parallel_follower_open_mode, parallel_use_psexec, cluster_name);
ConfigFile config_file(parallel, parallel_test, parallel_follower_open_mode, parallel_use_psexec,
cluster_name);
config_file.getConfigFileInfo(parallel_config_file);
config_file.checkPass(warnings);
config_file.transformPass();
@ -469,8 +475,8 @@ main(int argc, char **argv)
/*
* Macro-expand MOD file
*/
stringstream macro_output =
macroExpandModFile(filename, modfile, debug, save_macro, move(save_macro_file), line_macro,
stringstream macro_output
= macroExpandModFile(filename, modfile, debug, save_macro, move(save_macro_file), line_macro,
defines, move(paths));
if (only_macro)
@ -503,8 +509,8 @@ main(int argc, char **argv)
}
if (mod_file->use_dll)
ModelTree::initializeMEXCompilationWorkers(max(jthread::hardware_concurrency(), 1U),
dynareroot, mexext);
ModelTree::initializeMEXCompilationWorkers(max(jthread::hardware_concurrency(), 1U), dynareroot,
mexext);
if (json == JsonOutputPointType::parsing)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
@ -515,7 +521,8 @@ main(int argc, char **argv)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
// Perform transformations on the model (creation of auxiliary vars and equations)
mod_file->transformPass(nostrict, stochastic, compute_xrefs || json == JsonOutputPointType::transformpass,
mod_file->transformPass(nostrict, stochastic,
compute_xrefs || json == JsonOutputPointType::transformpass,
transform_unary_ops, exclude_eqs, include_eqs);
if (json == JsonOutputPointType::transformpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
@ -533,8 +540,8 @@ main(int argc, char **argv)
mod_file->writeJuliaOutput(basename);
else
mod_file->writeMOutput(basename, clear_all, clear_global, no_warn, console, nograph,
nointeractive, config_file, check_model_changes, minimal_workspace, compute_xrefs,
mexext, matlabroot, onlymodel, gui, notime);
nointeractive, config_file, check_model_changes, minimal_workspace,
compute_xrefs, mexext, matlabroot, onlymodel, gui, notime);
/* Ensures that workers are not destroyed before they finish compiling.
Also ensures that the preprocessor final message is printed after the end of

View File

@ -19,8 +19,8 @@
#include "EquationTags.hh"
#include <regex>
#include <ostream>
#include <regex>
#include <utility>
set<int>
@ -62,8 +62,7 @@ EquationTags::getEqnsByTags(const map<string, string> &tags_selected) const
if (auto tmp = tags.find(key); tmp == tags.end() || tmp->second != value)
goto next_eq;
retval.insert(eqn);
next_eq:
;
next_eq:;
}
return retval;
}
@ -89,8 +88,7 @@ EquationTags::writeCheckSumInfo(ostream &output) const
{
for (const auto& [eqn, tags] : eqn_tags)
for (const auto& [key, value] : tags)
output << " " << eqn + 1
<< key << " " << value << endl;
output << " " << eqn + 1 << key << " " << value << endl;
}
void
@ -99,8 +97,7 @@ EquationTags::writeOutput(ostream &output) const
output << "M_.equations_tags = {" << endl;
for (const auto& [eqn, tags] : eqn_tags)
for (const auto& [key, value] : tags)
output << " " << eqn + 1 << " , '"
<< key << "' , '" << value << "' ;" << endl;
output << " " << eqn + 1 << " , '" << key << "' , '" << value << "' ;" << endl;
output << "};" << endl;
}
@ -110,8 +107,7 @@ EquationTags::writeLatexOutput(ostream &output, int eqn) const
if (!eqn_tags.contains(eqn))
return;
auto escape_special_latex_symbols = [](string str)
{
auto escape_special_latex_symbols = [](string str) {
const regex special_latex_chars(R"([&%$#_{}])");
const regex backslash(R"(\\)");
const regex tilde(R"(~)");
@ -125,8 +121,7 @@ EquationTags::writeLatexOutput(ostream &output, int eqn) const
};
output << R"(\noindent[)";
for (bool wrote_eq_tag {false};
const auto & [key, value] : eqn_tags.at(eqn))
for (bool wrote_eq_tag {false}; const auto& [key, value] : eqn_tags.at(eqn))
{
if (exchange(wrote_eq_tag, true))
output << ", ";
@ -145,8 +140,7 @@ EquationTags::writeJsonAST(ostream &output, int eqn) const
return;
output << R"(, "tags": {)";
for (bool wroteFirst {false};
const auto &[key, value] : eqn_tags.at(eqn))
for (bool wroteFirst {false}; const auto& [key, value] : eqn_tags.at(eqn))
{
if (exchange(wroteFirst, true))
output << ", ";

View File

@ -21,9 +21,9 @@
#define _EQUATION_TAGS_HH
#include <map>
#include <optional>
#include <set>
#include <string>
#include <optional>
using namespace std;
@ -31,6 +31,7 @@ class EquationTags
{
private:
map<int, map<string, string>> eqn_tags;
public:
// Add multiple equation tags for the given equation
void

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,16 +17,17 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include "ExternalFunctionsTable.hh"
#include "SymbolTable.hh"
void
ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function_options &external_function_options_arg, bool track_nargs)
ExternalFunctionsTable::addExternalFunction(
int symb_id, const external_function_options& external_function_options_arg, bool track_nargs)
{
assert(symb_id >= 0);
assert(external_function_options_arg.nargs > 0);
@ -63,11 +64,14 @@ ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function
if (external_function_options_chng.secondDerivSymbID != IDNotSet
&& external_function_options_chng.firstDerivSymbID == IDNotSet)
{
cerr << "ERROR: If the second derivative is provided, the first derivative must also be provided." << endl;
cerr << "ERROR: If the second derivative is provided, the first derivative must also be "
"provided."
<< endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.secondDerivSymbID == external_function_options_chng.firstDerivSymbID
if (external_function_options_chng.secondDerivSymbID
== external_function_options_chng.firstDerivSymbID
&& external_function_options_chng.firstDerivSymbID != symb_id
&& external_function_options_chng.firstDerivSymbID != IDNotSet)
{
@ -80,29 +84,40 @@ ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function
if (exists(symb_id))
{
bool ok_to_overwrite = false;
if (getNargs(symb_id) == IDNotSet) // implies that the information stored about this function is not important
if (getNargs(symb_id)
== IDNotSet) // implies that the information stored about this function is not important
ok_to_overwrite = true;
if (!ok_to_overwrite) // prevents multiple non-compatible calls to external_function(name=funcname)
if (!ok_to_overwrite) // prevents multiple non-compatible calls to
// external_function(name=funcname)
{ // e.g. e_f(name=a,nargs=1,fd,sd) and e_f(name=a,nargs=2,fd=b,sd=c) should cause an error
if (external_function_options_chng.nargs != getNargs(symb_id))
{
cerr << "ERROR: The number of arguments passed to the external_function() statement do not "
<< "match the number of arguments passed to a previous call or declaration of the top-level function."<< endl;
cerr << "ERROR: The number of arguments passed to the external_function() statement "
"do not "
<< "match the number of arguments passed to a previous call or declaration of "
"the top-level function."
<< endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.firstDerivSymbID != getFirstDerivSymbID(symb_id))
{
cerr << "ERROR: The first derivative function passed to the external_function() statement does not "
<< "match the first derivative function passed to a previous call or declaration of the top-level function."<< endl;
cerr << "ERROR: The first derivative function passed to the external_function() "
"statement does not "
<< "match the first derivative function passed to a previous call or "
"declaration of the top-level function."
<< endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.secondDerivSymbID != getSecondDerivSymbID(symb_id))
{
cerr << "ERROR: The second derivative function passed to the external_function() statement does not "
<< "match the second derivative function passed to a previous call or declaration of the top-level function."<< endl;
cerr << "ERROR: The second derivative function passed to the external_function() "
"statement does not "
<< "match the second derivative function passed to a previous call or "
"declaration of the top-level function."
<< endl;
exit(EXIT_FAILURE);
}
}

View File

@ -20,11 +20,11 @@
#ifndef _EXTERNALFUNCTIONSTABLE_HH
#define _EXTERNALFUNCTIONSTABLE_HH
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
@ -55,12 +55,16 @@ public:
constexpr static int IDSetButNoNameProvided = -2;
//! Default number of arguments when nargs is not specified
constexpr static int defaultNargs = 1;
private:
//! Map containing options provided to external_functions()
external_function_table_type externalFunctionTable;
public:
//! Adds an external function to the table as well as its derivative functions
void addExternalFunction(int symb_id, const external_function_options &external_function_options_arg, bool track_nargs);
void addExternalFunction(int symb_id,
const external_function_options& external_function_options_arg,
bool track_nargs);
//! See if the function exists in the External Functions Table
inline bool exists(int symb_id) const;
//! Get the number of arguments for a given external function
@ -80,8 +84,7 @@ ExternalFunctionsTable::exists(int symb_id) const
inline int
ExternalFunctionsTable::getNargs(int symb_id) const noexcept(false)
{
if (auto it = externalFunctionTable.find(symb_id);
it != externalFunctionTable.end())
if (auto it = externalFunctionTable.find(symb_id); it != externalFunctionTable.end())
return it->second.nargs;
else
throw UnknownExternalFunctionSymbolIDException {symb_id};
@ -90,8 +93,7 @@ ExternalFunctionsTable::getNargs(int symb_id) const noexcept(false)
inline int
ExternalFunctionsTable::getFirstDerivSymbID(int symb_id) const noexcept(false)
{
if (auto it = externalFunctionTable.find(symb_id);
it != externalFunctionTable.end())
if (auto it = externalFunctionTable.find(symb_id); it != externalFunctionTable.end())
return it->second.firstDerivSymbID;
else
throw UnknownExternalFunctionSymbolIDException {symb_id};
@ -100,8 +102,7 @@ ExternalFunctionsTable::getFirstDerivSymbID(int symb_id) const noexcept(false)
inline int
ExternalFunctionsTable::getSecondDerivSymbID(int symb_id) const noexcept(false)
{
if (auto it = externalFunctionTable.find(symb_id);
it != externalFunctionTable.end())
if (auto it = externalFunctionTable.find(symb_id); it != externalFunctionTable.end())
return it->second.secondDerivSymbID;
else
throw UnknownExternalFunctionSymbolIDException {symb_id};

View File

@ -17,19 +17,18 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <regex>
#include <sstream>
#include <fstream>
#include <filesystem>
#include <algorithm>
#include "macro/Driver.hh"
stringstream
macroExpandModFile(const filesystem::path &filename, const istream &modfile,
bool debug, bool save_macro, filesystem::path save_macro_file, bool line_macro,
const vector<pair<string, string>> &defines,
vector<filesystem::path> paths)
macroExpandModFile(const filesystem::path& filename, const istream& modfile, bool debug,
bool save_macro, filesystem::path save_macro_file, bool line_macro,
const vector<pair<string, string>>& defines, vector<filesystem::path> paths)
{
// Do macro processing
stringstream macro_output;

View File

@ -17,22 +17,22 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <typeinfo>
#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <random>
#include <typeinfo>
#include <filesystem>
#include "ModFile.hh"
#include "ConfigFile.hh"
#include "ComputingTasks.hh"
#include "ConfigFile.hh"
#include "ModFile.hh"
#include "Shocks.hh"
ModFile::ModFile(WarningConsolidation &warnings_arg)
: var_model_table{symbol_table},
ModFile::ModFile(WarningConsolidation& warnings_arg) :
var_model_table {symbol_table},
trend_component_model_table {symbol_table},
var_expectation_model_table {symbol_table},
pac_model_table {symbol_table},
@ -45,8 +45,8 @@ ModFile::ModFile(WarningConsolidation &warnings_arg)
trend_component_model_table, var_model_table},
orig_ramsey_dynamic_model {symbol_table, num_constants, external_functions_table,
trend_component_model_table, var_model_table},
epilogue{symbol_table, num_constants, external_functions_table,
trend_component_model_table, var_model_table},
epilogue {symbol_table, num_constants, external_functions_table, trend_component_model_table,
var_model_table},
static_model {symbol_table, num_constants, external_functions_table},
steady_state_model {symbol_table, num_constants, external_functions_table, static_model},
warnings {warnings_arg}
@ -77,13 +77,14 @@ ModFile::evalAllExpressions(bool warn_uninit)
// Check if some symbols are not initialized, and give them a zero value then
for (int id = 0; id <= symbol_table.maxID(); id++)
if (auto type = symbol_table.getType(id);
(type == SymbolType::endogenous || type == SymbolType::exogenous || type == SymbolType::exogenousDet
|| type == SymbolType::parameter || type == SymbolType::modelLocalVariable)
(type == SymbolType::endogenous || type == SymbolType::exogenous
|| type == SymbolType::exogenousDet || type == SymbolType::parameter
|| type == SymbolType::modelLocalVariable)
&& !global_eval_context.contains(id))
{
if (warn_uninit)
warnings << "WARNING: Can't find a numeric initial value for "
<< symbol_table.getName(id) << ", using zero" << endl;
warnings << "WARNING: Can't find a numeric initial value for " << symbol_table.getName(id)
<< ", using zero" << endl;
global_eval_context[id] = 0;
}
}
@ -117,7 +118,9 @@ ModFile::checkPass(bool nostrict, bool stochastic)
if (mod_file_struct.write_latex_steady_state_model_present
&& !mod_file_struct.steady_state_model_present)
{
cerr << "ERROR: You cannot have a write_latex_steady_state_model statement without a steady_state_model block." << endl;
cerr << "ERROR: You cannot have a write_latex_steady_state_model statement without a "
"steady_state_model block."
<< endl;
exit(EXIT_FAILURE);
}
@ -129,20 +132,16 @@ ModFile::checkPass(bool nostrict, bool stochastic)
if (param_used_with_lead_lag)
warnings << "WARNING: A parameter was used with a lead or a lag in the model block" << endl;
bool stochastic_statement_present = mod_file_struct.stoch_simul_present
|| mod_file_struct.estimation_present
|| mod_file_struct.osr_present
|| mod_file_struct.discretionary_policy_present
|| mod_file_struct.calib_smoother_present
|| mod_file_struct.identification_present
|| mod_file_struct.mom_estimation_present
|| mod_file_struct.sensitivity_present
bool stochastic_statement_present
= mod_file_struct.stoch_simul_present || mod_file_struct.estimation_present
|| mod_file_struct.osr_present || mod_file_struct.discretionary_policy_present
|| mod_file_struct.calib_smoother_present || mod_file_struct.identification_present
|| mod_file_struct.mom_estimation_present || mod_file_struct.sensitivity_present
|| stochastic;
// Allow empty model only when doing a standalone BVAR estimation
if (dynamic_model.equation_number() == 0
&& (mod_file_struct.check_present
|| mod_file_struct.perfect_foresight_solver_present
&& (mod_file_struct.check_present || mod_file_struct.perfect_foresight_solver_present
|| mod_file_struct.perfect_foresight_with_expectation_errors_solver_present
|| stochastic_statement_present))
{
@ -152,7 +151,9 @@ ModFile::checkPass(bool nostrict, bool stochastic)
if (mod_file_struct.ramsey_model_present && mod_file_struct.discretionary_policy_present)
{
cerr << "ERROR: You cannot use the discretionary_policy command when you use either ramsey_model or ramsey_policy and vice versa" << endl;
cerr << "ERROR: You cannot use the discretionary_policy command when you use either "
"ramsey_model or ramsey_policy and vice versa"
<< endl;
exit(EXIT_FAILURE);
}
@ -161,28 +162,40 @@ ModFile::checkPass(bool nostrict, bool stochastic)
|| (!(mod_file_struct.ramsey_model_present || mod_file_struct.discretionary_policy_present)
&& mod_file_struct.planner_objective_present))
{
cerr << "ERROR: A planner_objective statement must be used with a ramsey_model, a ramsey_policy or a discretionary_policy statement and vice versa." << endl;
cerr << "ERROR: A planner_objective statement must be used with a ramsey_model, a "
"ramsey_policy or a discretionary_policy statement and vice versa."
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.ramsey_constraints_present && !mod_file_struct.ramsey_model_present)
{
cerr << "ERROR: A ramsey_constraints block requires the presence of a ramsey_model or ramsey_policy statement" << endl;
cerr << "ERROR: A ramsey_constraints block requires the presence of a ramsey_model or "
"ramsey_policy statement"
<< endl;
exit(EXIT_FAILURE);
}
if ((mod_file_struct.osr_present && (!mod_file_struct.osr_params_present || !mod_file_struct.optim_weights_present))
|| ((!mod_file_struct.osr_present || !mod_file_struct.osr_params_present) && mod_file_struct.optim_weights_present)
|| ((!mod_file_struct.osr_present || !mod_file_struct.optim_weights_present) && mod_file_struct.osr_params_present))
if ((mod_file_struct.osr_present
&& (!mod_file_struct.osr_params_present || !mod_file_struct.optim_weights_present))
|| ((!mod_file_struct.osr_present || !mod_file_struct.osr_params_present)
&& mod_file_struct.optim_weights_present)
|| ((!mod_file_struct.osr_present || !mod_file_struct.optim_weights_present)
&& mod_file_struct.osr_params_present))
{
cerr << "ERROR: The osr statement must be used with osr_params and optim_weights." << endl;
exit(EXIT_FAILURE);
}
if ((mod_file_struct.perfect_foresight_solver_present || mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
if ((mod_file_struct.perfect_foresight_solver_present
|| mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
&& stochastic_statement_present)
{
cerr << "ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul, perfect_foresight_with_expectation_errors_solver} and one of {stoch_simul, estimation, osr, ramsey_policy, discretionary_policy}. This is not possible: one cannot mix perfect foresight context with stochastic context in the same file." << endl;
cerr << "ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul, "
"perfect_foresight_with_expectation_errors_solver} and one of {stoch_simul, "
"estimation, osr, ramsey_policy, discretionary_policy}. This is not possible: one "
"cannot mix perfect foresight context with stochastic context in the same file."
<< endl;
exit(EXIT_FAILURE);
}
@ -192,15 +205,20 @@ ModFile::checkPass(bool nostrict, bool stochastic)
exit(EXIT_FAILURE);
}
if ((stochastic_statement_present || mod_file_struct.check_present || mod_file_struct.steady_present) && no_static)
if ((stochastic_statement_present || mod_file_struct.check_present
|| mod_file_struct.steady_present)
&& no_static)
{
cerr << "ERROR: no_static option is incompatible with stoch_simul, estimation, osr, ramsey_policy, discretionary_policy, steady and check commands" << endl;
cerr << "ERROR: no_static option is incompatible with stoch_simul, estimation, osr, "
"ramsey_policy, discretionary_policy, steady and check commands"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.dsge_var_estimated && !mod_file_struct.dsge_prior_weight_in_estimated_params)
{
cerr << "ERROR: When estimating a DSGE-VAR model and estimating the weight of the prior, dsge_prior_weight must "
cerr << "ERROR: When estimating a DSGE-VAR model and estimating the weight of the prior, "
"dsge_prior_weight must "
<< "be referenced in the estimated_params block." << endl;
exit(EXIT_FAILURE);
}
@ -219,19 +237,23 @@ ModFile::checkPass(bool nostrict, bool stochastic)
if (mod_file_struct.dsge_var_estimated || !mod_file_struct.dsge_var_calibrated.empty())
{
cerr << "ERROR: dsge_prior_weight can either be declared as a parameter (deprecated) or via the dsge_var option "
cerr << "ERROR: dsge_prior_weight can either be declared as a parameter (deprecated) or "
"via the dsge_var option "
<< "to the estimation statement (preferred), but not both." << endl;
exit(EXIT_FAILURE);
}
if (!mod_file_struct.dsge_prior_weight_initialized && !mod_file_struct.dsge_prior_weight_in_estimated_params)
if (!mod_file_struct.dsge_prior_weight_initialized
&& !mod_file_struct.dsge_prior_weight_in_estimated_params)
{
cerr << "ERROR: If dsge_prior_weight is declared as a parameter, it must either be initialized or placed in the "
cerr << "ERROR: If dsge_prior_weight is declared as a parameter, it must either be "
"initialized or placed in the "
<< "estimated_params block." << endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.dsge_prior_weight_initialized && mod_file_struct.dsge_prior_weight_in_estimated_params)
if (mod_file_struct.dsge_prior_weight_initialized
&& mod_file_struct.dsge_prior_weight_in_estimated_params)
{
cerr << "ERROR: dsge_prior_weight cannot be both initialized and estimated." << endl;
exit(EXIT_FAILURE);
@ -242,28 +264,36 @@ ModFile::checkPass(bool nostrict, bool stochastic)
{
if (!mod_file_struct.dsge_var_estimated && !mod_file_struct.dsge_var_calibrated.empty())
{
cerr << "ERROR: If dsge_prior_weight is in the estimated_params block, the prior weight cannot be calibrated "
cerr << "ERROR: If dsge_prior_weight is in the estimated_params block, the prior weight "
"cannot be calibrated "
<< "via the dsge_var option in the estimation statement." << endl;
exit(EXIT_FAILURE);
}
else if (!mod_file_struct.dsge_var_estimated && !symbol_table.exists("dsge_prior_weight"))
{
cerr << "ERROR: If dsge_prior_weight is in the estimated_params block, it must either be declared as a parameter "
<< "(deprecated) or the dsge_var option must be passed to the estimation statement (preferred)." << endl;
cerr << "ERROR: If dsge_prior_weight is in the estimated_params block, it must either be "
"declared as a parameter "
<< "(deprecated) or the dsge_var option must be passed to the estimation statement "
"(preferred)."
<< endl;
exit(EXIT_FAILURE);
}
}
if (dynamic_model.staticOnlyEquationsNbr() != dynamic_model.dynamicOnlyEquationsNbr())
{
cerr << "ERROR: the number of equations marked [static] must be equal to the number of equations marked [dynamic]" << endl;
cerr << "ERROR: the number of equations marked [static] must be equal to the number of "
"equations marked [dynamic]"
<< endl;
exit(EXIT_FAILURE);
}
if (dynamic_model.staticOnlyEquationsNbr() > 0
&& (mod_file_struct.ramsey_model_present || mod_file_struct.discretionary_policy_present))
{
cerr << "ERROR: marking equations as [static] or [dynamic] is not possible with ramsey_model, ramsey_policy or discretionary_policy" << endl;
cerr << "ERROR: marking equations as [static] or [dynamic] is not possible with "
"ramsey_model, ramsey_policy or discretionary_policy"
<< endl;
exit(EXIT_FAILURE);
}
@ -278,7 +308,9 @@ ModFile::checkPass(bool nostrict, bool stochastic)
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::lessEqual)
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::equalEqual)
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::different)))
warnings << R"(WARNING: you are using a function (max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) which is unsuitable for a stochastic context; see the reference manual, section about "Expressions", for more details.)" << endl;
warnings
<< R"(WARNING: you are using a function (max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) which is unsuitable for a stochastic context; see the reference manual, section about "Expressions", for more details.)"
<< endl;
if (linear
&& (dynamic_model.isUnaryOpUsedOnType(SymbolType::endogenous, UnaryOpcode::sign)
@ -298,8 +330,7 @@ ModFile::checkPass(bool nostrict, bool stochastic)
exit(EXIT_FAILURE);
}
if (linear
&& !mod_file_struct.perfect_foresight_solver_present
if (linear && !mod_file_struct.perfect_foresight_solver_present
&& !mod_file_struct.perfect_foresight_with_expectation_errors_solver_present
&& (dynamic_model.isUnaryOpUsedOnType(SymbolType::exogenous, UnaryOpcode::sign)
|| dynamic_model.isUnaryOpUsedOnType(SymbolType::exogenous, UnaryOpcode::abs)
@ -329,23 +360,23 @@ ModFile::checkPass(bool nostrict, bool stochastic)
if (parameters_intersect.size() > 0)
{
cerr << "ERROR: some estimated parameters (";
for (bool printed_something{false};
int symb_id : parameters_intersect)
for (bool printed_something {false}; int symb_id : parameters_intersect)
{
if (exchange(printed_something, true))
cerr << ", ";
cerr << symbol_table.getName(symb_id);
}
cerr << ") also appear in the expressions defining the variance/covariance matrix of shocks; this is not allowed." << endl;
cerr << ") also appear in the expressions defining the variance/covariance matrix of shocks; "
"this is not allowed."
<< endl;
exit(EXIT_FAILURE);
}
// Check if some exogenous is not used in the model block, Issue #841
set<int> unusedExo0 = dynamic_model.findUnusedExogenous();
set<int> unusedExo;
set_difference(unusedExo0.begin(), unusedExo0.end(),
mod_file_struct.pac_params.begin(), mod_file_struct.pac_params.end(),
inserter(unusedExo, unusedExo.begin()));
set_difference(unusedExo0.begin(), unusedExo0.end(), mod_file_struct.pac_params.begin(),
mod_file_struct.pac_params.end(), inserter(unusedExo, unusedExo.begin()));
if (unusedExo.size() > 0)
{
ostringstream unused_exos;
@ -357,7 +388,10 @@ ModFile::checkPass(bool nostrict, bool stochastic)
<< "not used in model block, removed by nostrict command-line option" << endl;
else
{
cerr << "ERROR: " << unused_exos.str() << "not used in model block. To bypass this error, use the `nostrict` option. This may lead to crashes or unexpected behavior." << endl;
cerr << "ERROR: " << unused_exos.str()
<< "not used in model block. To bypass this error, use the `nostrict` option. This "
"may lead to crashes or unexpected behavior."
<< endl;
exit(EXIT_FAILURE);
}
}
@ -401,7 +435,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
<< "' not used in model block, removed by nostrict command-line option" << endl;
}
else if (unusedEndogsIsErr)
cerr << "Error: " << symbol_table.getName(unusedEndog) << " not used in the model block"<< endl;
cerr << "Error: " << symbol_table.getName(unusedEndog) << " not used in the model block"
<< endl;
if (unusedEndogsIsErr)
exit(EXIT_FAILURE);
@ -427,13 +462,16 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
lag_equivalence_table_t unary_ops_nodes;
ExprNode::subst_table_t unary_ops_subst_table;
if (transform_unary_ops)
tie(unary_ops_nodes, unary_ops_subst_table) = dynamic_model.substituteUnaryOps(var_expectation_model_table, pac_model_table);
tie(unary_ops_nodes, unary_ops_subst_table)
= dynamic_model.substituteUnaryOps(var_expectation_model_table, pac_model_table);
else
// substitute only those unary ops that appear in VAR, TCM and PAC model equations
tie(unary_ops_nodes, unary_ops_subst_table) = dynamic_model.substituteUnaryOps(unary_ops_eqs, var_expectation_model_table, pac_model_table);
tie(unary_ops_nodes, unary_ops_subst_table) = dynamic_model.substituteUnaryOps(
unary_ops_eqs, var_expectation_model_table, pac_model_table);
// Create auxiliary variable and equations for Diff operators
auto [diff_nodes, diff_subst_table] = dynamic_model.substituteDiff(var_expectation_model_table, pac_model_table);
auto [diff_nodes, diff_subst_table]
= dynamic_model.substituteDiff(var_expectation_model_table, pac_model_table);
// Fill trend component and VAR model tables
dynamic_model.fillTrendComponentModelTable();
@ -447,9 +485,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
trend_component_model_table);
// PAC model
pac_model_table.transformPass(unary_ops_nodes, unary_ops_subst_table,
diff_nodes, diff_subst_table,
dynamic_model, var_model_table,
pac_model_table.transformPass(unary_ops_nodes, unary_ops_subst_table, diff_nodes,
diff_subst_table, dynamic_model, var_model_table,
trend_component_model_table);
// Create auxiliary vars for Expectation operator
@ -491,9 +528,12 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
*/
if (linear)
orig_ramsey_dynamic_model = dynamic_model;
DynamicModel ramsey_FOC_equations_dynamic_model {symbol_table, num_constants, external_functions_table, trend_component_model_table, var_model_table};
DynamicModel ramsey_FOC_equations_dynamic_model {
symbol_table, num_constants, external_functions_table, trend_component_model_table,
var_model_table};
ramsey_FOC_equations_dynamic_model = dynamic_model;
mod_file_struct.ramsey_orig_endo_nbr = ramsey_FOC_equations_dynamic_model.computeRamseyPolicyFOCs(planner_objective);
mod_file_struct.ramsey_orig_endo_nbr
= ramsey_FOC_equations_dynamic_model.computeRamseyPolicyFOCs(planner_objective);
ramsey_FOC_equations_dynamic_model.replaceMyEquations(dynamic_model);
}
@ -506,14 +546,11 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
exos. The transformation is not exactly the same on stochastic and
deterministic models, because there is no need to take into account the
Jensen inequality on the latter. */
bool deterministic_model = !(mod_file_struct.stoch_simul_present
|| mod_file_struct.estimation_present
|| mod_file_struct.osr_present
|| mod_file_struct.discretionary_policy_present
|| mod_file_struct.calib_smoother_present
|| mod_file_struct.identification_present
|| mod_file_struct.mom_estimation_present
|| mod_file_struct.sensitivity_present
bool deterministic_model
= !(mod_file_struct.stoch_simul_present || mod_file_struct.estimation_present
|| mod_file_struct.osr_present || mod_file_struct.discretionary_policy_present
|| mod_file_struct.calib_smoother_present || mod_file_struct.identification_present
|| mod_file_struct.mom_estimation_present || mod_file_struct.sensitivity_present
|| stochastic);
dynamic_model.substituteEndoLeadGreaterThanTwo(deterministic_model);
dynamic_model.substituteExoLead(deterministic_model);
@ -530,8 +567,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
{
int sid = symbol_table.addSymbol("dsge_prior_weight", SymbolType::parameter);
if (!mod_file_struct.dsge_var_calibrated.empty())
addStatementAtFront(make_unique<InitParamStatement>(sid,
expressions_tree.AddNonNegativeConstant(mod_file_struct.dsge_var_calibrated),
addStatementAtFront(make_unique<InitParamStatement>(
sid, expressions_tree.AddNonNegativeConstant(mod_file_struct.dsge_var_calibrated),
symbol_table));
}
catch (SymbolTable::AlreadyDeclaredException& e)
@ -559,54 +596,72 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
&& !(mod_file_struct.bvar_present && dynamic_model.equation_number() == 0)
&& (dynamic_model.equation_number() != symbol_table.endo_nbr()))
{
cerr << "ERROR: There are " << dynamic_model.equation_number() << " equations but " << symbol_table.endo_nbr() << " endogenous variables!" << endl;
cerr << "ERROR: There are " << dynamic_model.equation_number() << " equations but "
<< symbol_table.endo_nbr() << " endogenous variables!" << endl;
exit(EXIT_FAILURE);
}
if (symbol_table.exo_det_nbr() > 0
&& (mod_file_struct.perfect_foresight_solver_present || mod_file_struct.perfect_foresight_with_expectation_errors_solver_present))
&& (mod_file_struct.perfect_foresight_solver_present
|| mod_file_struct.perfect_foresight_with_expectation_errors_solver_present))
{
cerr << "ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul, perfect_foresight_with_expectation_errors_solver} and varexo_det declaration (all exogenous variables are deterministic in this case)" << endl;
cerr << "ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul, "
"perfect_foresight_with_expectation_errors_solver} and varexo_det declaration (all "
"exogenous variables are deterministic in this case)"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.ramsey_model_present && symbol_table.exo_det_nbr() > 0)
{
cerr << "ERROR: ramsey_model and ramsey_policy are incompatible with deterministic exogenous variables" << endl;
cerr << "ERROR: ramsey_model and ramsey_policy are incompatible with deterministic exogenous "
"variables"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.identification_present && symbol_table.exo_det_nbr() > 0)
{
cerr << "ERROR: identification is incompatible with deterministic exogenous variables" << endl;
cerr << "ERROR: identification is incompatible with deterministic exogenous variables"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.occbin_constraints_present
&& (mod_file_struct.osr_present || mod_file_struct.mom_estimation_present
|| mod_file_struct.ramsey_model_present
|| mod_file_struct.discretionary_policy_present || mod_file_struct.extended_path_present
|| mod_file_struct.identification_present || mod_file_struct.sensitivity_present))
|| mod_file_struct.ramsey_model_present || mod_file_struct.discretionary_policy_present
|| mod_file_struct.extended_path_present || mod_file_struct.identification_present
|| mod_file_struct.sensitivity_present))
{
cerr << "ERROR: the 'occbin_constraints' block is not compatible with commands other than 'estimation', 'stoch_simul', and 'calib_smoother'." << endl;
cerr << "ERROR: the 'occbin_constraints' block is not compatible with commands other than "
"'estimation', 'stoch_simul', and 'calib_smoother'."
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.shocks_surprise_present && !mod_file_struct.occbin_constraints_present)
{
cerr << "ERROR: the 'shocks(surprise)' block can only be used in conjunction with the 'occbin_constraints' block." << endl;
cerr << "ERROR: the 'shocks(surprise)' block can only be used in conjunction with the "
"'occbin_constraints' block."
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.shocks_learnt_in_present && !mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
if (mod_file_struct.shocks_learnt_in_present
&& !mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
{
cerr << "ERROR: the 'shocks(learnt_in=…)' block can only be used in conjunction with the 'perfect_foresight_with_expectation_errors_solver' command." << endl;
cerr << "ERROR: the 'shocks(learnt_in=…)' block can only be used in conjunction with the "
"'perfect_foresight_with_expectation_errors_solver' command."
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.endval_learnt_in_present && !mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
if (mod_file_struct.endval_learnt_in_present
&& !mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
{
cerr << "ERROR: the 'endval(learnt_in=…)' block can only be used in conjunction with the 'perfect_foresight_with_expectation_errors_solver' command." << endl;
cerr << "ERROR: the 'endval(learnt_in=…)' block can only be used in conjunction with the "
"'perfect_foresight_with_expectation_errors_solver' command."
<< endl;
exit(EXIT_FAILURE);
}
@ -615,7 +670,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
else
{
cout << "Found " << mod_file_struct.ramsey_orig_eq_nbr << " equation(s)." << endl;
cout << "Found " << dynamic_model.equation_number() << " FOC equation(s) for Ramsey Problem." << endl;
cout << "Found " << dynamic_model.equation_number() << " FOC equation(s) for Ramsey Problem."
<< endl;
}
if (symbol_table.exists("dsge_prior_weight"))
@ -624,8 +680,10 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
{
if (symbol_table.exo_nbr() != symbol_table.observedVariablesNbr())
{
cerr << "ERROR: When estimating a DSGE-Var and the bayesian_irf option is passed to the estimation "
<< "statement, the number of shocks must equal the number of observed variables." << endl;
cerr << "ERROR: When estimating a DSGE-Var and the bayesian_irf option is passed to "
"the estimation "
<< "statement, the number of shocks must equal the number of observed variables."
<< endl;
exit(EXIT_FAILURE);
}
}
@ -651,24 +709,28 @@ ModFile::computingPass(bool no_tmp_terms, OutputType output, int params_derivs_o
static_model = static_cast<StaticModel>(dynamic_model);
if (!no_static)
{
if (mod_file_struct.stoch_simul_present
|| mod_file_struct.estimation_present || mod_file_struct.osr_present
|| mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
|| mod_file_struct.calib_smoother_present || mod_file_struct.mom_estimation_present)
if (mod_file_struct.stoch_simul_present || mod_file_struct.estimation_present
|| mod_file_struct.osr_present || mod_file_struct.ramsey_model_present
|| mod_file_struct.identification_present || mod_file_struct.calib_smoother_present
|| mod_file_struct.mom_estimation_present)
static_model.set_cutoff_to_zero();
int derivsOrder = 1;
int paramsDerivsOrder = 0;
if (mod_file_struct.identification_present || mod_file_struct.estimation_analytic_derivation)
if (mod_file_struct.identification_present
|| mod_file_struct.estimation_analytic_derivation)
derivsOrder = 2;
if (mod_file_struct.identification_present
|| mod_file_struct.estimation_analytic_derivation
|| mod_file_struct.osr_analytic_derivation
|| (mod_file_struct.GMM_present && (mod_file_struct.analytic_standard_errors_present || mod_file_struct.analytic_jacobian_present)))
|| (mod_file_struct.GMM_present
&& (mod_file_struct.analytic_standard_errors_present
|| mod_file_struct.analytic_jacobian_present)))
paramsDerivsOrder = params_derivs_order;
static_model.computingPass(derivsOrder, paramsDerivsOrder, global_eval_context, no_tmp_terms, block, use_dll);
static_model.computingPass(derivsOrder, paramsDerivsOrder, global_eval_context,
no_tmp_terms, block, use_dll);
if (mod_file_struct.ramsey_model_present)
static_model.computeRamseyMultipliersDerivatives(mod_file_struct.ramsey_orig_endo_nbr,
!use_dll, no_tmp_terms);
@ -676,8 +738,7 @@ ModFile::computingPass(bool no_tmp_terms, OutputType output, int params_derivs_o
// Set things to compute for dynamic model
if (mod_file_struct.perfect_foresight_solver_present
|| mod_file_struct.perfect_foresight_with_expectation_errors_solver_present
|| mod_file_struct.check_present
|| mod_file_struct.stoch_simul_present
|| mod_file_struct.check_present || mod_file_struct.stoch_simul_present
|| mod_file_struct.estimation_present || mod_file_struct.osr_present
|| mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
|| mod_file_struct.calib_smoother_present || mod_file_struct.mom_estimation_present)
@ -690,25 +751,34 @@ ModFile::computingPass(bool no_tmp_terms, OutputType output, int params_derivs_o
derivsOrder = 2;
else if (output == OutputType::third)
derivsOrder = 3;
dynamic_model.computingPass(derivsOrder, 0, global_eval_context, no_tmp_terms, block, use_dll);
dynamic_model.computingPass(derivsOrder, 0, global_eval_context, no_tmp_terms, block,
use_dll);
}
else
{
if (mod_file_struct.stoch_simul_present
|| mod_file_struct.estimation_present || mod_file_struct.osr_present
|| mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
|| mod_file_struct.calib_smoother_present || mod_file_struct.mom_estimation_present)
if (mod_file_struct.stoch_simul_present || mod_file_struct.estimation_present
|| mod_file_struct.osr_present || mod_file_struct.ramsey_model_present
|| mod_file_struct.identification_present
|| mod_file_struct.calib_smoother_present
|| mod_file_struct.mom_estimation_present)
dynamic_model.set_cutoff_to_zero();
if (mod_file_struct.order_option < 1)
{
cerr << "ERROR: Incorrect order option..." << endl;
exit(EXIT_FAILURE);
}
int derivsOrder = max(mod_file_struct.order_option,mod_file_struct.identification_order + 1); // See preprocessor#40
int derivsOrder
= max(mod_file_struct.order_option,
mod_file_struct.identification_order + 1); // See preprocessor#40
if (mod_file_struct.GMM_present
&& (mod_file_struct.analytic_standard_errors_present || mod_file_struct.analytic_jacobian_present)) //analytic_standard_errors or analytic_jacobian require one order more
derivsOrder = max(mod_file_struct.order_option,
max(mod_file_struct.identification_order,mod_file_struct.mom_order) + 1); // See preprocessor#40
&& (mod_file_struct.analytic_standard_errors_present
|| mod_file_struct.analytic_jacobian_present)) // analytic_standard_errors or
// analytic_jacobian require
// one order more
derivsOrder
= max(mod_file_struct.order_option,
max(mod_file_struct.identification_order, mod_file_struct.mom_order)
+ 1); // See preprocessor#40
if (mod_file_struct.sensitivity_present || linear || output == OutputType::second)
derivsOrder = max(derivsOrder, 2);
@ -718,11 +788,15 @@ ModFile::computingPass(bool no_tmp_terms, OutputType output, int params_derivs_o
if (mod_file_struct.identification_present
|| mod_file_struct.estimation_analytic_derivation
|| mod_file_struct.osr_analytic_derivation
|| (mod_file_struct.GMM_present && (mod_file_struct.analytic_standard_errors_present || mod_file_struct.analytic_jacobian_present)))
|| (mod_file_struct.GMM_present
&& (mod_file_struct.analytic_standard_errors_present
|| mod_file_struct.analytic_jacobian_present)))
paramsDerivsOrder = params_derivs_order;
dynamic_model.computingPass(derivsOrder, paramsDerivsOrder, global_eval_context, no_tmp_terms, block, use_dll);
dynamic_model.computingPass(derivsOrder, paramsDerivsOrder, global_eval_context,
no_tmp_terms, block, use_dll);
if (linear && mod_file_struct.ramsey_model_present)
orig_ramsey_dynamic_model.computingPass(2, paramsDerivsOrder, global_eval_context, no_tmp_terms, block, use_dll);
orig_ramsey_dynamic_model.computingPass(2, paramsDerivsOrder, global_eval_context,
no_tmp_terms, block, use_dll);
}
}
else // No computing task requested, compute derivatives up to 2nd order by default
@ -771,8 +845,8 @@ void
ModFile::writeMOutput(const string& basename, bool clear_all, bool clear_global, bool no_warn,
bool console, bool nograph, bool nointeractive, const ConfigFile& config_file,
bool check_model_changes, bool minimal_workspace, bool compute_xrefs,
const string &mexext,
const filesystem::path &matlabroot, bool onlymodel, bool gui, bool notime) const
const string& mexext, const filesystem::path& matlabroot, bool onlymodel,
bool gui, bool notime) const
{
if (basename.empty())
{
@ -795,7 +869,8 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
filesystem::remove_all(basename + "/model/src");
filesystem::remove_all(basename + "/model/bytecode");
// Do not remove basename/model/julia/, otherwise it would break calls to writeToFileIfModified()
// Do not remove basename/model/julia/, otherwise it would break calls to
// writeToFileIfModified()
}
create_directory(plusfolder);
@ -811,7 +886,8 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
<< "% Status : main Dynare file" << endl
<< "%" << endl
<< "% Warning : this file is generated automatically by Dynare" << endl
<< "% from model file (.mod)" << endl << endl;
<< "% from model file (.mod)" << endl
<< endl;
if (no_warn)
mOutputFile << "warning off" << endl; // This will be executed *after* function warning_config()
@ -820,13 +896,17 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
mOutputFile << "clearvars -global" << endl
<< "clear_persistent_variables(fileparts(which('dynare')), false)" << endl;
else if (clear_global)
mOutputFile << "clear M_ options_ oo_ estim_params_ bayestopt_ dataset_ dataset_info estimation_info;" << endl;
mOutputFile
<< "clear M_ options_ oo_ estim_params_ bayestopt_ dataset_ dataset_info estimation_info;"
<< endl;
if (!notime)
mOutputFile << "tic0 = tic;" << endl;
mOutputFile << "% Define global variables." << endl
<< "global M_ options_ oo_ estim_params_ bayestopt_ dataset_ dataset_info estimation_info" << endl
mOutputFile
<< "% Define global variables." << endl
<< "global M_ options_ oo_ estim_params_ bayestopt_ dataset_ dataset_info estimation_info"
<< endl
<< "options_ = [];" << endl
<< "M_.fname = '" << basename << "';" << endl
<< "M_.dynare_version = '" << PACKAGE_VERSION << "';" << endl
@ -843,8 +923,7 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
mOutputFile << "options_.minimal_workspace = true;" << endl;
if (console)
mOutputFile << "options_.console_mode = true;" << endl
<< "options_.nodisplay = true;" << endl;
mOutputFile << "options_.console_mode = true;" << endl << "options_.nodisplay = true;" << endl;
if (nograph)
mOutputFile << "options_.nograph = true;" << endl;
@ -862,8 +941,8 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
pac_model_table.writeOutput(mOutputFile);
// Initialize M_.Sigma_e, M_.Correlation_matrix, M_.H, and M_.Correlation_matrix_ME
mOutputFile << "M_.Sigma_e = zeros(" << symbol_table.exo_nbr() << ", "
<< symbol_table.exo_nbr() << ");" << endl
mOutputFile << "M_.Sigma_e = zeros(" << symbol_table.exo_nbr() << ", " << symbol_table.exo_nbr()
<< ");" << endl
<< "M_.Correlation_matrix = eye(" << symbol_table.exo_nbr() << ", "
<< symbol_table.exo_nbr() << ");" << endl;
@ -873,13 +952,13 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
<< "M_.Correlation_matrix_ME = eye(" << symbol_table.observedVariablesNbr() << ", "
<< symbol_table.observedVariablesNbr() << ");" << endl;
else
mOutputFile << "M_.H = 0;" << endl
<< "M_.Correlation_matrix_ME = 1;" << endl;
mOutputFile << "M_.H = 0;" << endl << "M_.Correlation_matrix_ME = 1;" << endl;
// May be later modified by a shocks block
mOutputFile << "M_.sigma_e_is_diagonal = true;" << endl;
// Initialize M_.det_shocks, M_.surprise_shocks, M_.learnt_shocks, M_.learnt_endval and M_.heteroskedastic_shocks
// Initialize M_.det_shocks, M_.surprise_shocks, M_.learnt_shocks, M_.learnt_endval and
// M_.heteroskedastic_shocks
mOutputFile << "M_.det_shocks = [];" << endl
<< "M_.surprise_shocks = [];" << endl
<< "M_.learnt_shocks = [];" << endl
@ -888,16 +967,17 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
<< "M_.heteroskedastic_shocks.Qscale_orig = [];" << endl;
// NB: options_.{ramsey,discretionary}_policy should rather be fields of M_
mOutputFile << boolalpha
<< "options_.linear = " << linear << ";" << endl
mOutputFile << boolalpha << "options_.linear = " << linear << ";" << endl
<< "options_.block = " << block << ";" << endl
<< "options_.bytecode = " << bytecode << ";" << endl
<< "options_.use_dll = " << use_dll << ";" << endl
<< "options_.ramsey_policy = " << mod_file_struct.ramsey_model_present << ";" << endl
<< "options_.discretionary_policy = " << mod_file_struct.discretionary_policy_present << ";" << endl;
<< "options_.discretionary_policy = " << mod_file_struct.discretionary_policy_present
<< ";" << endl;
if (mod_file_struct.discretionary_policy_present)
mOutputFile << "M_.discretionary_orig_eq_nbr = " << original_model.equation_number() << ";" << endl;
mOutputFile << "M_.discretionary_orig_eq_nbr = " << original_model.equation_number() << ";"
<< endl;
if (parallel_local_files.size() > 0)
{
@ -918,8 +998,7 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
{
mOutputFile << "M_.nonzero_hessian_eqs = ";
dynamic_model.printNonZeroHessianEquations(mOutputFile);
mOutputFile << ";" << endl
<< "M_.hessian_eq_zero = isempty(M_.nonzero_hessian_eqs);" << endl;
mOutputFile << ";" << endl << "M_.hessian_eq_zero = isempty(M_.nonzero_hessian_eqs);" << endl;
}
if (!onlymodel)
@ -927,13 +1006,17 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
if (bytecode)
mOutputFile << "if exist('bytecode') ~= 3" << endl
<< " error('DYNARE: Can''t find bytecode DLL. Please compile it or remove the ''bytecode'' option.')" << endl
<< " error('DYNARE: Can''t find bytecode DLL. Please compile it or remove the "
"''bytecode'' option.')"
<< endl
<< "end" << endl;
mOutputFile << "M_.eq_nbr = " << dynamic_model.equation_number() << ";" << endl
<< "M_.ramsey_orig_eq_nbr = " << mod_file_struct.ramsey_orig_eq_nbr << ";" << endl
<< "M_.ramsey_orig_endo_nbr = " << mod_file_struct.ramsey_orig_endo_nbr << ";" << endl
<< "M_.set_auxiliary_variables = exist(['./+' M_.fname '/set_auxiliary_variables.m'], 'file') == 2;" << endl;
<< "M_.set_auxiliary_variables = exist(['./+' M_.fname "
"'/set_auxiliary_variables.m'], 'file') == 2;"
<< endl;
epilogue.writeOutput(mOutputFile);
@ -1001,41 +1084,60 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
if (auto evs = dynamic_cast<EndValStatement*>(statement.get()); evs)
static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel);
// Special treatment for load params and steady state statement: insert initial values for the auxiliary variables
if (auto lpass = dynamic_cast<LoadParamsAndSteadyStateStatement *>(statement.get()); lpass && !no_static)
// Special treatment for load params and steady state statement: insert initial values for
// the auxiliary variables
if (auto lpass = dynamic_cast<LoadParamsAndSteadyStateStatement*>(statement.get());
lpass && !no_static)
static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel);
}
if (!notime)
mOutputFile << endl << endl
mOutputFile << endl
<< endl
<< "oo_.time = toc(tic0);" << endl
<< "disp(['Total computing time : ' dynsec2hms(oo_.time) ]);" << endl;
mOutputFile << "if ~exist([M_.dname filesep 'Output'],'dir')" << endl
<< " mkdir(M_.dname,'Output');" << endl
<< "end" << endl
<< "save([M_.dname filesep 'Output' filesep '" << basename << "_results.mat'], 'oo_', 'M_', 'options_');" << endl
<< "save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'oo_', 'M_', 'options_');" << endl
<< "if exist('estim_params_', 'var') == 1" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename << "_results.mat'], 'estim_params_', '-append');" << endl << "end" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'estim_params_', '-append');" << endl
<< "end" << endl
<< "if exist('bayestopt_', 'var') == 1" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename << "_results.mat'], 'bayestopt_', '-append');" << endl << "end" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'bayestopt_', '-append');" << endl
<< "end" << endl
<< "if exist('dataset_', 'var') == 1" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename << "_results.mat'], 'dataset_', '-append');" << endl << "end" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'dataset_', '-append');" << endl
<< "end" << endl
<< "if exist('estimation_info', 'var') == 1" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename << "_results.mat'], 'estimation_info', '-append');" << endl << "end" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'estimation_info', '-append');" << endl
<< "end" << endl
<< "if exist('dataset_info', 'var') == 1" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename << "_results.mat'], 'dataset_info', '-append');" << endl << "end" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'dataset_info', '-append');" << endl
<< "end" << endl
<< "if exist('oo_recursive_', 'var') == 1" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename << "_results.mat'], 'oo_recursive_', '-append');" << endl << "end" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'oo_recursive_', '-append');" << endl
<< "end" << endl
<< "if exist('options_mom_', 'var') == 1" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename << "_results.mat'], 'options_mom_', '-append');" << endl << "end" << endl;
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'options_mom_', '-append');" << endl
<< "end" << endl;
config_file.writeEndParallel(mOutputFile);
if (!no_warn)
{
if (warnings.countWarnings() > 0)
mOutputFile << "disp('Note: " << warnings.countWarnings() << " warning(s) encountered in the preprocessor')" << endl;
mOutputFile << "disp('Note: " << warnings.countWarnings()
<< " warning(s) encountered in the preprocessor')" << endl;
mOutputFile << "if ~isempty(lastwarn)" << endl
<< " disp('Note: warning(s) encountered in MATLAB/Octave code')" << endl
@ -1057,9 +1159,11 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
if (mod_file_struct.ramsey_model_present)
{
if (use_dll)
static_model.writeRamseyMultipliersDerivativesCFile(basename, mexext, matlabroot, mod_file_struct.ramsey_orig_endo_nbr);
static_model.writeRamseyMultipliersDerivativesCFile(
basename, mexext, matlabroot, mod_file_struct.ramsey_orig_endo_nbr);
else
static_model.writeRamseyMultipliersDerivativesMFile(basename, mod_file_struct.ramsey_orig_endo_nbr);
static_model.writeRamseyMultipliersDerivativesMFile(
basename, mod_file_struct.ramsey_orig_endo_nbr);
}
}
@ -1095,7 +1199,8 @@ ModFile::writeJuliaOutput(const string &basename) const
}
void
ModFile::writeJsonOutput(const string &basename, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple)
ModFile::writeJsonOutput(const string& basename, JsonOutputPointType json,
JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple)
{
if (json == JsonOutputPointType::nojson)
return;
@ -1104,10 +1209,11 @@ ModFile::writeJsonOutput(const string &basename, JsonOutputPointType json, JsonF
symbol_table.freeze();
if (json_output_mode == JsonFileOutputType::standardout)
cout << "//-- BEGIN JSON --// " << endl
<< "{" << endl;
cout << "//-- BEGIN JSON --// " << endl << "{" << endl;
writeJsonOutputParsingCheck(basename, json_output_mode, json == JsonOutputPointType::transformpass, json == JsonOutputPointType::computingpass);
writeJsonOutputParsingCheck(basename, json_output_mode,
json == JsonOutputPointType::transformpass,
json == JsonOutputPointType::computingpass);
if (json == JsonOutputPointType::parsing || json == JsonOutputPointType::checkpass)
symbol_table.unfreeze();
@ -1116,8 +1222,7 @@ ModFile::writeJsonOutput(const string &basename, JsonOutputPointType json, JsonF
writeJsonComputingPassOutput(basename, json_output_mode, jsonderivsimple);
if (json_output_mode == JsonFileOutputType::standardout)
cout << "}" << endl
<< "//-- END JSON --// " << endl;
cout << "}" << endl << "//-- END JSON --// " << endl;
switch (json)
{
@ -1143,7 +1248,8 @@ ModFile::writeJsonOutput(const string &basename, JsonOutputPointType json, JsonF
}
void
ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType json_output_mode, bool transformpass, bool computingpass) const
ModFile::writeJsonOutputParsingCheck(const string& basename, JsonFileOutputType json_output_mode,
bool transformpass, bool computingpass) const
{
ostringstream output;
output << "{" << endl;
@ -1154,9 +1260,7 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
output << ", ";
static_model.writeJsonOutput(output);
if (!statements.empty()
|| !var_model_table.empty()
|| !trend_component_model_table.empty())
if (!statements.empty() || !var_model_table.empty() || !trend_component_model_table.empty())
{
output << R"(, "statements": [)";
if (!var_model_table.empty())
@ -1183,8 +1287,7 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
output << ", ";
}
for (bool printed_something{false};
auto &it : statements)
for (bool printed_something {false}; auto& it : statements)
{
if (exchange(printed_something, true))
output << ", " << endl;
@ -1224,8 +1327,7 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
pac_model_table.writeJsonOutput(original_model_output);
original_model_output << ", ";
}
for (bool printed_something{false};
const auto &it : statements)
for (bool printed_something {false}; const auto& it : statements)
{
original_model_output << (exchange(printed_something, true) ? "," : "") << endl;
it->writeJsonOutput(original_model_output);
@ -1319,7 +1421,8 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
}
void
ModFile::writeJsonComputingPassOutput(const string &basename, JsonFileOutputType json_output_mode, bool jsonderivsimple) const
ModFile::writeJsonComputingPassOutput(const string& basename, JsonFileOutputType json_output_mode,
bool jsonderivsimple) const
{
if (basename.empty() && json_output_mode != JsonFileOutputType::standardout)
{
@ -1327,7 +1430,8 @@ ModFile::writeJsonComputingPassOutput(const string &basename, JsonFileOutputType
exit(EXIT_FAILURE);
}
ostringstream tmp_out, static_output, dynamic_output, static_paramsd_output, dynamic_paramsd_output;
ostringstream tmp_out, static_output, dynamic_output, static_paramsd_output,
dynamic_paramsd_output;
static_output << "{";
static_model.writeJsonComputingPassOutput(static_output, !jsonderivsimple);
@ -1365,7 +1469,8 @@ ModFile::writeJsonComputingPassOutput(const string &basename, JsonFileOutputType
writeJsonFileHelper(basename + "/model/json/dynamic.json", dynamic_output);
if (!static_paramsd_output.str().empty())
writeJsonFileHelper(basename + "/model/json/static_params_derivs.json", static_paramsd_output);
writeJsonFileHelper(basename + "/model/json/static_params_derivs.json",
static_paramsd_output);
if (!dynamic_paramsd_output.str().empty())
writeJsonFileHelper(basename + "/model/json/params_derivs.json", dynamic_paramsd_output);

View File

@ -20,24 +20,24 @@
#ifndef _MOD_FILE_HH
#define _MOD_FILE_HH
#include <ostream>
#include <ctime>
#include <iostream>
#include <sstream>
#include <filesystem>
#include <iostream>
#include <ostream>
#include <sstream>
#include "SymbolTable.hh"
#include "ConfigFile.hh"
#include "DynamicModel.hh"
#include "ExtendedPreprocessorTypes.hh"
#include "ExternalFunctionsTable.hh"
#include "ModelEquationBlock.hh"
#include "NumericalConstants.hh"
#include "NumericalInitialization.hh"
#include "StaticModel.hh"
#include "DynamicModel.hh"
#include "ModelEquationBlock.hh"
#include "Statement.hh"
#include "ExternalFunctionsTable.hh"
#include "ConfigFile.hh"
#include "WarningConsolidation.hh"
#include "ExtendedPreprocessorTypes.hh"
#include "StaticModel.hh"
#include "SubModel.hh"
#include "SymbolTable.hh"
#include "WarningConsolidation.hh"
using namespace std;
@ -90,7 +90,8 @@ public:
model block or on the preprocessor command line) */
bool use_dll {false};
//! Is the static model have to computed (no_static=false) or not (no_static=true). Option of 'model'
//! Is the static model have to computed (no_static=false) or not (no_static=true). Option of
//! 'model'
bool no_static {false};
//! Is the 'differentiate_forward_vars' option used?
@ -124,8 +125,10 @@ private:
//! Warnings Encountered
WarningConsolidation& warnings;
//! Functions used in writing of JSON outut. See writeJsonOutput
void writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType json_output_mode, bool transformpass, bool computingpass) const;
void writeJsonComputingPassOutput(const string &basename, JsonFileOutputType json_output_mode, bool jsonderivsimple) const;
void writeJsonOutputParsingCheck(const string& basename, JsonFileOutputType json_output_mode,
bool transformpass, bool computingpass) const;
void writeJsonComputingPassOutput(const string& basename, JsonFileOutputType json_output_mode,
bool jsonderivsimple) const;
void writeJsonFileHelper(const filesystem::path& fname, ostringstream& output) const;
/* Generate a random temporary path, in the current directory. Equivalent to
boost::filesystem::unique_path(). Both are insecure, but currently there
@ -138,13 +141,15 @@ private:
same filesystem. This technique is applied recursively to subdirectories.
Works even if the argument does not exist or is not a directory. */
static void remove_directory_with_matlab_lock(const filesystem::path& dir);
public:
//! Add a statement
void addStatement(unique_ptr<Statement> st);
//! Add a statement at the front of the statements vector
void addStatementAtFront(unique_ptr<Statement> st);
//! Evaluate all the statements
/*! \param warn_uninit Should a warning be displayed for uninitialized endogenous/exogenous/parameters ? */
/*! \param warn_uninit Should a warning be displayed for uninitialized
* endogenous/exogenous/parameters ? */
void evalAllExpressions(bool warn_uninit);
//! Do some checking and fills mod_file_struct
/*! \todo add check for number of equations and endogenous if ramsey_policy is present */
@ -154,13 +159,14 @@ public:
void transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool transform_unary_ops,
const string& exclude_eqs, const string& include_eqs);
//! Execute computations
/*! \param no_tmp_terms if true, no temporary terms will be computed in the static and dynamic files */
/*! \param no_tmp_terms if true, no temporary terms will be computed in the static and dynamic
* files */
/*! \param params_derivs_order compute this order of derivs wrt parameters */
void computingPass(bool no_tmp_terms, OutputType output, int params_derivs_order);
//! Writes Matlab/Octave output files
/*!
\param basename The base name used for writing output files. Should be the name of the mod file without its extension
\param clear_all Should a "clear all" instruction be written to output ?
\param basename The base name used for writing output files. Should be the name of the mod file
without its extension \param clear_all Should a "clear all" instruction be written to output ?
\param console Are we in console mode ?
\param nograph Should we build the figures?
\param nointeractive Should Dynare request user input?
@ -172,17 +178,20 @@ public:
void writeMOutput(const string& basename, bool clear_all, bool clear_global, bool no_warn,
bool console, bool nograph, bool nointeractive, const ConfigFile& config_file,
bool check_model_changes, bool minimal_workspace, bool compute_xrefs,
const string &mexext, const filesystem::path &matlabroot,
bool onlymodel, bool gui, bool notime) const;
const string& mexext, const filesystem::path& matlabroot, bool onlymodel,
bool gui, bool notime) const;
void writeJuliaOutput(const string& basename) const;
void computeChecksum();
//! Write JSON representation of ModFile object
//! Initially created to enable Julia to work with .mod files
//! Potentially outputs ModFile after the various parts of processing (parsing, checkPass, transformPass, computingPass)
//! Allows user of other host language platforms (python, fortran, etc) to provide support for dynare .mod files
void writeJsonOutput(const string &basename, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple = false);
//! Potentially outputs ModFile after the various parts of processing (parsing, checkPass,
//! transformPass, computingPass) Allows user of other host language platforms (python, fortran,
//! etc) to provide support for dynare .mod files
void writeJsonOutput(const string& basename, JsonOutputPointType json,
JsonFileOutputType json_output_mode, bool onlyjson,
bool jsonderivsimple = false);
};
#endif // ! MOD_FILE_HH

View File

@ -17,8 +17,8 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <algorithm>
#include <cassert>
#include <sstream>
#include "ModelEquationBlock.hh"
@ -37,11 +37,10 @@ PlannerObjective::computingPassBlock([[maybe_unused]] const eval_context_t &eval
// Disable block decomposition on planner objective
}
OrigRamseyDynamicModel::OrigRamseyDynamicModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
OrigRamseyDynamicModel::OrigRamseyDynamicModel(
SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
TrendComponentModelTable &trend_component_model_table_arg,
VarModelTable &var_model_table_arg) :
TrendComponentModelTable& trend_component_model_table_arg, VarModelTable& var_model_table_arg) :
DynamicModel {symbol_table_arg, num_constants_arg, external_functions_table_arg,
trend_component_model_table_arg, var_model_table_arg}
{
@ -64,8 +63,7 @@ SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg,
}
SteadyStateModel::SteadyStateModel(const SteadyStateModel& m) :
DataTree{m},
static_model{m.static_model}
DataTree {m}, static_model {m.static_model}
{
for (const auto& it : m.def_table)
def_table.emplace_back(it.first, it.second->clone(*this));
@ -126,7 +124,8 @@ SteadyStateModel::checkPass(ModFileStructure &mod_file_struct, WarningConsolidat
// Check that symbols are not already defined
for (int symb_id : symb_ids)
if (so_far_defined.contains(symb_id))
warnings << "WARNING: in the 'steady_state_model' block, variable '" << symbol_table.getName(symb_id) << "' is declared twice" << endl;
warnings << "WARNING: in the 'steady_state_model' block, variable '"
<< symbol_table.getName(symb_id) << "' is declared twice" << endl;
// Check that expression has no undefined symbol
if (!mod_file_struct.ramsey_model_present)
@ -137,8 +136,10 @@ SteadyStateModel::checkPass(ModFileStructure &mod_file_struct, WarningConsolidat
for (int used_symbol : used_symbols)
if (!so_far_defined.contains(used_symbol))
{
cerr << "ERROR: in the 'steady_state_model' block, variable '" << symbol_table.getName(used_symbol)
<< "' is undefined in the declaration of variable '" << symbol_table.getName(symb_ids[0]) << "'" << endl;
cerr << "ERROR: in the 'steady_state_model' block, variable '"
<< symbol_table.getName(used_symbol)
<< "' is undefined in the declaration of variable '"
<< symbol_table.getName(symb_ids[0]) << "'" << endl;
exit(EXIT_FAILURE);
}
}
@ -155,7 +156,8 @@ SteadyStateModel::checkPass(ModFileStructure &mod_file_struct, WarningConsolidat
should_be_defined.erase(symbol_table.getID(s));
for (int v : should_be_defined)
if (!so_far_defined.contains(v))
warnings << "WARNING: in the 'steady_state_model' block, variable '" << symbol_table.getName(v) << "' is not assigned a value" << endl;
warnings << "WARNING: in the 'steady_state_model' block, variable '"
<< symbol_table.getName(v) << "' is not assigned a value" << endl;
}
void
@ -191,16 +193,14 @@ SteadyStateModel::writeLatexSteadyStateFile(const string &basename) const
for (const auto& [ids, value] : def_table)
for (int id : ids)
{
content_output << "\\begin{dmath}" << endl
<< symbol_table.getTeXName(id) << " = ";
content_output << "\\begin{dmath}" << endl << symbol_table.getTeXName(id) << " = ";
value->writeOutput(content_output, ExprNodeOutputType::latexStaticModel);
content_output << endl << "\\end{dmath}" << endl;
}
static_model.writeLatexAuxVarRecursiveDefinitions(content_output);
output << "\\include{steady_state_content.tex}" << endl
<< "\\end{document}" << endl;
output << "\\include{steady_state_content.tex}" << endl << "\\end{document}" << endl;
output.close();
content_output.close();
@ -212,7 +212,8 @@ SteadyStateModel::writeSteadyStateFile(const string &basename, bool julia) const
if (def_table.size() == 0)
return;
ExprNodeOutputType output_type = (julia ? ExprNodeOutputType::juliaSteadyStateFile : ExprNodeOutputType::steadyStateFile);
ExprNodeOutputType output_type
= (julia ? ExprNodeOutputType::juliaSteadyStateFile : ExprNodeOutputType::steadyStateFile);
stringstream output;
if (!julia)
@ -257,7 +258,8 @@ SteadyStateModel::writeSteadyStateFile(const string &basename, bool julia) const
output << "end" << endl;
if (julia)
writeToFileIfModified(output, filesystem::path{basename} / "model" / "julia" / "SteadyState2.jl");
writeToFileIfModified(output,
filesystem::path {basename} / "model" / "julia" / "SteadyState2.jl");
else
{
/* Calling writeToFileIfModified() is useless here since we write inside
@ -284,16 +286,14 @@ SteadyStateModel::writeJsonSteadyStateFile(ostream &output, bool transformComput
output << "{\"steady_state_model\": [";
for (bool printed_something{false};
const auto &[symb_ids, value] : def_table)
for (bool printed_something {false}; const auto& [symb_ids, value] : def_table)
{
if (exchange(printed_something, true))
output << ",";
output << "{\"lhs\": ";
if (symb_ids.size() > 1)
output << "[";
for (bool printed_something2{false};
int symb_id : symb_ids)
for (bool printed_something2 {false}; int symb_id : symb_ids)
{
if (exchange(printed_something2, true))
output << ",";
@ -314,8 +314,7 @@ SteadyStateModel::writeJsonSteadyStateFile(ostream &output, bool transformComput
output << "]}";
}
Epilogue::Epilogue(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
Epilogue::Epilogue(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
TrendComponentModelTable& trend_component_model_table_arg,
VarModelTable& var_model_table_arg) :
@ -324,8 +323,7 @@ Epilogue::Epilogue(SymbolTable &symbol_table_arg,
{
}
Epilogue::Epilogue(const Epilogue &m) :
DynamicModel{m}
Epilogue::Epilogue(const Epilogue& m) : DynamicModel {m}
{
for (const auto& it : m.dynamic_def_table)
dynamic_def_table.emplace_back(it.first, it.second->clone(*this));
@ -356,7 +354,9 @@ Epilogue::checkPass(ModFileStructure &mod_file_struct) const
{
if (mod_file_struct.with_epilogue_option)
{
cerr << "ERROR: the 'with_epilogue' option cannot be specified when there is no 'epilogue' block" << endl;
cerr << "ERROR: the 'with_epilogue' option cannot be specified when there is no "
"'epilogue' block"
<< endl;
exit(EXIT_FAILURE);
}
return;
@ -385,8 +385,7 @@ void
Epilogue::detrend(const map<int, expr_t>& trend_symbols_map,
const nonstationary_symbols_map_t& nonstationary_symbols_map)
{
for (auto it = nonstationary_symbols_map.crbegin();
it != nonstationary_symbols_map.crend(); ++it)
for (auto it = nonstationary_symbols_map.crbegin(); it != nonstationary_symbols_map.crend(); ++it)
for (auto& [symb_id, expr] : dynamic_def_table)
{
expr = expr->detrend(it->first, it->second.first, it->second.second);
@ -433,21 +432,25 @@ Epilogue::writeStaticEpilogueFile(const string &basename) const
for (const auto& [symb_id, expr] : static_def_table)
{
// Rewrite external function TEF term for every equation as argument values could have been changed
// in between two calls to the same function;
// Rewrite external function TEF term for every equation as argument values could have been
// changed in between two calls to the same function;
deriv_node_temp_terms_t tef_terms;
temporary_terms_t temporary_terms;
temporary_terms_idxs_t temporary_terms_idxs;
output << endl;
if (expr->containsExternalFunction())
expr->writeExternalFunctionOutput(output, ExprNodeOutputType::matlabDseries, temporary_terms, temporary_terms_idxs, tef_terms);
expr->writeExternalFunctionOutput(output, ExprNodeOutputType::matlabDseries,
temporary_terms, temporary_terms_idxs, tef_terms);
output << "epilogue_static_tmp_term = ";
expr->writeOutput(output, ExprNodeOutputType::matlabDseries, temporary_terms, temporary_terms_idxs, tef_terms);
expr->writeOutput(output, ExprNodeOutputType::matlabDseries, temporary_terms,
temporary_terms_idxs, tef_terms);
output << ";" << endl
<< "if isdseries(epilogue_static_tmp_term)" << endl
<< " ds." << symbol_table.getName(symb_id) << " = epilogue_static_tmp_term;" << endl
<< "else" << endl
<< " ds." << symbol_table.getName(symb_id) << " = dseries(ones(ds.nobs,1)*epilogue_static_tmp_term, ds.firstdate, '" << symbol_table.getName(symb_id) << "');" << endl
<< " ds." << symbol_table.getName(symb_id)
<< " = dseries(ones(ds.nobs,1)*epilogue_static_tmp_term, ds.firstdate, '"
<< symbol_table.getName(symb_id) << "');" << endl
<< "end" << endl;
}
output << "end" << endl;
@ -467,7 +470,8 @@ Epilogue::writeDynamicEpilogueFile(const string &basename) const
output << "function ds = epilogue_dynamic(params, ds)" << endl
<< "% function ds = epilogue_dynamic(params, ds)" << endl
<< "% Epilogue file generated by Dynare preprocessor" << endl << endl
<< "% Epilogue file generated by Dynare preprocessor" << endl
<< endl
<< "simul_end_date = lastdate(ds);" << endl;
deriv_node_temp_terms_t tef_terms;
@ -483,12 +487,12 @@ Epilogue::writeDynamicEpilogueFile(const string &basename) const
output << endl
<< "if ~ds.exist('" << symbol_table.getName(symb_id) << "')" << endl
<< " ds = [ds dseries(NaN(ds.nobs,1), ds.firstdate, '" << symbol_table.getName(symb_id)<< "')];" << endl
<< " ds = [ds dseries(NaN(ds.nobs,1), ds.firstdate, '"
<< symbol_table.getName(symb_id) << "')];" << endl
<< "end" << endl
<< "try" << endl
<< " simul_begin_date = firstobservedperiod(ds{";
for (bool printed_something{false};
int symb_id : used_symbols)
for (bool printed_something {false}; int symb_id : used_symbols)
{
if (exchange(printed_something, true))
output << ", ";
@ -497,10 +501,9 @@ Epilogue::writeDynamicEpilogueFile(const string &basename) const
output << "}) + " << max_lag << ";" << endl
<< " from simul_begin_date to simul_end_date do "
<< "ds." << symbol_table.getName(symb_id) << "(t) = ";
expr->writeOutput(output, ExprNodeOutputType::epilogueFile, temporary_terms, temporary_terms_idxs, tef_terms);
output << ";" << endl
<< "catch" << endl
<< "end" << endl;
expr->writeOutput(output, ExprNodeOutputType::epilogueFile, temporary_terms,
temporary_terms_idxs, tef_terms);
output << ";" << endl << "catch" << endl << "end" << endl;
}
output << "end" << endl;
output.close();
@ -511,16 +514,14 @@ Epilogue::writeOutput(ostream &output) const
{
if (dynamic_def_table.empty())
{
output << "M_.epilogue_names = {};" << endl
<< "M_.epilogue_var_list_ = {};" << endl;
output << "M_.epilogue_names = {};" << endl << "M_.epilogue_var_list_ = {};" << endl;
return;
}
output << "M_.epilogue_names = cell(" << dynamic_def_table.size() << ",1);" << endl;
for (int idx{1};
const auto &[symb_id, expr] : dynamic_def_table)
output << "M_.epilogue_names{" << idx++ << "} = '"
<< symbol_table.getName(symb_id) << "';" << endl;
for (int idx {1}; const auto& [symb_id, expr] : dynamic_def_table)
output << "M_.epilogue_names{" << idx++ << "} = '" << symbol_table.getName(symb_id) << "';"
<< endl;
set<int> endogs;
for (const auto& [symb_id, expr] : dynamic_def_table)

View File

@ -21,17 +21,17 @@
#define _MODEL_EQUATION_BLOCK_HH
#include "DataTree.hh"
#include "DynamicModel.hh"
#include "Statement.hh"
#include "StaticModel.hh"
#include "DynamicModel.hh"
#include "WarningConsolidation.hh"
class PlannerObjective : public StaticModel
{
public:
PlannerObjective(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
PlannerObjective(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg);
protected:
string
modelClassName() const override
@ -46,8 +46,7 @@ private:
class OrigRamseyDynamicModel : public DynamicModel
{
public:
OrigRamseyDynamicModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
OrigRamseyDynamicModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
TrendComponentModelTable& trend_component_model_table_arg,
VarModelTable& var_model_table_arg);
@ -64,15 +63,15 @@ protected:
class SteadyStateModel : public DataTree
{
private:
//! Associates a set of symbol IDs (the variable(s) assigned in a given statement) to an expression (their assigned value)
//! Associates a set of symbol IDs (the variable(s) assigned in a given statement) to an
//! expression (their assigned value)
vector<pair<vector<int>, expr_t>> def_table;
//! Reference to static model (for writing auxiliary equations)
const StaticModel& static_model;
public:
SteadyStateModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
SteadyStateModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
const StaticModel& static_model_arg);
@ -85,7 +84,8 @@ public:
void addMultipleDefinitions(const vector<int>& symb_ids, expr_t expr);
//! Checks that definitions are in a recursive order, and that no variable is declared twice
/*!
\param[in] ramsey_model Is there a Ramsey model in the MOD file? If yes, then disable the check on the recursivity of the declarations
\param[in] ramsey_model Is there a Ramsey model in the MOD file? If yes, then disable the check
on the recursivity of the declarations
*/
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) const;
//! Write the steady state file
@ -99,11 +99,12 @@ public:
class Epilogue : public DynamicModel
{
private:
//! Associates a symbol ID (the variable assigned in a given statement) to an expression (its assigned value)
//! Associates a symbol ID (the variable assigned in a given statement) to an expression (its
//! assigned value)
vector<pair<int, expr_t>> dynamic_def_table, static_def_table;
public:
Epilogue(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
Epilogue(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
TrendComponentModelTable& trend_component_model_table_arg,
VarModelTable& var_model_table_arg);

View File

@ -33,9 +33,9 @@
# include <mach-o/dyld.h>
#endif
#include <algorithm>
#include <regex>
#include <utility>
#include <algorithm>
/* NB: The workers must be listed *after* all the other static variables
related to MEX compilation, so that when the preprocessor exits, the workers
@ -44,7 +44,8 @@
condition_variable_any ModelTree::mex_compilation_cv;
mutex ModelTree::mex_compilation_mut;
vector<tuple<filesystem::path, set<filesystem::path>, string>> ModelTree::mex_compilation_queue;
set<filesystem::path> ModelTree::mex_compilation_ongoing, ModelTree::mex_compilation_done, ModelTree::mex_compilation_failed;
set<filesystem::path> ModelTree::mex_compilation_ongoing, ModelTree::mex_compilation_done,
ModelTree::mex_compilation_failed;
vector<jthread> ModelTree::mex_compilation_workers;
void
@ -58,8 +59,7 @@ ModelTree::copyHelper(const ModelTree &m)
for (const auto& it : m.aux_equations)
aux_equations.push_back(dynamic_cast<BinaryOpNode*>(f(it)));
auto convert_deriv_map = [f](const map<vector<int>, expr_t> &dm)
{
auto convert_deriv_map = [f](const map<vector<int>, expr_t>& dm) {
map<vector<int>, expr_t> dm2;
for (const auto& it : dm)
dm2.emplace(it.first, f(it.second));
@ -74,8 +74,7 @@ ModelTree::copyHelper(const ModelTree &m)
for (const auto& it : m.jacobian_sparse_column_major_order)
jacobian_sparse_column_major_order.emplace(it.first, f(it.second));
auto convert_temporary_terms_t = [f](const temporary_terms_t &tt)
{
auto convert_temporary_terms_t = [f](const temporary_terms_t& tt) {
temporary_terms_t tt2;
for (const auto& it : tt)
tt2.insert(f(it));
@ -99,7 +98,8 @@ ModelTree::copyHelper(const ModelTree &m)
nonstationary_symbols_map.emplace(it.first, pair {it.second.first, f(it.second.second)});
for (const auto& it : m.equation_type_and_normalized_equation)
equation_type_and_normalized_equation.emplace_back(it.first, dynamic_cast<BinaryOpNode *>(f(it.second)));
equation_type_and_normalized_equation.emplace_back(it.first,
dynamic_cast<BinaryOpNode*>(f(it.second)));
for (const auto& it : m.blocks_derivatives)
{
@ -109,8 +109,7 @@ ModelTree::copyHelper(const ModelTree &m)
blocks_derivatives.push_back(v);
}
auto convert_vector_tt = [f](vector<temporary_terms_t> vtt)
{
auto convert_vector_tt = [f](vector<temporary_terms_t> vtt) {
vector<temporary_terms_t> vtt2;
for (const auto& tt : vtt)
{
@ -135,17 +134,16 @@ ModelTree::copyHelper(const ModelTree &m)
}
}
ModelTree::ModelTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg,
bool is_dynamic_arg) :
ModelTree::ModelTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, bool is_dynamic_arg) :
DataTree {symbol_table_arg, num_constants_arg, external_functions_table_arg, is_dynamic_arg},
derivatives(4),
NNZDerivatives(4, 0),
temporary_terms_derivatives(4)
{
// Ensure that elements accessed by writeParamsDerivativesFileHelper() exist
for (const auto &ord : {pair{0, 1}, pair{1, 1}, pair{0, 2}, pair{1, 2}, pair{2, 1}, pair{3, 1}})
for (const auto& ord :
{pair {0, 1}, pair {1, 1}, pair {0, 2}, pair {1, 2}, pair {2, 1}, pair {3, 1}})
params_derivatives.try_emplace(ord);
}
@ -257,13 +255,17 @@ ModelTree::computeNormalization(const jacob_map_t &contemporaneous_jacobian)
edmonds_maximum_cardinality_matching(g, &mate_map[0]);
// Check if all variables are normalized
if (auto it = find(mate_map.begin(), mate_map.begin() + n, boost::graph_traits<BipartiteGraph>::null_vertex());
if (auto it = find(mate_map.begin(), mate_map.begin() + n,
boost::graph_traits<BipartiteGraph>::null_vertex());
it != mate_map.begin() + n)
throw ModelNormalizationFailed {symbol_table.getName(symbol_table.getID(SymbolType::endogenous, it - mate_map.begin())) };
throw ModelNormalizationFailed {
symbol_table.getName(symbol_table.getID(SymbolType::endogenous, it - mate_map.begin()))};
// Create the resulting map, by copying the n first elements of mate_map, and substracting n to them
// Create the resulting map, by copying the n first elements of mate_map, and substracting n to
// them
endo2eq.resize(equations.size());
transform(mate_map.begin(), mate_map.begin() + n, endo2eq.begin(), [=](vertex_descriptor_t i) { return i-n; });
transform(mate_map.begin(), mate_map.begin() + n, endo2eq.begin(),
[=](vertex_descriptor_t i) { return i - n; });
}
bool
@ -275,7 +277,9 @@ ModelTree::computeNonSingularNormalization(const eval_context_t &eval_context)
not have as many equations as variables. */
if (n != symbol_table.endo_nbr())
{
cout << "The " << modelClassName() << " cannot be normalized, since it does not have as many equations as variables." << endl;
cout << "The " << modelClassName()
<< " cannot be normalized, since it does not have as many equations as variables."
<< endl;
return false;
}
@ -296,7 +300,12 @@ ModelTree::computeNonSingularNormalization(const eval_context_t &eval_context)
}
catch (ModelNormalizationFailed& e)
{
cerr << "WARNING: All equations are written so that a single contemporaneous endogenous variable appears on the left-hand side. This suggests a natural normalization of the model. However, variable " << e.unmatched_endo << " could not be matched with an equation. Check whether this is desired." << endl;
cerr << "WARNING: All equations are written so that a single contemporaneous "
"endogenous variable appears on the left-hand side. This suggests a natural "
"normalization of the model. However, variable "
<< e.unmatched_endo
<< " could not be matched with an equation. Check whether this is desired."
<< endl;
}
}
@ -362,8 +371,8 @@ ModelTree::computeNonSingularNormalization(const eval_context_t &eval_context)
}
catch (ModelNormalizationFailed& e)
{
cerr << "Could not normalize the " << modelClassName() << ". Variable "
<< e.unmatched_endo << " is not in the maximum cardinality matching." << endl;
cerr << "Could not normalize the " << modelClassName() << ". Variable " << e.unmatched_endo
<< " is not in the maximum cardinality matching." << endl;
}
return false;
@ -381,8 +390,7 @@ ModelTree::evaluateAndReduceJacobian(const eval_context_t &eval_context) const
int eq = indices[0];
int var {getTypeSpecificIDByDerivID(deriv_id)};
int lag = getLagByDerivID(deriv_id);
double val { [&]
{
double val {[&] {
try
{
return d1->eval(eval_context);
@ -509,7 +517,8 @@ ModelTree::computePrologueAndEpilogue()
}
void
ModelTree::equationTypeDetermination(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives)
ModelTree::equationTypeDetermination(
const map<tuple<int, int, int>, expr_t>& first_order_endo_derivatives)
{
equation_type_and_normalized_equation.clear();
equation_type_and_normalized_equation.resize(equations.size());
@ -536,7 +545,8 @@ ModelTree::equationTypeDetermination(const map<tuple<int, int, int>, expr_t> &fi
try
{
normalized_eq = equations[eq]->normalizeEquation(symbol_table.getID(SymbolType::endogenous, var), 0);
normalized_eq = equations[eq]->normalizeEquation(
symbol_table.getID(SymbolType::endogenous, var), 0);
if ((getMFS() == 2 && variable_not_in_derivative) || getMFS() == 3)
Equation_Simulation_Type = EquationType::evaluateRenormalized;
}
@ -567,7 +577,8 @@ ModelTree::computeDynamicStructureOfBlock(int blk)
{
blocks[blk].max_endo_lag = max(blocks[blk].max_endo_lag, -lag);
blocks[blk].max_endo_lead = max(blocks[blk].max_endo_lead, lag);
auto &[max_endo_lag, max_endo_lead] = max_endo_lag_lead[getBlockInitialVariableID(blk, endo)];
auto& [max_endo_lag, max_endo_lead]
= max_endo_lag_lead[getBlockInitialVariableID(blk, endo)];
max_endo_lag = max(max_endo_lag, -lag);
max_endo_lead = max(max_endo_lead, lag);
}
@ -597,11 +608,11 @@ ModelTree::computeSimulationTypeOfBlock(int blk)
bool can_eval = (getBlockEquationType(blk, 0) == EquationType::evaluate
|| getBlockEquationType(blk, 0) == EquationType::evaluateRenormalized);
if (blocks[blk].max_endo_lead > 0)
type = can_eval ? BlockSimulationType::evaluateBackward :
BlockSimulationType::solveBackwardSimple;
type = can_eval ? BlockSimulationType::evaluateBackward
: BlockSimulationType::solveBackwardSimple;
else
type = can_eval ? BlockSimulationType::evaluateForward :
BlockSimulationType::solveForwardSimple;
type = can_eval ? BlockSimulationType::evaluateForward
: BlockSimulationType::solveForwardSimple;
}
}
@ -642,10 +653,8 @@ ModelTree::computeBlockDecomposition(int prologue, int epilogue)
for (const auto& [key, value] : computeSymbolicJacobian(time_recursive_block_decomposition))
{
auto [eq, endo] = key;
if (eq_idx_orig2block[eq] >= prologue
&& eq_idx_orig2block[eq] < nb_var - epilogue
&& endo_idx_orig2block[endo] >= prologue
&& endo_idx_orig2block[endo] < nb_var - epilogue
if (eq_idx_orig2block[eq] >= prologue && eq_idx_orig2block[eq] < nb_var - epilogue
&& endo_idx_orig2block[endo] >= prologue && endo_idx_orig2block[endo] < nb_var - epilogue
&& eq != endo2eq[endo])
add_edge(vertex(eq_idx_orig2block[endo2eq[endo]] - prologue, G),
vertex(eq_idx_orig2block[eq] - prologue, G), G);
@ -698,20 +707,23 @@ ModelTree::computeBlockDecomposition(int prologue, int epilogue)
related to lead/lag variables. This forces those vertices to belong to the
feedback set */
for (int i = 0; i < nb_simvars; i++)
if (equation_type_and_normalized_equation[eq_idx_block2orig[i+prologue]].first == EquationType::solve
|| (!time_recursive_block_decomposition &&
(variable_lag_lead[endo_idx_block2orig[i+prologue]].first > 0
if (equation_type_and_normalized_equation[eq_idx_block2orig[i + prologue]].first
== EquationType::solve
|| (!time_recursive_block_decomposition
&& (variable_lag_lead[endo_idx_block2orig[i + prologue]].first > 0
|| variable_lag_lead[endo_idx_block2orig[i + prologue]].second > 0
|| equation_lag_lead[eq_idx_block2orig[i + prologue]].first > 0
|| equation_lag_lead[eq_idx_block2orig[i + prologue]].second > 0))
|| getMFS() == 0)
add_edge(vertex(i, G), vertex(i, G), G);
const vector<int> old_eq_idx_block2orig(eq_idx_block2orig), old_endo_idx_block2orig(endo_idx_block2orig);
const vector<int> old_eq_idx_block2orig(eq_idx_block2orig),
old_endo_idx_block2orig(endo_idx_block2orig);
int ordidx = prologue;
for (int blk = prologue; blk < prologue + num_simblocks; blk++)
{
blocks[blk].first_equation = (blk == 0 ? 0 : blocks[blk-1].first_equation + blocks[blk-1].size);
blocks[blk].first_equation
= (blk == 0 ? 0 : blocks[blk - 1].first_equation + blocks[blk - 1].size);
auto subG = G.extractSubgraph(simblock2simvars[blk - prologue]);
auto feed_back_vertices = subG.minimalSetOfFeedbackVertices();
blocks[blk].mfs_size = feed_back_vertices.size();
@ -761,8 +773,7 @@ ModelTree::printBlockDecomposition() const
|| simulation_type == BlockSimulationType::solveTwoBoundariesComplete)
{
Nb_SimulBlocks++;
if (int size = blocks[block].size;
size > largest_block)
if (int size = blocks[block].size; size > largest_block)
{
largest_block = size;
Nb_feedback_variable = blocks[block].mfs_size;
@ -771,9 +782,11 @@ ModelTree::printBlockDecomposition() const
int Nb_RecursBlocks = Nb_TotalBlocks - Nb_SimulBlocks;
cout << Nb_TotalBlocks << " block(s) found:" << endl
<< " " << Nb_RecursBlocks << " recursive block(s) and " << Nb_SimulBlocks << " simultaneous block(s)." << endl
<< " " << Nb_RecursBlocks << " recursive block(s) and " << Nb_SimulBlocks
<< " simultaneous block(s)." << endl
<< " the largest simultaneous block has " << largest_block << " equation(s)" << endl
<< " and " << Nb_feedback_variable << " feedback variable(s)." << endl;
<< " and " << Nb_feedback_variable
<< " feedback variable(s)." << endl;
}
void
@ -796,11 +809,9 @@ ModelTree::reduceBlockDecomposition()
}
if ((blocks[blk - 1].simulation_type == BlockSimulationType::evaluateForward
&& blocks[blk].simulation_type == BlockSimulationType::evaluateForward
&& !is_lead)
&& blocks[blk].simulation_type == BlockSimulationType::evaluateForward && !is_lead)
|| (blocks[blk - 1].simulation_type == BlockSimulationType::evaluateBackward
&& blocks[blk].simulation_type == BlockSimulationType::evaluateBackward
&& !is_lag))
&& blocks[blk].simulation_type == BlockSimulationType::evaluateBackward && !is_lag))
{
// Merge the current block into the previous one
blocks[blk - 1].size++;
@ -898,8 +909,10 @@ ModelTree::computeDerivatives(int order, const set<int> &vars)
// Compute the sparse representation of the Jacobian
for (const auto& [indices, d1] : derivatives[1])
jacobian_sparse_column_major_order.try_emplace({indices[0], getJacobianCol(indices[1], true)}, d1);
jacobian_sparse_colptr = computeCSCColPtr(jacobian_sparse_column_major_order, getJacobianColsNbr(true));
jacobian_sparse_column_major_order.try_emplace({indices[0], getJacobianCol(indices[1], true)},
d1);
jacobian_sparse_colptr
= computeCSCColPtr(jacobian_sparse_column_major_order, getJacobianColsNbr(true));
// Higher-order derivatives
for (int o = 2; o <= order; o++)
@ -930,8 +943,7 @@ ModelTree::computeTemporaryTerms(bool is_matlab, bool no_tmp_terms)
{
/* Ensure that we dont have any model-local variable in the model at this
point (we used to treat them as temporary terms) */
assert([&]
{
assert([&] {
set<int> used_local_vars;
for (auto& equation : equations)
equation->collectVariables(SymbolType::modelLocalVariable, used_local_vars);
@ -943,32 +955,26 @@ ModelTree::computeTemporaryTerms(bool is_matlab, bool no_tmp_terms)
unordered_map<expr_t, pair<int, pair<int, int>>> reference_count;
for (auto& equation : equations)
equation->computeTemporaryTerms({ 0, 0 },
temp_terms_map,
reference_count,
is_matlab);
equation->computeTemporaryTerms({0, 0}, temp_terms_map, reference_count, is_matlab);
for (int order = 1; order < static_cast<int>(derivatives.size()); order++)
for (const auto& it : derivatives[order])
it.second->computeTemporaryTerms({ order, 0 },
temp_terms_map,
reference_count,
is_matlab);
it.second->computeTemporaryTerms({order, 0}, temp_terms_map, reference_count, is_matlab);
/* If the user has specified the notmpterms option, clear all temporary
terms, except those that correspond to external functions (since they are
not optional) */
if (no_tmp_terms)
for (auto& it : temp_terms_map)
erase_if(it.second,
[](expr_t e) { return !dynamic_cast<AbstractExternalFunctionNode *>(e); });
erase_if(it.second, [](expr_t e) { return !dynamic_cast<AbstractExternalFunctionNode*>(e); });
// Fill the structures
temporary_terms_derivatives.clear();
temporary_terms_derivatives.resize(derivatives.size());
for (int order = 0; order < static_cast<int>(derivatives.size()); order++)
copy(temp_terms_map[{order, 0}].begin(), temp_terms_map[{order, 0}].end(),
inserter(temporary_terms_derivatives.at(order), temporary_terms_derivatives.at(order).begin()));
inserter(temporary_terms_derivatives.at(order),
temporary_terms_derivatives.at(order).begin()));
// Compute indices in MATLAB/Julia vector
for (int order {0}, idx {0}; order < static_cast<int>(derivatives.size()); order++)
@ -998,9 +1004,11 @@ ModelTree::computeBlockTemporaryTerms(bool no_tmp_terms)
|| blocks[blk].simulation_type == BlockSimulationType::evaluateForward
|| eq < blocks[blk].getRecursiveSize())
&& isBlockEquationRenormalized(blk, eq))
getBlockEquationRenormalizedExpr(blk, eq)->computeBlockTemporaryTerms(blk, eq, temp_terms, reference_count);
getBlockEquationRenormalizedExpr(blk, eq)->computeBlockTemporaryTerms(
blk, eq, temp_terms, reference_count);
else
getBlockEquationExpr(blk, eq)->computeBlockTemporaryTerms(blk, eq, temp_terms, reference_count);
getBlockEquationExpr(blk, eq)->computeBlockTemporaryTerms(blk, eq, temp_terms,
reference_count);
}
for (const auto& [ignore, d] : blocks_derivatives[blk])
d->computeBlockTemporaryTerms(blk, blocks[blk].size, temp_terms, reference_count);
@ -1019,30 +1027,29 @@ ModelTree::computeBlockTemporaryTerms(bool no_tmp_terms)
{
blocks_temporary_terms.at(blk).resize(temp_terms.at(blk).size());
for (size_t i {0}; i < temp_terms.at(blk).size(); i++)
copy(temp_terms.at(blk).at(i).begin(), temp_terms.at(blk).at(i).end(), inserter(blocks_temporary_terms.at(blk).at(i), blocks_temporary_terms.at(blk).at(i).begin()));
copy(temp_terms.at(blk).at(i).begin(), temp_terms.at(blk).at(i).end(),
inserter(blocks_temporary_terms.at(blk).at(i),
blocks_temporary_terms.at(blk).at(i).begin()));
}
// Compute indices in the temporary terms vector
blocks_temporary_terms_idxs.clear();
for (int idx{0};
auto &blk_tt : blocks_temporary_terms)
for (int idx {0}; auto& blk_tt : blocks_temporary_terms)
for (auto& eq_tt : blk_tt)
for (auto tt : eq_tt)
blocks_temporary_terms_idxs[tt] = idx++;
}
void
ModelTree::writeJsonTemporaryTerms(const temporary_terms_t &tt,
temporary_terms_t &temp_term_union,
ostream &output,
deriv_node_temp_terms_t &tef_terms, const string &concat) const
ModelTree::writeJsonTemporaryTerms(const temporary_terms_t& tt, temporary_terms_t& temp_term_union,
ostream& output, deriv_node_temp_terms_t& tef_terms,
const string& concat) const
{
// Local var used to keep track of temp nodes already written
temporary_terms_t tt2 = temp_term_union;
output << R"("external_functions_temporary_terms_)" << concat << R"(": [)";
for (bool printed_term{false};
auto it : tt)
for (bool printed_term {false}; auto it : tt)
{
if (dynamic_cast<AbstractExternalFunctionNode*>(it))
{
@ -1050,8 +1057,7 @@ ModelTree::writeJsonTemporaryTerms(const temporary_terms_t &tt,
output << ", ";
vector<string> efout;
it->writeJsonExternalFunctionOutput(efout, tt2, tef_terms);
for (bool printed_efout{false};
auto &it : efout)
for (bool printed_efout {false}; auto& it : efout)
{
if (exchange(printed_efout, true))
output << ", ";
@ -1063,8 +1069,7 @@ ModelTree::writeJsonTemporaryTerms(const temporary_terms_t &tt,
output << "]"
<< R"(, "temporary_terms_)" << concat << R"(": [)";
for (bool printed_term{false};
const auto &it : tt)
for (bool printed_term {false}; const auto& it : tt)
{
if (exchange(printed_term, true))
output << ", ";
@ -1081,7 +1086,8 @@ ModelTree::writeJsonTemporaryTerms(const temporary_terms_t &tt,
}
void
ModelTree::fixNestedParenthesis(ostringstream &output, map<string, string> &tmp_paren_vars, bool &message_printed) const
ModelTree::fixNestedParenthesis(ostringstream& output, map<string, string>& tmp_paren_vars,
bool& message_printed) const
{
string str = output.str();
if (!testNestedParenthesis(str))
@ -1112,11 +1118,23 @@ ModelTree::fixNestedParenthesis(ostringstream &output, map<string, string> &tmp_
{
if (!message_printed)
{
cerr << "Warning: A .m file created by Dynare will have more than 32 nested parenthesis. MATLAB cannot support this. " << endl
<< " We are going to modify, albeit inefficiently, this output to have fewer than 32 nested parenthesis. " << endl
<< " It would hence behoove you to use the use_dll option of the model block to circumnavigate this problem." << endl
<< " If you have not yet set up a compiler on your system, see the MATLAB documentation for doing so." << endl
<< " For Windows, see: https://www.mathworks.com/help/matlab/matlab_external/install-mingw-support-package.html" << endl << endl;
cerr << "Warning: A .m file created by Dynare will have more than 32 nested "
"parenthesis. MATLAB cannot support this. "
<< endl
<< " We are going to modify, albeit inefficiently, this output to have "
"fewer than 32 nested parenthesis. "
<< endl
<< " It would hence behoove you to use the use_dll option of the model "
"block to circumnavigate this problem."
<< endl
<< " If you have not yet set up a compiler on your system, see the "
"MATLAB documentation for doing so."
<< endl
<< " For Windows, see: "
"https://www.mathworks.com/help/matlab/matlab_external/"
"install-mingw-support-package.html"
<< endl
<< endl;
message_printed = true;
}
string str1 = str.substr(first_open_paren, matching_paren - first_open_paren + 1);
@ -1146,9 +1164,9 @@ ModelTree::fixNestedParenthesis(ostringstream &output, map<string, string> &tmp_
if (open_paren_idx != string::npos && match_paren_idx != string::npos)
{
string val = str1.substr(open_paren_idx, match_paren_idx - open_paren_idx + 1);
if (auto it = tmp_paren_vars.find(val);
it == tmp_paren_vars.end())
string val
= str1.substr(open_paren_idx, match_paren_idx - open_paren_idx + 1);
if (auto it = tmp_paren_vars.find(val); it == tmp_paren_vars.end())
{
varname = "paren32_tmp_var_" + to_string(i1++);
repstr = repstr + varname + " = " + val + ";\n";
@ -1161,8 +1179,7 @@ ModelTree::fixNestedParenthesis(ostringstream &output, map<string, string> &tmp_
}
}
}
if (auto it = tmp_paren_vars.find(str1);
it == tmp_paren_vars.end())
if (auto it = tmp_paren_vars.find(str1); it == tmp_paren_vars.end())
{
varname = "paren32_tmp_var_" + to_string(i1++);
repstr = repstr + varname + " = " + str1 + ";\n";
@ -1183,8 +1200,7 @@ ModelTree::fixNestedParenthesis(ostringstream &output, map<string, string> &tmp_
bool
ModelTree::testNestedParenthesis(const string& str) const
{
for (int open{0};
char i : str)
for (int open {0}; char i : str)
{
if (i == '(')
open++;
@ -1197,7 +1213,8 @@ ModelTree::testNestedParenthesis(const string &str) const
}
void
ModelTree::writeJsonModelLocalVariables(ostream &output, bool write_tef_terms, deriv_node_temp_terms_t &tef_terms) const
ModelTree::writeJsonModelLocalVariables(ostream& output, bool write_tef_terms,
deriv_node_temp_terms_t& tef_terms) const
{
/* Collect all model local variables appearing in equations, and print only
them. Printing unused model local variables can lead to a crash (see
@ -1208,8 +1225,7 @@ ModelTree::writeJsonModelLocalVariables(ostream &output, bool write_tef_terms, d
equation->collectVariables(SymbolType::modelLocalVariable, used_local_vars);
output << R"("model_local_variables": [)";
for (bool printed_something{false};
int id : local_variables_vector)
for (bool printed_something {false}; int id : local_variables_vector)
if (used_local_vars.contains(id))
{
if (exchange(printed_something, true))
@ -1220,8 +1236,7 @@ ModelTree::writeJsonModelLocalVariables(ostream &output, bool write_tef_terms, d
{
vector<string> efout;
value->writeJsonExternalFunctionOutput(efout, {}, tef_terms);
for (bool printed_efout{false};
auto &it : efout)
for (bool printed_efout {false}; auto& it : efout)
{
if (exchange(printed_efout, true))
output << ", ";
@ -1232,8 +1247,7 @@ ModelTree::writeJsonModelLocalVariables(ostream &output, bool write_tef_terms, d
output << ", ";
}
output << R"({"variable": ")" << symbol_table.getName(id)
<< R"(", "value": ")";
output << R"({"variable": ")" << symbol_table.getName(id) << R"(", "value": ")";
value->writeJsonOutput(output, {}, tef_terms);
output << R"("})" << endl;
}
@ -1251,8 +1265,7 @@ ModelTree::writeBytecodeBinFile(const filesystem::path &filename, bool is_two_bo
}
int u_count {0};
for (const auto& [indices, d1] : derivatives[1])
if (int deriv_id {indices[1]};
getTypeByDerivID(deriv_id) == SymbolType::endogenous)
if (int deriv_id {indices[1]}; getTypeByDerivID(deriv_id) == SymbolType::endogenous)
{
int eq {indices[0]};
SaveCode.write(reinterpret_cast<char*>(&eq), sizeof eq);
@ -1319,7 +1332,8 @@ ModelTree::writeBlockBytecodeBinFile(ofstream &bin_file, int block) const
}
void
ModelTree::writeLatexModelFile(const string &mod_basename, const string &latex_basename, ExprNodeOutputType output_type, bool write_equation_tags) const
ModelTree::writeLatexModelFile(const string& mod_basename, const string& latex_basename,
ExprNodeOutputType output_type, bool write_equation_tags) const
{
filesystem::create_directories(mod_basename + "/latex");
@ -1352,8 +1366,7 @@ ModelTree::writeLatexModelFile(const string &mod_basename, const string &latex_b
{
expr_t value = local_variables_table.at(id);
content_output << R"(\begin{dmath*})" << endl
<< symbol_table.getTeXName(id) << " = ";
content_output << R"(\begin{dmath*})" << endl << symbol_table.getTeXName(id) << " = ";
// Use an empty set for the temporary terms
value->writeOutput(content_output, output_type);
content_output << endl << R"(\end{dmath*})" << endl;
@ -1366,12 +1379,14 @@ ModelTree::writeLatexModelFile(const string &mod_basename, const string &latex_b
equation_tags.writeLatexOutput(content_output, eq);
content_output << R"(\begin{dmath})" << endl;
// Here it is necessary to cast to superclass ExprNode, otherwise the overloaded writeOutput() method is not found
// Here it is necessary to cast to superclass ExprNode, otherwise the overloaded writeOutput()
// method is not found
dynamic_cast<ExprNode*>(equations[eq])->writeOutput(content_output, output_type);
content_output << endl << R"(\end{dmath})" << endl;
}
output << R"(\include{)" << latex_basename + "_content" << "}" << endl
output << R"(\include{)" << latex_basename + "_content"
<< "}" << endl
<< R"(\end{document})" << endl;
output.close();
@ -1423,7 +1438,8 @@ ModelTree::addTrendVariables(const vector<int> &trend_vars, expr_t growth_factor
}
void
ModelTree::addNonstationaryVariables(const vector<int> &nonstationary_vars, bool log_deflator, expr_t deflator) noexcept(false)
ModelTree::addNonstationaryVariables(const vector<int>& nonstationary_vars, bool log_deflator,
expr_t deflator) noexcept(false)
{
for (int id : nonstationary_vars)
if (nonstationary_symbols_map.contains(id))
@ -1493,7 +1509,8 @@ ModelTree::computeParamsDerivatives(int paramsDerivsOrder)
continue;
vector<int> indices {lower_indices};
indices.push_back(param);
// At this point, indices of both endogenous and parameters are sorted in non-decreasing order
// At this point, indices of both endogenous and parameters are sorted in non-decreasing
// order
params_derivatives[{endoOrd, paramOrd}][indices] = d;
}
}
@ -1512,10 +1529,10 @@ ModelTree::computeParamsDerivativesTemporaryTerms()
for (const auto& [order, tts] : temp_terms_map)
copy(temp_terms_map[order].begin(), temp_terms_map[order].end(),
inserter(params_derivs_temporary_terms[order], params_derivs_temporary_terms[order].begin()));
inserter(params_derivs_temporary_terms[order],
params_derivs_temporary_terms[order].begin()));
for (int idx {0};
const auto &[order, tts] : params_derivs_temporary_terms)
for (int idx {0}; const auto& [order, tts] : params_derivs_temporary_terms)
for (const auto& tt : tts)
params_derivs_temporary_terms_idxs[tt] = idx++;
}
@ -1563,12 +1580,10 @@ ModelTree::writeJsonModelEquations(ostream &output, bool residuals) const
if (equations_lineno[eq])
output << R"(, "line": )" << *equations_lineno[eq];
if (auto eqtags = equation_tags.getTagsByEqn(eq);
!eqtags.empty())
if (auto eqtags = equation_tags.getTagsByEqn(eq); !eqtags.empty())
{
output << R"(, "tags": {)";
for (bool printed_something{false};
const auto &[name, value] : eqtags)
for (bool printed_something {false}; const auto& [name, value] : eqtags)
{
if (exchange(printed_something, true))
output << ", ";
@ -1605,7 +1620,8 @@ ModelTree::matlab_arch(const string &mexext)
return "maca64";
else
{
cerr << "ERROR: 'mexext' option to preprocessor incorrectly set, needed with 'use_dll'" << endl;
cerr << "ERROR: 'mexext' option to preprocessor incorrectly set, needed with 'use_dll'"
<< endl;
exit(EXIT_FAILURE);
}
}
@ -1647,12 +1663,18 @@ ModelTree::findCompilerOnMacos(const string &mexext)
#endif
filesystem::path
ModelTree::compileMEX(const filesystem::path &output_dir, const string &output_basename, const string &mexext, const vector<filesystem::path> &input_files, const filesystem::path &matlabroot, bool link) const
ModelTree::compileMEX(const filesystem::path& output_dir, const string& output_basename,
const string& mexext, const vector<filesystem::path>& input_files,
const filesystem::path& matlabroot, bool link) const
{
assert(!mex_compilation_workers.empty());
const string gcc_opt_flags { "-O3 -g0 --param ira-max-conflict-table-size=1 -fno-forward-propagate -fno-gcse -fno-dce -fno-dse -fno-tree-fre -fno-tree-pre -fno-tree-cselim -fno-tree-dse -fno-tree-dce -fno-tree-pta -fno-gcse-after-reload" };
const string clang_opt_flags { "-O3 -g0 --param ira-max-conflict-table-size=1 -Wno-unused-command-line-argument" };
const string gcc_opt_flags {
"-O3 -g0 --param ira-max-conflict-table-size=1 -fno-forward-propagate -fno-gcse -fno-dce "
"-fno-dse -fno-tree-fre -fno-tree-pre -fno-tree-cselim -fno-tree-dse -fno-tree-dce "
"-fno-tree-pta -fno-gcse-after-reload"};
const string clang_opt_flags {
"-O3 -g0 --param ira-max-conflict-table-size=1 -Wno-unused-command-line-argument"};
filesystem::path compiler;
ostringstream flags;
@ -1661,7 +1683,8 @@ ModelTree::compileMEX(const filesystem::path &output_dir, const string &output_b
if (matlabroot.empty())
{
cerr << "ERROR: 'matlabroot' option to preprocessor is not set, needed with 'use_dll'" << endl;
cerr << "ERROR: 'matlabroot' option to preprocessor is not set, needed with 'use_dll'"
<< endl;
exit(EXIT_FAILURE);
}
@ -1719,10 +1742,10 @@ ModelTree::compileMEX(const filesystem::path &output_dir, const string &output_b
if (user_set_compiler.empty())
cmd << compiler << " ";
else
if (!filesystem::exists(user_set_compiler))
else if (!filesystem::exists(user_set_compiler))
{
cerr << "Error: The specified compiler '" << user_set_compiler << "' cannot be found on your system" << endl;
cerr << "Error: The specified compiler '" << user_set_compiler
<< "' cannot be found on your system" << endl;
exit(EXIT_FAILURE);
}
else
@ -1760,11 +1783,8 @@ ModelTree::compileMEX(const filesystem::path &output_dir, const string &output_b
// The prerequisites are the object files among the input files
set<filesystem::path> prerequisites;
copy_if(input_files.begin(), input_files.end(),
inserter(prerequisites, prerequisites.end()), [](const auto &p)
{
return p.extension() == ".o";
});
copy_if(input_files.begin(), input_files.end(), inserter(prerequisites, prerequisites.end()),
[](const auto& p) { return p.extension() == ".o"; });
unique_lock<mutex> lk {mex_compilation_mut};
mex_compilation_queue.emplace_back(output_filename, prerequisites, cmd.str());
@ -1799,8 +1819,7 @@ ModelTree::reorderAuxiliaryEquations()
set<int> endos;
aux_equations[i]->collectVariables(SymbolType::endogenous, endos);
for (int endo : endos)
if (auto it = auxEndoToEq.find(endo);
it != auxEndoToEq.end() && it->second != i)
if (auto it = auxEndoToEq.find(endo); it != auxEndoToEq.end() && it->second != i)
add_edge(i, it->second, g);
}
@ -1853,7 +1872,8 @@ ModelTree::computeLeftHandSideSymbolicJacobian() const
auto not_contemporaneous = [](const pair<int, int>& p) { return p.second != 0; };
for (int eq {0}; eq < static_cast<int>(equations.size()); eq++)
if (equations_lineno[eq]) // Hand-written equation: test whether LHS has single contemporaneous endo
if (equations_lineno[eq]) // Hand-written equation: test whether LHS has single contemporaneous
// endo
{
set<pair<int, int>> endos_and_lags;
equations[eq]->arg1->collectEndogenous(endos_and_lags);
@ -1907,8 +1927,7 @@ ModelTree::initializeMEXCompilationWorkers(int numworkers, const filesystem::pat
cout << "Spawning " << numworkers << " threads for compiling MEX files." << endl;
for (int i {0}; i < numworkers; i++)
mex_compilation_workers.emplace_back([](stop_token stoken)
{
mex_compilation_workers.emplace_back([](stop_token stoken) {
unique_lock<mutex> lk {mex_compilation_mut};
filesystem::path output;
string cmd;
@ -1916,8 +1935,7 @@ ModelTree::initializeMEXCompilationWorkers(int numworkers, const filesystem::pat
/* Look for an object to compile, whose prerequisites are already
compiled. If found, remove it from the queue, save the output path and
the compilation command, and return true. Must be run under the lock. */
auto pick_job = [&cmd, &output]
{
auto pick_job = [&cmd, &output] {
for (auto it {mex_compilation_queue.begin()}; it != mex_compilation_queue.end(); ++it)
if (const auto& prerequisites {get<1>(*it)}; // Will become dangling after erase
includes(mex_compilation_done.begin(), mex_compilation_done.end(),
@ -1997,7 +2015,8 @@ ModelTree::waitForMEXCompilationWorkers()
unique_lock<mutex> lk {mex_compilation_mut};
mex_compilation_cv.wait(lk, [] {
return (mex_compilation_queue.empty() && mex_compilation_ongoing.empty())
|| !mex_compilation_failed.empty(); });
|| !mex_compilation_failed.empty();
});
if (!mex_compilation_failed.empty())
{
cerr << "Compilation failed for: ";
@ -2031,8 +2050,7 @@ vector<int>
ModelTree::computeCSCColPtr(const SparseColumnMajorOrderMatrix& matrix, int ncols)
{
vector<int> colptr(ncols + 1, matrix.size());
for (int k {0}, current_col {0};
const auto &[indices, d1] : matrix)
for (int k {0}, current_col {0}; const auto& [indices, d1] : matrix)
{
while (indices.second >= current_col)
colptr[current_col++] = k;

File diff suppressed because it is too large Load Diff

View File

@ -17,17 +17,16 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include "NumericalConstants.hh"
int
NumericalConstants::AddNonNegativeConstant(const string& iConst)
{
if (auto iter = numConstantsIndex.find(iConst);
iter != numConstantsIndex.end())
if (auto iter = numConstantsIndex.find(iConst); iter != numConstantsIndex.end())
return iter->second;
auto id = static_cast<int>(mNumericalConstants.size());

View File

@ -20,9 +20,9 @@
#ifndef _NUMERICALCONSTANTS_HH
#define _NUMERICALCONSTANTS_HH
#include <map>
#include <string>
#include <vector>
#include <map>
using namespace std;
@ -36,6 +36,7 @@ private:
vector<double> double_vals;
//! Map matching constants to their id
map<string, int> numConstantsIndex;
public:
//! Adds a non-negative constant (possibly Inf or NaN) and returns its ID
int AddNonNegativeConstant(const string& iConst);

View File

@ -17,36 +17,36 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <utility>
#include "NumericalInitialization.hh"
InitParamStatement::InitParamStatement(int symb_id_arg,
const expr_t param_value_arg,
InitParamStatement::InitParamStatement(int symb_id_arg, const expr_t param_value_arg,
const SymbolTable& symbol_table_arg) :
symb_id{symb_id_arg},
param_value{param_value_arg},
symbol_table{symbol_table_arg}
symb_id {symb_id_arg}, param_value {param_value_arg}, symbol_table {symbol_table_arg}
{
}
void
InitParamStatement::checkPass(ModFileStructure &mod_file_struct, [[maybe_unused]] WarningConsolidation &warnings)
InitParamStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if (symbol_table.getName(symb_id) == "dsge_prior_weight")
mod_file_struct.dsge_prior_weight_initialized = true;
// Needed for the workaround discussed in dynare#1173
if (symbol_table.getName(symb_id) == "optimal_policy_discount_factor")
param_value->collectVariables(SymbolType::parameter, mod_file_struct.parameters_in_planner_discount);
param_value->collectVariables(SymbolType::parameter,
mod_file_struct.parameters_in_planner_discount);
}
void
InitParamStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename, bool minimal_workspace) const
InitParamStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
bool minimal_workspace) const
{
int id = symbol_table.getTypeSpecificID(symb_id) + 1;
output << "M_.params(" << id << ") = ";
@ -59,7 +59,9 @@ InitParamStatement::writeOutput(ostream &output, [[maybe_unused]] const string &
void
InitParamStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "param_init", "name": ")" << symbol_table.getName(symb_id) << R"(", )" << R"("value": ")";
output << R"({"statementName": "param_init", "name": ")" << symbol_table.getName(symb_id)
<< R"(", )"
<< R"("value": ")";
param_value->writeJsonOutput(output, {}, {});
output << R"("})";
}
@ -163,14 +165,14 @@ InitOrEndValStatement::writeInitValues(ostream &output) const
void
InitOrEndValStatement::writeJsonInitValues(ostream& output) const
{
for (bool printed_something{false};
auto &[symb_id, value] : init_values)
for (bool printed_something {false}; auto& [symb_id, value] : init_values)
{
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
continue;
if (exchange(printed_something, true))
output << ", ";
output << R"({"name": ")" << symbol_table.getName(symb_id) << R"(", )" << R"("value": ")";
output << R"({"name": ")" << symbol_table.getName(symb_id) << R"(", )"
<< R"("value": ")";
value->writeJsonOutput(output, {}, {});
output << R"("})";
}
@ -220,9 +222,7 @@ void
InitValStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "%" << endl
<< "% INITVAL instructions" << endl
<< "%" << endl;
output << "%" << endl << "% INITVAL instructions" << endl << "%" << endl;
// Writing initval block to set initial values for variables
output << "options_.initval_file = false;" << endl;
@ -248,8 +248,7 @@ InitValStatement::writeOutputPostInit(ostream &output) const
<< "end" << endl;
}
EndValStatement::EndValStatement(init_values_t init_values_arg,
const SymbolTable &symbol_table_arg,
EndValStatement::EndValStatement(init_values_t init_values_arg, const SymbolTable& symbol_table_arg,
bool all_values_required_arg) :
InitOrEndValStatement {move(init_values_arg), symbol_table_arg, all_values_required_arg}
{
@ -288,9 +287,7 @@ void
EndValStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "%" << endl
<< "% ENDVAL instructions" << endl
<< "%" << endl;
output << "%" << endl << "% ENDVAL instructions" << endl << "%" << endl;
// Writing endval block to set terminal values for variables
output << "oo_.initial_steady_state = oo_.steady_state;" << endl
<< "oo_.initial_exo_steady_state = oo_.exo_steady_state;" << endl;
@ -346,9 +343,9 @@ EndValLearntInStatement::writeOutput(ostream &output, [[maybe_unused]] const str
{
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
continue;
output << "struct('learnt_in'," << learnt_in_period
<< ",'exo_id'," << symbol_table.getTypeSpecificID(symb_id)+1
<< ",'type','" << typeToString(type) << "'"
output << "struct('learnt_in'," << learnt_in_period << ",'exo_id',"
<< symbol_table.getTypeSpecificID(symb_id) + 1 << ",'type','" << typeToString(type)
<< "'"
<< ",'value',";
value->writeOutput(output);
output << ");" << endl;
@ -359,10 +356,8 @@ EndValLearntInStatement::writeOutput(ostream &output, [[maybe_unused]] const str
void
EndValLearntInStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "endval", "learnt_in": )"
<< learnt_in_period << R"(, "vals": [)";
for (bool printed_something{false};
auto &[type, symb_id, value] : learnt_end_values)
output << R"({"statementName": "endval", "learnt_in": )" << learnt_in_period << R"(, "vals": [)";
for (bool printed_something {false}; auto& [type, symb_id, value] : learnt_end_values)
{
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
continue;
@ -430,15 +425,18 @@ HistValStatement::writeOutput(ostream &output, [[maybe_unused]] const string &ba
output << "%" << endl
<< "% HISTVAL instructions" << endl
<< "%" << endl
<< "M_.histval_dseries = dseries(zeros(M_.orig_maximum_lag_with_diffs_expanded, M_.orig_endo_nbr"
<< "M_.histval_dseries = dseries(zeros(M_.orig_maximum_lag_with_diffs_expanded, "
"M_.orig_endo_nbr"
<< (symbol_table.AuxVarsSize() > 0 ? "+sum([M_.aux_vars.type]==6)" : "")
<< (symbol_table.exo_nbr() > 0 ? "+M_.exo_nbr" : "")
<< (symbol_table.exo_det_nbr() > 0 ? "+M_.exo_det_nbr" : "")
<< "), dates(sprintf('%dY', -M_.orig_maximum_lag_with_diffs_expanded+1)), [ M_.endo_names(1:M_.orig_endo_nbr); "
<< (symbol_table.AuxVarsSize() > 0 ? "M_.endo_names([M_.aux_vars(find([M_.aux_vars.type]==6)).endo_index]); " : "")
<< "), dates(sprintf('%dY', -M_.orig_maximum_lag_with_diffs_expanded+1)), [ "
"M_.endo_names(1:M_.orig_endo_nbr); "
<< (symbol_table.AuxVarsSize() > 0
? "M_.endo_names([M_.aux_vars(find([M_.aux_vars.type]==6)).endo_index]); "
: "")
<< (symbol_table.exo_nbr() > 0 ? "M_.exo_names; " : "")
<< (symbol_table.exo_det_nbr() > 0 ? "M_.exo_det_names; " : "")
<< "]);" << endl;
<< (symbol_table.exo_det_nbr() > 0 ? "M_.exo_det_names; " : "") << "]);" << endl;
for (const auto& [key, value] : hist_values)
{
@ -446,29 +444,38 @@ HistValStatement::writeOutput(ostream &output, [[maybe_unused]] const string &ba
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
continue;
output << "M_.histval_dseries{'" << symbol_table.getName(symb_id) << "'}(dates('" << lag << "Y'))=";
output << "M_.histval_dseries{'" << symbol_table.getName(symb_id) << "'}(dates('" << lag
<< "Y'))=";
value->writeOutput(output);
output << ";" << endl;
}
output << "if exist(['+' M_.fname '/dynamic_set_auxiliary_series.m'])" << endl
<< " eval(['M_.histval_dseries = ' M_.fname '.dynamic_set_auxiliary_series(M_.histval_dseries, M_.params);']);" << endl
<< " eval(['M_.histval_dseries = ' M_.fname "
"'.dynamic_set_auxiliary_series(M_.histval_dseries, M_.params);']);"
<< endl
<< "end" << endl
<< "M_.endo_histval = M_.histval_dseries{M_.endo_names{:}}(dates(sprintf('%dY', 1-M_.maximum_lag)):dates('0Y')).data';" << endl
<< "M_.endo_histval(isnan(M_.endo_histval)) = 0;" << endl; // Ensure that lead aux variables do not have a NaN
<< "M_.endo_histval = M_.histval_dseries{M_.endo_names{:}}(dates(sprintf('%dY', "
"1-M_.maximum_lag)):dates('0Y')).data';"
<< endl
<< "M_.endo_histval(isnan(M_.endo_histval)) = 0;"
<< endl; // Ensure that lead aux variables do not have a NaN
if (symbol_table.exo_nbr() > 0)
output << "M_.exo_histval = M_.histval_dseries{M_.exo_names{:}}(dates(sprintf('%dY', 1-M_.maximum_lag)):dates('0Y')).data';" << endl;
output << "M_.exo_histval = M_.histval_dseries{M_.exo_names{:}}(dates(sprintf('%dY', "
"1-M_.maximum_lag)):dates('0Y')).data';"
<< endl;
if (symbol_table.exo_det_nbr() > 0)
output << "M_.exo_det_histval = M_.histval_dseries{M_.exo_det_names{:}}(dates(sprintf('%dY', 1-M_.maximum_lag)):dates('0Y')).data';" << endl;
output << "M_.exo_det_histval = M_.histval_dseries{M_.exo_det_names{:}}(dates(sprintf('%dY', "
"1-M_.maximum_lag)):dates('0Y')).data';"
<< endl;
}
void
HistValStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "histval", "vals": [)";
for (bool printed_something{false};
const auto &[key, value] : hist_values)
for (bool printed_something {false}; const auto& [key, value] : hist_values)
{
auto& [symb_id, lag] = key;
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
@ -476,8 +483,7 @@ HistValStatement::writeJsonOutput(ostream &output) const
if (exchange(printed_something, true))
output << ", ";
output << R"({ "name": ")" << symbol_table.getName(symb_id) << R"(")"
<< R"(, "lag": )" << lag
<< R"(, "value": ")";
<< R"(, "lag": )" << lag << R"(, "value": ")";
value->writeJsonOutput(output, {}, {});
output << R"("})";
}
@ -498,7 +504,9 @@ InitvalFileStatement::writeOutput(ostream &output, [[maybe_unused]] const string
<< "%" << endl
<< "options_.initval_file = true;" << endl;
options_list.writeOutput(output, "options_initvalf");
output << "[oo_.initval_series, options_.periods] = histvalf_initvalf('INITVALF', M_, options_initvalf);" << endl;
output << "[oo_.initval_series, options_.periods] = histvalf_initvalf('INITVALF', M_, "
"options_initvalf);"
<< endl;
}
void
@ -527,7 +535,9 @@ HistvalFileStatement::writeOutput(ostream &output, [[maybe_unused]] const string
<< "%" << endl
<< "options_.histval_file = true;" << endl;
options_list.writeOutput(output, "options_histvalf");
output << "[M_.endo_histval, M_.exo_histval, M_.exo_det_histval] = histvalf(M_, options_histvalf);" << endl;
output
<< "[M_.endo_histval, M_.exo_histval, M_.exo_det_histval] = histvalf(M_, options_histvalf);"
<< endl;
}
void
@ -558,7 +568,8 @@ HomotopySetupStatement::writeOutput(ostream &output, [[maybe_unused]] const stri
output << "%" << endl
<< "% HOMOTOPY_SETUP instructions" << endl
<< "%" << endl
<< "options_.homotopy_from_initval_to_endval = " << boolalpha << from_initval_to_endval << ';' << endl
<< "options_.homotopy_from_initval_to_endval = " << boolalpha << from_initval_to_endval
<< ';' << endl
<< "options_.homotopy_values = zeros(0, 4);" << endl;
for (auto [symb_id, expression1, expression2] : homotopy_values)
@ -566,7 +577,8 @@ HomotopySetupStatement::writeOutput(ostream &output, [[maybe_unused]] const stri
const SymbolType type = symbol_table.getType(symb_id);
const int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
output << "options_.homotopy_values = vertcat(options_.homotopy_values, [ " << static_cast<int>(type) << ", " << tsid << ", ";
output << "options_.homotopy_values = vertcat(options_.homotopy_values, [ "
<< static_cast<int>(type) << ", " << tsid << ", ";
if (expression1)
expression1->writeOutput(output);
else
@ -608,7 +620,8 @@ SaveParamsAndSteadyStateStatement::SaveParamsAndSteadyStateStatement(string file
}
void
SaveParamsAndSteadyStateStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
SaveParamsAndSteadyStateStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "save_params_and_steady_state('" << filename << "');" << endl;
@ -622,8 +635,8 @@ SaveParamsAndSteadyStateStatement::writeJsonOutput(ostream &output) const
<< "}";
}
LoadParamsAndSteadyStateStatement::LoadParamsAndSteadyStateStatement(const filesystem::path &filename,
const SymbolTable &symbol_table_arg,
LoadParamsAndSteadyStateStatement::LoadParamsAndSteadyStateStatement(
const filesystem::path& filename, const SymbolTable& symbol_table_arg,
WarningConsolidation& warnings) :
symbol_table {symbol_table_arg}
{
@ -651,14 +664,16 @@ LoadParamsAndSteadyStateStatement::LoadParamsAndSteadyStateStatement(const files
}
catch (SymbolTable::UnknownSymbolNameException& e)
{
warnings << "WARNING: Unknown symbol " << symb_name << " in " << filename.string() << endl;
warnings << "WARNING: Unknown symbol " << symb_name << " in " << filename.string()
<< endl;
}
}
f.close();
}
void
LoadParamsAndSteadyStateStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
LoadParamsAndSteadyStateStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
for (const auto& [id, value] : content)
@ -678,7 +693,8 @@ LoadParamsAndSteadyStateStatement::writeOutput(ostream &output, [[maybe_unused]]
output << "oo_.exo_det_steady_state";
break;
default:
cerr << "ERROR: Unsupported variable type for " << symbol_table.getName(id) << " in load_params_and_steady_state" << endl;
cerr << "ERROR: Unsupported variable type for " << symbol_table.getName(id)
<< " in load_params_and_steady_state" << endl;
exit(EXIT_FAILURE);
}
@ -692,8 +708,7 @@ LoadParamsAndSteadyStateStatement::writeJsonOutput(ostream &output) const
{
output << R"({"statementName": "load_params_and_steady_state",)"
<< R"("values": [)";
for (bool printed_something{false};
const auto &[id, value] : content)
for (bool printed_something {false}; const auto& [id, value] : content)
{
if (exchange(printed_something, true))
output << ", ";

View File

@ -20,14 +20,14 @@
#ifndef _NUMERICALINITIALIZATION_HH
#define _NUMERICALINITIALIZATION_HH
#include <filesystem>
#include <map>
#include <string>
#include <vector>
#include <map>
#include <filesystem>
#include "SymbolTable.hh"
#include "ExprNode.hh"
#include "Statement.hh"
#include "SymbolTable.hh"
using namespace std;
@ -37,6 +37,7 @@ private:
const int symb_id;
const expr_t param_value;
const SymbolTable& symbol_table;
public:
InitParamStatement(int symb_id_arg, const expr_t param_value_arg,
const SymbolTable& symbol_table_arg);
@ -55,18 +56,20 @@ public:
an initialization can depend on a previously initialized variable inside the block
*/
using init_values_t = vector<pair<int, expr_t>>;
protected:
const init_values_t init_values;
const SymbolTable& symbol_table;
const bool all_values_required;
public:
InitOrEndValStatement(init_values_t init_values_arg,
const SymbolTable &symbol_table_arg,
InitOrEndValStatement(init_values_t init_values_arg, const SymbolTable& symbol_table_arg,
bool all_values_required_arg);
//! Return set of unused variables by type
set<int> getUninitializedVariables(SymbolType type);
//! Fill eval context with variables values
void fillEvalContext(eval_context_t& eval_context) const;
protected:
void writeInitValues(ostream& output) const;
void writeJsonInitValues(ostream& output) const;
@ -75,8 +78,7 @@ protected:
class InitValStatement : public InitOrEndValStatement
{
public:
InitValStatement(init_values_t init_values_arg,
const SymbolTable &symbol_table_arg,
InitValStatement(init_values_t init_values_arg, const SymbolTable& symbol_table_arg,
bool all_values_required_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -88,8 +90,7 @@ public:
class EndValStatement : public InitOrEndValStatement
{
public:
EndValStatement(init_values_t init_values_arg,
const SymbolTable &symbol_table_arg,
EndValStatement(init_values_t init_values_arg, const SymbolTable& symbol_table_arg,
bool all_values_required_arg);
//! Workaround for trac ticket #35
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -110,12 +111,13 @@ public:
// The tuple is (type, symb_id, value)
using learnt_end_values_t = vector<tuple<LearntEndValType, int, expr_t>>;
const learnt_end_values_t learnt_end_values;
private:
const SymbolTable& symbol_table;
static string typeToString(LearntEndValType type);
public:
EndValLearntInStatement(int learnt_in_period_arg,
learnt_end_values_t learnt_end_values_arg,
EndValLearntInStatement(int learnt_in_period_arg, learnt_end_values_t learnt_end_values_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -131,13 +133,14 @@ public:
Maps pairs (symbol_id, lag) to expr_t
*/
using hist_values_t = map<pair<int, int>, expr_t>;
private:
const hist_values_t hist_values;
const SymbolTable& symbol_table;
const bool all_values_required;
public:
HistValStatement(hist_values_t hist_values_arg,
const SymbolTable &symbol_table_arg,
HistValStatement(hist_values_t hist_values_arg, const SymbolTable& symbol_table_arg,
bool all_values_required_arg);
//! Workaround for trac ticket #157
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
@ -149,6 +152,7 @@ class InitvalFileStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit InitvalFileStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -159,6 +163,7 @@ class HistvalFileStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit HistvalFileStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -171,10 +176,12 @@ public:
//! Stores the declarations of homotopy_setup
/*! Order matter so we use a vector. First expr_t can be NULL if no initial value given. */
using homotopy_values_t = vector<tuple<int, expr_t, expr_t>>;
private:
const bool from_initval_to_endval; // Whether the from_initval_to_endval option was passed
const homotopy_values_t homotopy_values;
const SymbolTable& symbol_table;
public:
HomotopySetupStatement(bool from_initval_to_endval_arg, homotopy_values_t homotopy_values_arg,
const SymbolTable& symbol_table_arg);
@ -186,6 +193,7 @@ class SaveParamsAndSteadyStateStatement : public Statement
{
private:
const string filename;
public:
explicit SaveParamsAndSteadyStateStatement(string filename_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -199,6 +207,7 @@ private:
//! Content of the file
/*! Maps symbol ID to numeric value (stored as string) */
map<int, string> content;
public:
LoadParamsAndSteadyStateStatement(const filesystem::path& filename,
const SymbolTable& symbol_table_arg,

File diff suppressed because it is too large Load Diff

View File

@ -24,24 +24,24 @@
# error Impossible to include both ParsingDriver.hh and macro/Driver.hh
#endif
#include <string>
#include <vector>
#include <istream>
#include <stack>
#include <optional>
#include <stack>
#include <string>
#include <string_view>
#include <vector>
#include "ModFile.hh"
#include "SymbolList.hh"
class ParsingDriver;
#include "ExprNode.hh"
#include "DynareBison.hh"
#include "ExprNode.hh"
#include "ComputingTasks.hh"
#include "Shocks.hh"
#include "NumericalInitialization.hh"
#include "DynamicModel.hh"
#include "NumericalInitialization.hh"
#include "Shocks.hh"
using namespace std;
@ -66,8 +66,7 @@ public:
//! The main lexing function
Dynare::parser::token_type lex(Dynare::parser::semantic_type* yylval,
Dynare::parser::location_type *yylloc,
ParsingDriver &driver);
Dynare::parser::location_type* yylloc, ParsingDriver& driver);
//! The filename being parsed
/*! The bison parser locations (begin and end) contain a pointer to that string */
@ -88,27 +87,32 @@ private:
//! Checks that a given symbol exists, and stops with an error message if it doesn't
void check_symbol_existence(const string& name);
//! Checks that a given symbol exists and is a parameter, and stops with an error message if it isn't
//! Checks that a given symbol exists and is a parameter, and stops with an error message if it
//! isn't
void check_symbol_is_parameter(const string& name);
//! Checks that a given symbol was assigned within a Statement
void check_symbol_is_statement_variable(const string& name);
//! Checks that a given symbol exists and is a endogenous or exogenous, and stops with an error message if it isn't
//! Checks that a given symbol exists and is a endogenous or exogenous, and stops with an error
//! message if it isn't
void check_symbol_is_endogenous_or_exogenous(const string& name, bool allow_exo_det);
//! Checks that a given symbol exists and is a endogenous, and stops with an error message if it isn't
//! Checks that a given symbol exists and is a endogenous, and stops with an error message if it
//! isn't
void check_symbol_is_endogenous(const string& name);
//! Checks that a given symbol exists and is a exogenous, and stops with an error message if it isn't
//! Checks that a given symbol exists and is a exogenous, and stops with an error message if it
//! isn't
void check_symbol_is_exogenous(const string& name, bool allow_exo_det);
//! Checks for symbol existence in model block. If it doesn't exist, an error message is stored to be printed at
//! the end of the model block
//! Checks for symbol existence in model block. If it doesn't exist, an error message is stored to
//! be printed at the end of the model block
void check_symbol_existence_in_model_block(const string& name);
//! Helper to add a symbol declaration (returns its symbol ID)
int declare_symbol(const string &name, SymbolType type, const string &tex_name, const vector<pair<string, string>> &partition_value);
int declare_symbol(const string& name, SymbolType type, const string& tex_name,
const vector<pair<string, string>>& partition_value);
//! Temporary store for the planner objective
unique_ptr<PlannerObjective> planner_objective;
@ -122,11 +126,13 @@ private:
DataTree* data_tree;
//! The model tree in which to add expressions currently parsed
/*! It is only a dynamic cast of data_tree pointer, and is therefore null if data_tree is not a ModelTree instance */
/*! It is only a dynamic cast of data_tree pointer, and is therefore null if data_tree is not a
* ModelTree instance */
ModelTree* model_tree;
//! The dynamic model tree in which to add expressions currently parsed
/*! It is only a dynamic cast of data_tree pointer, and is therefore null if data_tree is not a DynamicModel instance */
/*! It is only a dynamic cast of data_tree pointer, and is therefore null if data_tree is not a
* DynamicModel instance */
DynamicModel* dynamic_model;
//! Sets data_tree and model_tree pointers
@ -163,7 +169,8 @@ private:
//! Temporary storage for correlations of shocks
ShocksStatement::covar_and_corr_shocks_t corr_shocks;
//! Temporary storage for values and scales of heteroskedastic_shocks
HeteroskedasticShocksStatement::heteroskedastic_shocks_t heteroskedastic_shocks_values, heteroskedastic_shocks_scales;
HeteroskedasticShocksStatement::heteroskedastic_shocks_t heteroskedastic_shocks_values,
heteroskedastic_shocks_scales;
//! Temporary storage for initval blocks
InitOrEndValStatement::init_values_t init_values;
/* Temporary storage for endval blocks. Uses a type that encompasses both
@ -181,7 +188,8 @@ private:
RamseyConstraintsStatement::constraints_t ramsey_constraints;
//! Temporary storage for svar_identification blocks
SvarIdentificationStatement::svar_identification_restrictions_t svar_ident_restrictions;
//! Temporary storage for mapping the equation number to the restrictions within an svar_identification block
//! Temporary storage for mapping the equation number to the restrictions within an
//! svar_identification block
map<int, vector<int>> svar_equation_restrictions;
//! Temporary storage for constants exculsion within an svar_identification
bool svar_constants_exclusion;
@ -191,7 +199,8 @@ private:
bool svar_lower_cholesky;
//! Temporary storage for equation number for a restriction within an svar_identification block
int svar_equation_nbr;
//! Temporary storage for left/right handside of a restriction equation within an svar_identificaton block
//! Temporary storage for left/right handside of a restriction equation within an
//! svar_identificaton block
bool svar_left_handside;
//! Temporary storage for current restriction number in svar_identification block
map<int, int> svar_Qi_restriction_nbr;
@ -214,15 +223,18 @@ private:
stack<vector<expr_t>> stack_external_function_args;
//! Temporary storage for parameters in joint prior statement
vector<string> joint_parameters;
//! Temporary storage for the symb_id associated with the "name" symbol of the current external_function statement
//! Temporary storage for the symb_id associated with the "name" symbol of the current
//! external_function statement
int current_external_function_id;
//! Temporary storage for option list provided to external_function()
ExternalFunctionsTable::external_function_options current_external_function_options;
//! Temporary storage for a variance declared in the prior statement
expr_t prior_variance;
SubsamplesStatement::subsample_declaration_map_t subsample_declaration_map;
//! Temporary storage for subsample statement: map<pair<var_name1, var_name2>>, subsample_declaration_map >
using subsample_declarations_t = map<pair<string, string >, SubsamplesStatement::subsample_declaration_map_t >;
//! Temporary storage for subsample statement: map<pair<var_name1, var_name2>>,
//! subsample_declaration_map >
using subsample_declarations_t
= map<pair<string, string>, SubsamplesStatement::subsample_declaration_map_t>;
subsample_declarations_t subsample_declarations;
//! Temporary storage for shock_groups
vector<string> shock_group;
@ -273,7 +285,7 @@ public:
ParsingDriver(WarningConsolidation& warnings_arg, bool nostrict_arg) :
warnings {warnings_arg}, nostrict {nostrict_arg}
{
};
}
ParsingDriver(const ParsingDriver&) = delete;
ParsingDriver& operator=(const ParsingDriver&) = delete;
@ -308,13 +320,16 @@ public:
//! Warning handler using saved location
void warning(const string& m);
//! Error handler with explicit location (used in model block, accumulating error messages to be printed later)
//! Error handler with explicit location (used in model block, accumulating error messages to be
//! printed later)
void model_error(const string& m, const string& var);
void undeclared_model_variable_error(const string& m, const string& var);
//! Code shared between model_error() and error()
void create_error_string(const Dynare::parser::location_type &l, const string &m, const string &var);
void create_error_string(const Dynare::parser::location_type &l, const string &m, ostream &stream);
void create_error_string(const Dynare::parser::location_type& l, const string& m,
const string& var);
void create_error_string(const Dynare::parser::location_type& l, const string& m,
ostream& stream);
//! Check if a given symbol exists in the parsing context, and is not a mod file local variable
bool symbol_exists_and_is_not_modfile_local_or_external_function(const string& s);
@ -352,17 +367,21 @@ public:
//! Sets the FILENAME for the initial value in initval
void initval_file();
//! Declares an endogenous variable (and returns its symbol ID)
int declare_endogenous(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
int declare_endogenous(const string& name, const string& tex_name = "",
const vector<pair<string, string>>& partition_value = {});
// Handles a “var” or “var(log)” statement (without “deflator” or “log_deflator” options)
void var(const vector<tuple<string, string, vector<pair<string, string>>>> &symbol_list, bool log_option);
void var(const vector<tuple<string, string, vector<pair<string, string>>>>& symbol_list,
bool log_option);
//! Declares an exogenous variable (and returns its symbol ID)
int declare_exogenous(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
int declare_exogenous(const string& name, const string& tex_name = "",
const vector<pair<string, string>>& partition_value = {});
// Handles a “varexo” statement
void varexo(const vector<tuple<string, string, vector<pair<string, string>>>>& symbol_list);
// Handles a “varexo_det” statement
void varexo_det(const vector<tuple<string, string, vector<pair<string, string>>>>& symbol_list);
//! Declares a parameter (and returns its symbol ID)
int declare_parameter(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
int declare_parameter(const string& name, const string& tex_name = "",
const vector<pair<string, string>>& partition_value = {});
// Handles a “parameters” statement
void parameters(const vector<tuple<string, string, vector<pair<string, string>>>>& symbol_list);
// Handles a “model_local_variable” statement
@ -375,7 +394,8 @@ public:
void set_subsample_name_equal_to_date_range(string name, string date1, string date2);
//! Checks that a subsample statement (and given name) were provided for the pair name1 & name2
void check_subsample_declaration_exists(const string& name1, const string& subsample_name);
void check_subsample_declaration_exists(const string &name1, const string &name2, const string &subsample_name);
void check_subsample_declaration_exists(const string& name1, const string& name2,
const string& subsample_name);
//! Copies the set of subsamples from_name to_name
void copy_subsamples(string to_name1, string to_name2, string from_name1, string from_name2);
//! Sets the value of the planner_discount option of ramsey_{model,policy}
@ -449,7 +469,8 @@ public:
//! Writes a shocks(learnt_in=…) block
void end_shocks_learnt_in(const string& learnt_in_period, bool overwrite);
//! Writes a mshocks(learnt_in=…) block
void end_mshocks_learnt_in(const string &learnt_in_period, bool overwrite, bool relative_to_initval);
void end_mshocks_learnt_in(const string& learnt_in_period, bool overwrite,
bool relative_to_initval);
//! Writes a heteroskedastic_shocks statement
void end_heteroskedastic_shocks(bool overwrite);
/* Adds a deterministic shock, a path element inside a
@ -461,9 +482,11 @@ public:
multiply, // for “multiply” in “shocks(learnt_in)”
conditional_forecast
};
void add_det_shock(const string &var, const vector<pair<int, int>> &periods, const vector<expr_t> &values, DetShockType type);
void add_det_shock(const string& var, const vector<pair<int, int>>& periods,
const vector<expr_t>& values, DetShockType type);
//! Adds a heteroskedastic shock (either values or scales)
void add_heteroskedastic_shock(const string &var, const vector<pair<int, int>> &periods, const vector<expr_t> &values, bool scales);
void add_heteroskedastic_shock(const string& var, const vector<pair<int, int>>& periods,
const vector<expr_t>& values, bool scales);
//! Adds a std error shock
void add_stderr_shock(const string& var, expr_t value);
//! Adds a variance shock
@ -550,13 +573,15 @@ public:
//! Adds the variance option to its temporary holding place
void set_prior_variance(expr_t variance = nullptr);
//! Copies the prior from_name to_name
void copy_prior(string to_declaration_type, string to_name1, string to_name2, string to_subsample_name,
string from_declaration_type, string from_name1, string from_name2, string from_subsample_name);
void copy_prior(string to_declaration_type, string to_name1, string to_name2,
string to_subsample_name, string from_declaration_type, string from_name1,
string from_name2, string from_subsample_name);
//! Sets the options for a parameter
void set_options(string name, string subsample_name);
//! Copies the options from_name to_name
void copy_options(string to_declaration_type, string to_name1, string to_name2, string to_subsample_name,
string from_declaration_type, string from_name1, string from_name2, string from_subsample_name);
void copy_options(string to_declaration_type, string to_name1, string to_name2,
string to_subsample_name, string from_declaration_type, string from_name1,
string from_name2, string from_subsample_name);
//! Sets the prior for estimated std dev
void set_std_prior(string name, string subsample_name);
//! Sets the options for estimated std dev
@ -836,11 +861,13 @@ public:
expr_t add_model_var_or_external_function(const string& function_name, bool in_model_block);
//! Adds a native statement
void add_native(string s);
//! Adds a native statement, first removing the set of characters passed in token (and everything after)
//! Adds a native statement, first removing the set of characters passed in token (and everything
//! after)
void add_native_remove_charset(string_view str, string_view token);
//! Adds a verbatim statement
void add_verbatim(string s);
//! Adds a verbatim statement, first removing the set of characters passed in token (and everything after)
//! Adds a verbatim statement, first removing the set of characters passed in token (and
//! everything after)
void add_verbatim_remove_charset(string_view str, string_view token);
//! Resets data_tree and model_tree pointers to default (i.e. mod_file->expressions_tree)
void reset_data_tree();
@ -851,14 +878,19 @@ public:
//! Add a multiple assignment equation in steady_state_model block
void add_steady_state_model_equal_multiple(const vector<string>& symbol_list, expr_t expr);
//! Ends declaration of trend variable
void end_trend_var(bool log_trend, expr_t growth_factor, const vector<pair<string, string>> &symbol_list);
void end_trend_var(bool log_trend, expr_t growth_factor,
const vector<pair<string, string>>& symbol_list);
//! Handles a “var(deflator=…)”, “var(log, deflator=…)” or “var(log_deflator=…)” statement
void end_nonstationary_var(bool log_deflator, expr_t deflator, const vector<tuple<string, string, vector<pair<string, string>>>> &symbol_list, bool log_option);
void end_nonstationary_var(
bool log_deflator, expr_t deflator,
const vector<tuple<string, string, vector<pair<string, string>>>>& symbol_list,
bool log_option);
//! Add a graph format to the list of formats requested
void add_graph_format(string name);
//! Add the graph_format option to the OptionsList structure
void process_graph_format_option();
//! Add the graph_format option to the initial_condition_decomp substructure of the OptionsList structure
//! Add the graph_format option to the initial_condition_decomp substructure of the OptionsList
//! structure
void initial_condition_decomp_process_graph_format_option();
//! Add the graph_format option to the plot_shock_decomp substructure of the OptionsList structure
void plot_shock_decomp_process_graph_format_option();
@ -867,11 +899,13 @@ public:
//! Processing the parallel_local_files option
void add_parallel_local_file(string filename);
//! Add an item of a moment_calibration statement
void add_moment_calibration_item(const string &endo1, const string &endo2, string lags, const pair<expr_t, expr_t> &range);
void add_moment_calibration_item(const string& endo1, const string& endo2, string lags,
const pair<expr_t, expr_t>& range);
//! End a moment_calibration statement
void end_moment_calibration();
//! Add an item of an irf_calibration statement
void add_irf_calibration_item(const string &endo, string periods, const string &exo, const pair<expr_t, expr_t> &range);
void add_irf_calibration_item(const string& endo, string periods, const string& exo,
const pair<expr_t, expr_t>& range);
//! End a moment_calibration statement
void end_irf_calibration();
//! Add a shock to a group
@ -902,7 +936,8 @@ public:
//! Start parsing an occbin_constraints block
void begin_occbin_constraints();
//! Add an occbin_constraints block
void end_occbin_constraints(vector<tuple<string, BinaryOpNode *, BinaryOpNode *, expr_t, expr_t>> constraints);
void end_occbin_constraints(
vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> constraints);
// Process a model_remove statement
void model_remove(const vector<map<string, string>>& listed_eqs_by_tags);
// Begin a model_replace statement
@ -922,7 +957,8 @@ public:
// Returns true iff the string is a legal symbol identifier (see NAME token in lexer)
static bool isSymbolIdentifier(const string& str);
// Given an Occbin regime name, returns the corresponding auxiliary parameter
static string buildOccbinBindParamName(const string &regime)
static string
buildOccbinBindParamName(const string& regime)
{
return "occbin_" + regime + "_bind";
}

View File

@ -44,12 +44,9 @@ AbstractShocksStatement::writeDetShocks(ostream &output) const
const auto& [period1, period2, value] : shock_vec)
{
output << "M_.det_shocks = [ M_.det_shocks;" << endl
<< boolalpha
<< "struct('exo_det'," << exo_det
<< ",'exo_id'," << symbol_table.getTypeSpecificID(id)+1
<< ",'type','" << typeToString(type) << "'"
<< ",'periods'," << period1 << ":" << period2
<< ",'value',";
<< boolalpha << "struct('exo_det'," << exo_det << ",'exo_id',"
<< symbol_table.getTypeSpecificID(id) + 1 << ",'type','" << typeToString(type) << "'"
<< ",'periods'," << period1 << ":" << period2 << ",'value',";
value->writeOutput(output);
output << ") ];" << endl;
@ -63,15 +60,13 @@ void
AbstractShocksStatement::writeJsonDetShocks(ostream& output) const
{
output << R"("deterministic_shocks": [)";
for (bool printed_something{false};
const auto &[id, shock_vec] : det_shocks)
for (bool printed_something {false}; const auto& [id, shock_vec] : det_shocks)
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"var": ")" << symbol_table.getName(id) << R"(", )"
<< R"("values": [)";
for (bool printed_something2{false};
const auto &[period1, period2, value] : shock_vec)
for (bool printed_something2 {false}; const auto& [period1, period2, value] : shock_vec)
{
if (exchange(printed_something2, true))
output << ", ";
@ -101,14 +96,14 @@ AbstractShocksStatement::typeToString(ShockType type)
__builtin_unreachable(); // Silence GCC warning
}
ShocksStatement::ShocksStatement(bool overwrite_arg,
det_shocks_t det_shocks_arg,
ShocksStatement::ShocksStatement(bool overwrite_arg, det_shocks_t det_shocks_arg,
var_and_std_shocks_t var_shocks_arg,
var_and_std_shocks_t std_shocks_arg,
covar_and_corr_shocks_t covar_shocks_arg,
covar_and_corr_shocks_t corr_shocks_arg,
const SymbolTable& symbol_table_arg) :
AbstractShocksStatement{overwrite_arg, ShockType::level, move(det_shocks_arg), symbol_table_arg},
AbstractShocksStatement {overwrite_arg, ShockType::level, move(det_shocks_arg),
symbol_table_arg},
var_shocks {move(var_shocks_arg)},
std_shocks {move(std_shocks_arg)},
covar_shocks {move(covar_shocks_arg)},
@ -120,16 +115,14 @@ void
ShocksStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "%" << endl
<< "% SHOCKS instructions" << endl
<< "%" << endl;
output << "%" << endl << "% SHOCKS instructions" << endl << "%" << endl;
if (overwrite)
{
output << "M_.det_shocks = [];" << endl;
output << "M_.Sigma_e = zeros(" << symbol_table.exo_nbr() << ", "
<< symbol_table.exo_nbr() << ");" << endl
output << "M_.Sigma_e = zeros(" << symbol_table.exo_nbr() << ", " << symbol_table.exo_nbr()
<< ");" << endl
<< "M_.Correlation_matrix = eye(" << symbol_table.exo_nbr() << ", "
<< symbol_table.exo_nbr() << ");" << endl;
@ -139,9 +132,7 @@ ShocksStatement::writeOutput(ostream &output, [[maybe_unused]] const string &bas
<< "M_.Correlation_matrix_ME = eye(" << symbol_table.observedVariablesNbr() << ", "
<< symbol_table.observedVariablesNbr() << ");" << endl;
else
output << "M_.H = 0;" << endl
<< "M_.Correlation_matrix_ME = 1;" << endl;
output << "M_.H = 0;" << endl << "M_.Correlation_matrix_ME = 1;" << endl;
}
writeDetShocks(output);
@ -169,8 +160,7 @@ ShocksStatement::writeJsonOutput(ostream &output) const
writeJsonDetShocks(output);
}
output << R"(, "variance": [)";
for (bool printed_something{false};
auto &[id, value] : var_shocks)
for (bool printed_something {false}; auto& [id, value] : var_shocks)
{
if (exchange(printed_something, true))
output << ", ";
@ -181,8 +171,7 @@ ShocksStatement::writeJsonOutput(ostream &output) const
}
output << "]"
<< R"(, "stderr": [)";
for (bool printed_something{false};
auto &[id, value] : std_shocks)
for (bool printed_something {false}; auto& [id, value] : std_shocks)
{
if (exchange(printed_something, true))
output << ", ";
@ -193,8 +182,7 @@ ShocksStatement::writeJsonOutput(ostream &output) const
}
output << "]"
<< R"(, "covariance": [)";
for (bool printed_something{false};
auto &[ids, value] : covar_shocks)
for (bool printed_something {false}; auto& [ids, value] : covar_shocks)
{
if (exchange(printed_something, true))
output << ", ";
@ -207,8 +195,7 @@ ShocksStatement::writeJsonOutput(ostream &output) const
}
output << "]"
<< R"(, "correlation": [)";
for (bool printed_something{false};
auto &[ids, value] : corr_shocks)
for (bool printed_something {false}; auto& [ids, value] : corr_shocks)
{
if (exchange(printed_something, true))
output << ", ";
@ -224,8 +211,7 @@ ShocksStatement::writeJsonOutput(ostream &output) const
}
void
ShocksStatement::writeVarOrStdShock(ostream &output, const pair<int, expr_t> &it,
bool stddev) const
ShocksStatement::writeVarOrStdShock(ostream& output, const pair<int, expr_t>& it, bool stddev) const
{
SymbolType type = symbol_table.getType(it.first);
assert(type == SymbolType::exogenous || symbol_table.isObservedVariable(it.first));
@ -268,7 +254,8 @@ ShocksStatement::writeCovarOrCorrShock(ostream &output, const pair<pair<int, int
SymbolType type1 = symbol_table.getType(it.first.first);
SymbolType type2 = symbol_table.getType(it.first.second);
assert((type1 == SymbolType::exogenous && type2 == SymbolType::exogenous)
|| (symbol_table.isObservedVariable(it.first.first) && symbol_table.isObservedVariable(it.first.second)));
|| (symbol_table.isObservedVariable(it.first.first)
&& symbol_table.isObservedVariable(it.first.second)));
string matrix, corr_matrix;
int id1, id2;
if (type1 == SymbolType::exogenous)
@ -289,19 +276,19 @@ ShocksStatement::writeCovarOrCorrShock(ostream &output, const pair<pair<int, int
output << matrix << "(" << id1 << ", " << id2 << ") = ";
it.second->writeOutput(output);
if (corr)
output << "*sqrt(" << matrix << "(" << id1 << ", " << id1 << ")*"
<< matrix << "(" << id2 << ", " << id2 << "))";
output << "*sqrt(" << matrix << "(" << id1 << ", " << id1 << ")*" << matrix << "(" << id2
<< ", " << id2 << "))";
output << ";" << endl
<< matrix << "(" << id2 << ", " << id1 << ") = "
<< matrix << "(" << id1 << ", " << id2 << ");" << endl;
<< matrix << "(" << id2 << ", " << id1 << ") = " << matrix << "(" << id1 << ", " << id2
<< ");" << endl;
if (corr)
{
output << corr_matrix << "(" << id1 << ", " << id2 << ") = ";
it.second->writeOutput(output);
output << ";" << endl
<< corr_matrix << "(" << id2 << ", " << id1 << ") = "
<< corr_matrix << "(" << id1 << ", " << id2 << ");" << endl;
<< corr_matrix << "(" << id2 << ", " << id1 << ") = " << corr_matrix << "(" << id1
<< ", " << id2 << ");" << endl;
}
}
@ -324,22 +311,24 @@ ShocksStatement::checkPass(ModFileStructure &mod_file_struct,
Also Determine if there is a calibrated measurement error */
for (auto [id, val] : var_shocks)
{
if (symbol_table.getType(id) != SymbolType::exogenous
&& !symbol_table.isObservedVariable(id))
if (symbol_table.getType(id) != SymbolType::exogenous && !symbol_table.isObservedVariable(id))
{
cerr << "shocks: setting a variance on '"
<< symbol_table.getName(id) << "' is not allowed, because it is neither an exogenous variable nor an observed endogenous variable" << endl;
cerr << "shocks: setting a variance on '" << symbol_table.getName(id)
<< "' is not allowed, because it is neither an exogenous variable nor an observed "
"endogenous variable"
<< endl;
exit(EXIT_FAILURE);
}
}
for (auto [id, val] : std_shocks)
{
if (symbol_table.getType(id) != SymbolType::exogenous
&& !symbol_table.isObservedVariable(id))
if (symbol_table.getType(id) != SymbolType::exogenous && !symbol_table.isObservedVariable(id))
{
cerr << "shocks: setting a standard error on '"
<< symbol_table.getName(id) << "' is not allowed, because it is neither an exogenous variable nor an observed endogenous variable" << endl;
cerr << "shocks: setting a standard error on '" << symbol_table.getName(id)
<< "' is not allowed, because it is neither an exogenous variable nor an observed "
"endogenous variable"
<< endl;
exit(EXIT_FAILURE);
}
}
@ -353,9 +342,11 @@ ShocksStatement::checkPass(ModFileStructure &mod_file_struct,
|| (symbol_table.isObservedVariable(symb_id1)
&& symbol_table.isObservedVariable(symb_id2))))
{
cerr << "shocks: setting a covariance between '"
<< symbol_table.getName(symb_id1) << "' and '"
<< symbol_table.getName(symb_id2) << "'is not allowed; covariances can only be specified for exogenous or observed endogenous variables of same type" << endl;
cerr << "shocks: setting a covariance between '" << symbol_table.getName(symb_id1)
<< "' and '" << symbol_table.getName(symb_id2)
<< "'is not allowed; covariances can only be specified for exogenous or observed "
"endogenous variables of same type"
<< endl;
exit(EXIT_FAILURE);
}
}
@ -369,9 +360,11 @@ ShocksStatement::checkPass(ModFileStructure &mod_file_struct,
|| (symbol_table.isObservedVariable(symb_id1)
&& symbol_table.isObservedVariable(symb_id2))))
{
cerr << "shocks: setting a correlation between '"
<< symbol_table.getName(symb_id1) << "' and '"
<< symbol_table.getName(symb_id2) << "'is not allowed; correlations can only be specified for exogenous or observed endogenous variables of same type" << endl;
cerr << "shocks: setting a correlation between '" << symbol_table.getName(symb_id1)
<< "' and '" << symbol_table.getName(symb_id2)
<< "'is not allowed; correlations can only be specified for exogenous or observed "
"endogenous variables of same type"
<< endl;
exit(EXIT_FAILURE);
}
}
@ -402,13 +395,11 @@ ShocksStatement::has_calibrated_measurement_errors() const
return true;
for (const auto& [ids, val] : covar_shocks)
if (symbol_table.isObservedVariable(ids.first)
|| symbol_table.isObservedVariable(ids.second))
if (symbol_table.isObservedVariable(ids.first) || symbol_table.isObservedVariable(ids.second))
return true;
for (const auto& [ids, val] : corr_shocks)
if (symbol_table.isObservedVariable(ids.first)
|| symbol_table.isObservedVariable(ids.second))
if (symbol_table.isObservedVariable(ids.first) || symbol_table.isObservedVariable(ids.second))
return true;
return false;
@ -418,7 +409,8 @@ MShocksStatement::MShocksStatement(bool overwrite_arg, bool relative_to_initval_
det_shocks_t det_shocks_arg,
const SymbolTable& symbol_table_arg) :
AbstractShocksStatement {overwrite_arg,
relative_to_initval_arg ? ShockType::multiplyInitialSteadyState : ShockType::multiplySteadyState,
relative_to_initval_arg ? ShockType::multiplyInitialSteadyState
: ShockType::multiplySteadyState,
move(det_shocks_arg), symbol_table_arg},
relative_to_initval {relative_to_initval_arg}
{
@ -428,9 +420,7 @@ void
MShocksStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "%" << endl
<< "% MSHOCKS instructions" << endl
<< "%" << endl;
output << "%" << endl << "% MSHOCKS instructions" << endl << "%" << endl;
if (overwrite)
output << "M_.det_shocks = [];" << endl;
@ -442,8 +432,8 @@ void
MShocksStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "mshocks")"
<< R"(, "overwrite": )" << boolalpha << overwrite
<< R"(, "relative_to_initval": )" << boolalpha << relative_to_initval;
<< R"(, "overwrite": )" << boolalpha << overwrite << R"(, "relative_to_initval": )"
<< boolalpha << relative_to_initval;
if (!det_shocks.empty())
{
output << ", ";
@ -452,10 +442,11 @@ MShocksStatement::writeJsonOutput(ostream &output) const
output << "}";
}
ShocksSurpriseStatement::ShocksSurpriseStatement(bool overwrite_arg,
AbstractShocksStatement::det_shocks_t surprise_shocks_arg,
ShocksSurpriseStatement::ShocksSurpriseStatement(
bool overwrite_arg, AbstractShocksStatement::det_shocks_t surprise_shocks_arg,
const SymbolTable& symbol_table_arg) :
overwrite{overwrite_arg}, surprise_shocks{move(surprise_shocks_arg)},
overwrite {overwrite_arg},
surprise_shocks {move(surprise_shocks_arg)},
symbol_table {symbol_table_arg}
{
}
@ -478,9 +469,8 @@ ShocksSurpriseStatement::writeOutput(ostream &output, [[maybe_unused]] const str
for (const auto& [id, shock_vec] : surprise_shocks)
for (const auto& [period1, period2, value] : shock_vec)
{
output << "struct('exo_id'," << symbol_table.getTypeSpecificID(id)+1
<< ",'periods'," << period1 << ":" << period2
<< ",'value',";
output << "struct('exo_id'," << symbol_table.getTypeSpecificID(id) + 1 << ",'periods',"
<< period1 << ":" << period2 << ",'value',";
value->writeOutput(output);
output << ");" << endl;
}
@ -493,15 +483,13 @@ ShocksSurpriseStatement::writeJsonOutput(ostream &output) const
output << R"({"statementName": "shocks")"
<< R"(, "surprise": true)"
<< R"(, "surprise_shocks": [)";
for (bool printed_something{false};
const auto &[id, shock_vec] : surprise_shocks)
for (bool printed_something {false}; const auto& [id, shock_vec] : surprise_shocks)
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"var": ")" << symbol_table.getName(id) << R"(", )"
<< R"("values": [)";
for (bool printed_something2{false};
const auto &[period1, period2, value] : shock_vec)
for (bool printed_something2 {false}; const auto& [period1, period2, value] : shock_vec)
{
if (exchange(printed_something2, true))
output << ", ";
@ -519,8 +507,10 @@ ShocksSurpriseStatement::writeJsonOutput(ostream &output) const
ShocksLearntInStatement::ShocksLearntInStatement(int learnt_in_period_arg, bool overwrite_arg,
learnt_shocks_t learnt_shocks_arg,
const SymbolTable& symbol_table_arg) :
learnt_in_period{learnt_in_period_arg}, overwrite{overwrite_arg},
learnt_shocks{move(learnt_shocks_arg)}, symbol_table{symbol_table_arg}
learnt_in_period {learnt_in_period_arg},
overwrite {overwrite_arg},
learnt_shocks {move(learnt_shocks_arg)},
symbol_table {symbol_table_arg}
{
}
@ -556,17 +546,17 @@ ShocksLearntInStatement::writeOutput(ostream &output, [[maybe_unused]] const str
{
if (overwrite)
output << "if ~isempty(M_.learnt_shocks)" << endl
<< " M_.learnt_shocks = M_.learnt_shocks([M_.learnt_shocks.learnt_in] ~= " << learnt_in_period << ");" << endl
<< " M_.learnt_shocks = M_.learnt_shocks([M_.learnt_shocks.learnt_in] ~= "
<< learnt_in_period << ");" << endl
<< "end" << endl;
output << "M_.learnt_shocks = [ M_.learnt_shocks;" << endl;
for (const auto& [id, shock_vec] : learnt_shocks)
for (const auto& [type, period1, period2, value] : shock_vec)
{
output << "struct('learnt_in'," << learnt_in_period
<< ",'exo_id'," << symbol_table.getTypeSpecificID(id)+1
<< ",'periods'," << period1 << ":" << period2
<< ",'type','" << typeToString(type) << "'"
output << "struct('learnt_in'," << learnt_in_period << ",'exo_id',"
<< symbol_table.getTypeSpecificID(id) + 1 << ",'periods'," << period1 << ":"
<< period2 << ",'type','" << typeToString(type) << "'"
<< ",'value',";
value->writeOutput(output);
output << ");" << endl;
@ -578,18 +568,15 @@ void
ShocksLearntInStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "shocks")"
<< R"(, "learnt_in": )" << learnt_in_period
<< R"(, "overwrite": )" << boolalpha << overwrite
<< R"(, "learnt_shocks": [)";
for (bool printed_something{false};
const auto &[id, shock_vec] : learnt_shocks)
<< R"(, "learnt_in": )" << learnt_in_period << R"(, "overwrite": )" << boolalpha
<< overwrite << R"(, "learnt_shocks": [)";
for (bool printed_something {false}; const auto& [id, shock_vec] : learnt_shocks)
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"var": ")" << symbol_table.getName(id) << R"(", )"
<< R"("values": [)";
for (bool printed_something2{false};
const auto &[type, period1, period2, value] : shock_vec)
for (bool printed_something2 {false}; const auto& [type, period1, period2, value] : shock_vec)
{
if (exchange(printed_something2, true))
output << ", ";
@ -605,16 +592,15 @@ ShocksLearntInStatement::writeJsonOutput(ostream &output) const
output << "]}";
}
ConditionalForecastPathsStatement::ConditionalForecastPathsStatement(AbstractShocksStatement::det_shocks_t paths_arg,
const SymbolTable &symbol_table_arg) :
paths{move(paths_arg)},
symbol_table{symbol_table_arg},
path_length{computePathLength(paths)}
ConditionalForecastPathsStatement::ConditionalForecastPathsStatement(
AbstractShocksStatement::det_shocks_t paths_arg, const SymbolTable& symbol_table_arg) :
paths {move(paths_arg)}, symbol_table {symbol_table_arg}, path_length {computePathLength(paths)}
{
}
int
ConditionalForecastPathsStatement::computePathLength(const AbstractShocksStatement::det_shocks_t &paths)
ConditionalForecastPathsStatement::computePathLength(
const AbstractShocksStatement::det_shocks_t& paths)
{
int length {0};
for (const auto& [ignore, elems] : paths)
@ -633,13 +619,13 @@ ConditionalForecastPathsStatement::writeOutput(ostream &output,
output << "constrained_vars_ = [];" << endl
<< "constrained_paths_ = NaN(" << paths.size() << ", " << path_length << ");" << endl;
for (int k{1};
const auto &[id, elems] : paths)
for (int k {1}; const auto& [id, elems] : paths)
{
if (k == 1)
output << "constrained_vars_ = " << symbol_table.getTypeSpecificID(id) + 1 << ";" << endl;
else
output << "constrained_vars_ = [constrained_vars_; " << symbol_table.getTypeSpecificID(id) + 1 << "];" << endl;
output << "constrained_vars_ = [constrained_vars_; "
<< symbol_table.getTypeSpecificID(id) + 1 << "];" << endl;
for (const auto& [period1, period2, value] : elems)
for (int j = period1; j <= period2; j++)
{
@ -656,15 +642,13 @@ ConditionalForecastPathsStatement::writeJsonOutput(ostream &output) const
{
output << R"({"statementName": "conditional_forecast_paths")"
<< R"(, "paths": [)";
for (bool printed_something{false};
const auto &[id, elems] : paths)
for (bool printed_something {false}; const auto& [id, elems] : paths)
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"var": ")" << symbol_table.getName(id) << R"(", )"
<< R"("values": [)";
for (bool printed_something2{false};
const auto &[period1, period2, value] : elems)
for (bool printed_something2 {false}; const auto& [period1, period2, value] : elems)
{
if (exchange(printed_something2, true))
output << ", ";
@ -680,8 +664,8 @@ ConditionalForecastPathsStatement::writeJsonOutput(ostream &output) const
}
MomentCalibration::MomentCalibration(constraints_t constraints_arg,
const SymbolTable &symbol_table_arg)
: constraints{move(constraints_arg)}, symbol_table{symbol_table_arg}
const SymbolTable& symbol_table_arg) :
constraints {move(constraints_arg)}, symbol_table {symbol_table_arg}
{
}
@ -693,14 +677,12 @@ MomentCalibration::writeOutput(ostream &output, [[maybe_unused]] const string &b
for (const auto& c : constraints)
{
output << "'" << symbol_table.getName(c.endo1) << "', "
<< "'" << symbol_table.getName(c.endo2) << "', "
<< c.lags << ", "
<< "'" << symbol_table.getName(c.endo2) << "', " << c.lags << ", "
<< "[ ";
c.lower_bound->writeOutput(output);
output << ", ";
c.upper_bound->writeOutput(output);
output << " ];"
<< endl;
output << " ];" << endl;
}
output << "};" << endl;
}
@ -710,8 +692,7 @@ MomentCalibration::writeJsonOutput(ostream &output) const
{
output << R"({"statementName": "moment_calibration")"
<< R"(, "moment_calibration_criteria": [)";
for (bool printed_something{false};
const auto &c : constraints)
for (bool printed_something {false}; const auto& c : constraints)
{
if (exchange(printed_something, true))
output << ", ";
@ -730,10 +711,11 @@ MomentCalibration::writeJsonOutput(ostream &output) const
<< "}";
}
IrfCalibration::IrfCalibration(constraints_t constraints_arg,
const SymbolTable &symbol_table_arg,
OptionsList options_list_arg)
: constraints{move(constraints_arg)}, symbol_table{symbol_table_arg}, options_list{move(options_list_arg)}
IrfCalibration::IrfCalibration(constraints_t constraints_arg, const SymbolTable& symbol_table_arg,
OptionsList options_list_arg) :
constraints {move(constraints_arg)},
symbol_table {symbol_table_arg},
options_list {move(options_list_arg)}
{
}
@ -747,14 +729,12 @@ IrfCalibration::writeOutput(ostream &output, [[maybe_unused]] const string &base
for (const auto& c : constraints)
{
output << "'" << symbol_table.getName(c.endo) << "', "
<< "'" << symbol_table.getName(c.exo) << "', "
<< c.periods << ", "
<< "'" << symbol_table.getName(c.exo) << "', " << c.periods << ", "
<< "[ ";
c.lower_bound->writeOutput(output);
output << ", ";
c.upper_bound->writeOutput(output);
output << " ];"
<< endl;
output << " ];" << endl;
}
output << "};" << endl;
}
@ -770,8 +750,7 @@ IrfCalibration::writeJsonOutput(ostream &output) const
}
output << R"(, "irf_restrictions": [)";
for (bool printed_something{false};
const auto &c : constraints)
for (bool printed_something {false}; const auto& c : constraints)
{
if (exchange(printed_something, true))
output << ", ";
@ -790,8 +769,8 @@ IrfCalibration::writeJsonOutput(ostream &output) const
<< "}";
}
ShockGroupsStatement::ShockGroupsStatement(group_t shock_groups_arg, string name_arg)
: shock_groups{move(shock_groups_arg)}, name{move(name_arg)}
ShockGroupsStatement::ShockGroupsStatement(group_t shock_groups_arg, string name_arg) :
shock_groups {move(shock_groups_arg)}, name {move(name_arg)}
{
}
@ -814,10 +793,9 @@ ShockGroupsStatement::writeOutput(ostream &output, [[maybe_unused]] const string
if (unique_label)
{
output << "M_.shock_groups." << name
<< ".group" << i << ".label = '" << it->name << "';" << endl
<< "M_.shock_groups." << name
<< ".group" << i << ".shocks = {";
output << "M_.shock_groups." << name << ".group" << i << ".label = '" << it->name << "';"
<< endl
<< "M_.shock_groups." << name << ".group" << i << ".shocks = {";
for (const auto& it1 : it->list)
output << " '" << it1 << "'";
output << "};" << endl;
@ -847,8 +825,7 @@ ShockGroupsStatement::writeJsonOutput(ostream &output) const
output << ", ";
output << R"({"group_name": ")" << it->name << R"(",)"
<< R"("shocks": [)";
for (bool printed_something2{false};
const auto &it1 : it->list)
for (bool printed_something2 {false}; const auto& it1 : it->list)
{
if (exchange(printed_something2, true))
output << ", ";
@ -861,8 +838,8 @@ ShockGroupsStatement::writeJsonOutput(ostream &output) const
}
Init2shocksStatement::Init2shocksStatement(vector<pair<int, int>> init2shocks_arg, string name_arg,
const SymbolTable &symbol_table_arg)
: init2shocks{move(init2shocks_arg)}, name{move(name_arg)}, symbol_table{symbol_table_arg}
const SymbolTable& symbol_table_arg) :
init2shocks {move(init2shocks_arg)}, name {move(name_arg)}, symbol_table {symbol_table_arg}
{
}
@ -887,7 +864,8 @@ Init2shocksStatement::writeOutput(ostream &output, [[maybe_unused]] const string
{
output << "M_.init2shocks." << name << " = {" << endl;
for (const auto& [id1, id2] : init2shocks)
output << "{'" << symbol_table.getName(id1) << "', '" << symbol_table.getName(id2) << "'};" << endl;
output << "{'" << symbol_table.getName(id1) << "', '" << symbol_table.getName(id2) << "'};"
<< endl;
output << "};" << endl;
}
@ -895,8 +873,7 @@ void
Init2shocksStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "init2shocks", "name": ")" << name << R"(", "groups": [)";
for (bool printed_something{false};
const auto &[id1, id2] : init2shocks)
for (bool printed_something {false}; const auto& [id1, id2] : init2shocks)
{
if (exchange(printed_something, true))
output << ",";
@ -906,17 +883,19 @@ Init2shocksStatement::writeJsonOutput(ostream &output) const
output << "]}";
}
HeteroskedasticShocksStatement::HeteroskedasticShocksStatement(bool overwrite_arg,
heteroskedastic_shocks_t values_arg,
heteroskedastic_shocks_t scales_arg,
const SymbolTable &symbol_table_arg)
: overwrite{overwrite_arg}, values{move(values_arg)}, scales{move(scales_arg)},
HeteroskedasticShocksStatement::HeteroskedasticShocksStatement(
bool overwrite_arg, heteroskedastic_shocks_t values_arg, heteroskedastic_shocks_t scales_arg,
const SymbolTable& symbol_table_arg) :
overwrite {overwrite_arg},
values {move(values_arg)},
scales {move(scales_arg)},
symbol_table {symbol_table_arg}
{
}
void
HeteroskedasticShocksStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
HeteroskedasticShocksStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
// NB: The first initialization of the fields is done in ModFile::writeMOutput()
@ -928,9 +907,9 @@ HeteroskedasticShocksStatement::writeOutput(ostream &output, [[maybe_unused]] co
for (int tsid = symbol_table.getTypeSpecificID(symb_id);
const auto& [period1, period2, value] : vec)
{
output << "M_.heteroskedastic_shocks.Qvalue_orig = [M_.heteroskedastic_shocks.Qvalue_orig; struct('exo_id', "
<< tsid+1 << ",'periods',"
<< period1 << ":" << period2 << ",'value',";
output << "M_.heteroskedastic_shocks.Qvalue_orig = [M_.heteroskedastic_shocks.Qvalue_orig; "
"struct('exo_id', "
<< tsid + 1 << ",'periods'," << period1 << ":" << period2 << ",'value',";
value->writeOutput(output);
output << ")];" << endl;
}
@ -938,9 +917,9 @@ HeteroskedasticShocksStatement::writeOutput(ostream &output, [[maybe_unused]] co
for (int tsid = symbol_table.getTypeSpecificID(symb_id);
const auto& [period1, period2, scale] : vec)
{
output << "M_.heteroskedastic_shocks.Qscale_orig = [M_.heteroskedastic_shocks.Qscale_orig; struct('exo_id', "
<< tsid+1 << ",'periods',"
<< period1 << ":" << period2 << ",'scale',";
output << "M_.heteroskedastic_shocks.Qscale_orig = [M_.heteroskedastic_shocks.Qscale_orig; "
"struct('exo_id', "
<< tsid + 1 << ",'periods'," << period1 << ":" << period2 << ",'scale',";
scale->writeOutput(output);
output << ")];" << endl;
}
@ -950,17 +929,14 @@ void
HeteroskedasticShocksStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "heteroskedastic_shocks")"
<< R"(, "overwrite": )" << boolalpha << overwrite
<< R"(, "shocks_values": [)";
for (bool printed_something{false};
const auto &[symb_id, vec] : values)
<< R"(, "overwrite": )" << boolalpha << overwrite << R"(, "shocks_values": [)";
for (bool printed_something {false}; const auto& [symb_id, vec] : values)
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"var": ")" << symbol_table.getName(symb_id) << R"(", )"
<< R"("values": [)";
for (bool printed_something2{false};
const auto &[period1, period2, value] : vec)
for (bool printed_something2 {false}; const auto& [period1, period2, value] : vec)
{
if (exchange(printed_something2, true))
output << ", ";
@ -973,15 +949,13 @@ HeteroskedasticShocksStatement::writeJsonOutput(ostream &output) const
output << "]}";
}
output << R"(], "shocks_scales": [)";
for (bool printed_something{false};
const auto &[symb_id, vec] : scales)
for (bool printed_something {false}; const auto& [symb_id, vec] : scales)
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"var": ")" << symbol_table.getName(symb_id) << R"(", )"
<< R"("scales": [)";
for (bool printed_something2{false};
const auto &[period1, period2, value] : vec)
for (bool printed_something2 {false}; const auto& [period1, period2, value] : vec)
{
if (exchange(printed_something2, true))
output << ", ";

View File

@ -20,13 +20,13 @@
#ifndef _SHOCKS_HH
#define _SHOCKS_HH
#include <map>
#include <string>
#include <vector>
#include <map>
#include "ExprNode.hh"
#include "Statement.hh"
#include "SymbolTable.hh"
#include "ExprNode.hh"
using namespace std;
@ -38,9 +38,12 @@ public:
enum class ShockType
{
level, // The value is the level of the exogenous (“values” statement in “shocks”)
multiplySteadyState, // The value is the ratio of the exogenous over its (terminal) steady state (“values” statement in “mshocks”)
multiplyInitialSteadyState // The value is the ratio of the exogenous over its initial steady state (“values” statement in “mshocks(relative_to_initval)”)
multiplySteadyState, // The value is the ratio of the exogenous over its (terminal) steady state
// (“values” statement in “mshocks”)
multiplyInitialSteadyState // The value is the ratio of the exogenous over its initial steady
// state (“values” statement in “mshocks(relative_to_initval)”)
};
protected:
//! Does this "shocks" statement replace the previous ones?
const bool overwrite;
@ -51,8 +54,7 @@ protected:
void writeJsonDetShocks(ostream& output) const;
static string typeToString(ShockType type);
AbstractShocksStatement(bool overwrite_arg, ShockType type_arg,
det_shocks_t det_shocks_arg,
AbstractShocksStatement(bool overwrite_arg, ShockType type_arg, det_shocks_t det_shocks_arg,
const SymbolTable& symbol_table_arg);
};
@ -61,21 +63,21 @@ class ShocksStatement : public AbstractShocksStatement
public:
using var_and_std_shocks_t = map<int, expr_t>;
using covar_and_corr_shocks_t = map<pair<int, int>, expr_t>;
private:
const var_and_std_shocks_t var_shocks, std_shocks;
const covar_and_corr_shocks_t covar_shocks, corr_shocks;
void writeVarOrStdShock(ostream& output, const pair<int, expr_t>& it, bool stddev) const;
void writeVarAndStdShocks(ostream& output) const;
void writeCovarOrCorrShock(ostream &output, const pair<pair<int, int>, expr_t> &it, bool corr) const;
void writeCovarOrCorrShock(ostream& output, const pair<pair<int, int>, expr_t>& it,
bool corr) const;
void writeCovarAndCorrShocks(ostream& output) const;
bool has_calibrated_measurement_errors() const;
public:
ShocksStatement(bool overwrite_arg,
det_shocks_t det_shocks_arg,
var_and_std_shocks_t var_shocks_arg,
var_and_std_shocks_t std_shocks_arg,
covar_and_corr_shocks_t covar_shocks_arg,
covar_and_corr_shocks_t corr_shocks_arg,
ShocksStatement(bool overwrite_arg, det_shocks_t det_shocks_arg,
var_and_std_shocks_t var_shocks_arg, var_and_std_shocks_t std_shocks_arg,
covar_and_corr_shocks_t covar_shocks_arg, covar_and_corr_shocks_t corr_shocks_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -86,8 +88,7 @@ class MShocksStatement : public AbstractShocksStatement
{
public:
const bool relative_to_initval;
MShocksStatement(bool overwrite_arg, bool relative_to_initval_arg,
det_shocks_t det_shocks_arg,
MShocksStatement(bool overwrite_arg, bool relative_to_initval_arg, det_shocks_t det_shocks_arg,
const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
@ -102,8 +103,10 @@ public:
//! Does this "shocks(surprise)" statement replace the previous ones?
const bool overwrite;
const AbstractShocksStatement::det_shocks_t surprise_shocks;
private:
const SymbolTable& symbol_table;
public:
ShocksSurpriseStatement(bool overwrite_arg,
AbstractShocksStatement::det_shocks_t surprise_shocks_arg,
@ -125,21 +128,28 @@ public:
enum class LearntShockType
{
level, // The value is the level of the exogenous (“values” statement in “shocks(learnt_in=…)”)
add, // The value is the additive change of the exogenous compared to previous information period (“add” statement in “shocks(learnt_in=…)”)
multiply, // The value is the multiplicative change of the exogenous compared to previous information period (“multiply” statement in “shocks(learnt_in=…)”)
multiplySteadyState, // The value is the ratio of the exogenous over its (terminal) steady state as anticipated in the same informational period (“values” statement in “mshocks(learnt_in=…)”)
multiplyInitialSteadyState // The value is the ratio of the exogenous over its initial steady state as anticipated in the same informational period (“values” statement in “mshocks(learnt_in=…, relative_to_initval)”)
add, // The value is the additive change of the exogenous compared to previous information
// period (“add” statement in “shocks(learnt_in=…)”)
multiply, // The value is the multiplicative change of the exogenous compared to previous
// information period (“multiply” statement in “shocks(learnt_in=…)”)
multiplySteadyState, // The value is the ratio of the exogenous over its (terminal) steady state
// as anticipated in the same informational period (“values” statement in
// “mshocks(learnt_in=…)”)
multiplyInitialSteadyState // The value is the ratio of the exogenous over its initial steady
// state as anticipated in the same informational period (“values”
// statement in “mshocks(learnt_in=…, relative_to_initval)”)
};
// The tuple is (type, period1, period2, value)
using learnt_shocks_t = map<int, vector<tuple<LearntShockType, int, int, expr_t>>>;
const learnt_shocks_t learnt_shocks;
private:
const SymbolTable& symbol_table;
static string typeToString(LearntShockType type);
public:
ShocksLearntInStatement(int learnt_in_period_arg, bool overwrite_arg,
learnt_shocks_t learnt_shocks_arg,
const SymbolTable &symbol_table_arg);
learnt_shocks_t learnt_shocks_arg, const SymbolTable& symbol_table_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;
@ -151,6 +161,7 @@ private:
const AbstractShocksStatement::det_shocks_t paths;
const SymbolTable& symbol_table;
const int path_length;
public:
ConditionalForecastPathsStatement(AbstractShocksStatement::det_shocks_t paths_arg,
const SymbolTable& symbol_table_arg);
@ -169,12 +180,13 @@ public:
expr_t lower_bound, upper_bound;
};
using constraints_t = vector<Constraint>;
private:
constraints_t constraints;
const SymbolTable& symbol_table;
public:
MomentCalibration(constraints_t constraints_arg,
const SymbolTable &symbol_table_arg);
MomentCalibration(constraints_t constraints_arg, const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
@ -190,13 +202,14 @@ public:
expr_t lower_bound, upper_bound;
};
using constraints_t = vector<Constraint>;
private:
constraints_t constraints;
const SymbolTable& symbol_table;
const OptionsList options_list;
public:
IrfCalibration(constraints_t constraints_arg,
const SymbolTable &symbol_table_arg,
IrfCalibration(constraints_t constraints_arg, const SymbolTable& symbol_table_arg,
OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
@ -211,9 +224,11 @@ public:
vector<string> list;
};
using group_t = vector<Group>;
private:
group_t shock_groups;
string name;
public:
ShockGroupsStatement(group_t shock_groups_arg, string name_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -226,8 +241,10 @@ private:
const vector<pair<int, int>> init2shocks;
const string name;
const SymbolTable& symbol_table;
public:
Init2shocksStatement(vector<pair<int, int>> init2shocks_arg, string name_arg, const SymbolTable &symbol_table_arg);
Init2shocksStatement(vector<pair<int, int>> init2shocks_arg, string name_arg,
const SymbolTable& symbol_table_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;
@ -238,10 +255,12 @@ class HeteroskedasticShocksStatement : public Statement
public:
// Maps exo symb_id to list of tuples (period1, period2, value/scale)
using heteroskedastic_shocks_t = map<int, vector<tuple<int, int, expr_t>>>;
private:
const bool overwrite;
const heteroskedastic_shocks_t values, scales;
const SymbolTable& symbol_table;
public:
HeteroskedasticShocksStatement(bool overwrite_arg, heteroskedastic_shocks_t values_arg,
heteroskedastic_shocks_t scales_arg,

View File

@ -168,10 +168,10 @@ void
OptionsList::writeOutput(ostream& output, const string& option_group) const
{
// Initialize option_group as an empty struct iff the field does not exist!
if (size_t idx = option_group.find_last_of(".");
idx != string::npos)
if (size_t idx = option_group.find_last_of("."); idx != string::npos)
{
output << "if ~isfield(" << option_group.substr(0, idx) << ",'" << option_group.substr(idx+1) << "')" << endl;
output << "if ~isfield(" << option_group.substr(0, idx) << ",'"
<< option_group.substr(idx + 1) << "')" << endl;
output << " " << option_group << " = struct();" << endl;
output << "end" << endl;
}
@ -185,8 +185,8 @@ void
OptionsList::writeOutputCommon(ostream& output, const string& option_group) const
{
for (const auto& [name, val] : options)
std::visit([&]<class T>(const T &v)
{
std::visit(
[&]<class T>(const T& v) {
if constexpr (is_same_v<T, SymbolListVal>)
v.writeOutput(option_group + "." + name, output);
else
@ -259,7 +259,8 @@ OptionsList::writeOutputCommon(ostream &output, const string &option_group) cons
static_assert(always_false_v<T>, "Non-exhaustive visitor!");
output << ";" << endl;
}
}, val);
},
val);
}
void
@ -270,14 +271,13 @@ OptionsList::writeJsonOutput(ostream &output) const
output << R"("options": {)";
for (bool opt_written {false};
const auto &[name, val] : options)
for (bool opt_written {false}; const auto& [name, val] : options)
{
if (exchange(opt_written, true))
output << ", ";
output << R"(")" << name << R"(": )";
std::visit([&]<class T>(const T &v)
{
std::visit(
[&]<class T>(const T& v) {
if constexpr (is_same_v<T, NumVal>)
output << v;
else if constexpr (is_same_v<T, pair<string, string>>)
@ -295,8 +295,7 @@ OptionsList::writeJsonOutput(ostream &output) const
|| is_same_v<T, vector<vector<string>>>)
{
output << '[';
for (bool printed_something{false};
const auto &it : v)
for (bool printed_something {false}; const auto& it : v)
{
if (exchange(printed_something, true))
output << ", ";
@ -307,8 +306,7 @@ OptionsList::writeJsonOutput(ostream &output) const
else // vector<vector<string>>
{
output << '[';
for (bool printed_something2{false};
const auto &it2 : it)
for (bool printed_something2 {false}; const auto& it2 : it)
{
if (exchange(printed_something2, true))
output << ", ";
@ -321,7 +319,8 @@ OptionsList::writeJsonOutput(ostream &output) const
}
else
static_assert(always_false_v<T>, "Non-exhaustive visitor!");
}, val);
},
val);
}
output << "}";

View File

@ -20,11 +20,11 @@
#ifndef _STATEMENT_HH
#define _STATEMENT_HH
#include <ostream>
#include <string>
#include <map>
#include <set>
#include <optional>
#include <ostream>
#include <set>
#include <string>
#include <variant>
#include "SymbolList.hh"
@ -60,13 +60,15 @@ struct ModFileStructure
bool extended_path_present {false};
//! The value of the "order" option of stoch_simul, estimation, osr, ramsey_policy
//! Derivation order
/*! First initialized to zero. If user sets order option somewhere in the MOD file, it will be equal to the maximum of order options. Otherwise will default to 2 */
/*! First initialized to zero. If user sets order option somewhere in the MOD file, it will be
* equal to the maximum of order options. Otherwise will default to 2 */
int order_option {0};
//! Whether a bvar_density, bvar_forecast, sbvar, ms_sbvar statement is present
bool bvar_present {false};
//! Whether an svar_identification statement is present
bool svar_identification_present {false};
//! Whether an identification statement is present or the identification option of dynare_sensitivity statement is equal to one
//! Whether an identification statement is present or the identification option of
//! dynare_sensitivity statement is equal to one
bool identification_present {false};
//! The maximum of the “order” option in identification statements
int identification_order {0};
@ -190,9 +192,11 @@ public:
//! Write Matlab output code
/*!
\param output is the output stream of the main matlab file
\param basename is the name of the modfile (without extension) which can be used to build auxiliary files
\param basename is the name of the modfile (without extension) which can be used to build
auxiliary files
*/
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const = 0;
virtual void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const
= 0;
virtual void writeJsonOutput(ostream& output) const = 0;
};
@ -200,6 +204,7 @@ class NativeStatement : public Statement
{
private:
const string native_statement;
public:
explicit NativeStatement(string native_statement_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -210,6 +215,7 @@ class VerbatimStatement : public Statement
{
private:
const string verbatim_statement;
public:
explicit VerbatimStatement(string verbatim_statement_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -321,10 +327,12 @@ private:
// pair<string, string> corresponds to a pair of numerical values
// vector<vector<string>> corresponds to a vector of vectors of numerical values
map<string, variant<NumVal, pair<string, string>, StringVal, DateVal, SymbolListVal, vector<int>,
VecStrVal, VecCellStrVal, VecValueVal, vector<vector<string>>>> options;
VecStrVal, VecCellStrVal, VecValueVal, vector<vector<string>>>>
options;
void writeOutputCommon(ostream& output, const string& option_group) const;
// Helper constant for visitors
template<class> static constexpr bool always_false_v {false};
template<class>
static constexpr bool always_false_v {false};
};
#endif // ! _STATEMENT_HH

View File

@ -17,20 +17,19 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <cassert>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <numeric>
#include <sstream>
#include <unordered_map>
#include "StaticModel.hh"
#include "DynamicModel.hh"
#include "StaticModel.hh"
StaticModel::StaticModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
StaticModel::StaticModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg) :
ModelTree {symbol_table_arg, num_constants_arg, external_functions_table_arg}
{
@ -87,9 +86,9 @@ StaticModel::StaticModel(const DynamicModel &m) :
// If equation is dynamic, replace it by an equation marked [static]
if (dynamic_equations.contains(i))
{
auto [static_only_equations,
static_only_equations_lineno,
static_only_equations_equation_tags] = m.getStaticOnlyEquationsInfo();
auto [static_only_equations, static_only_equations_lineno,
static_only_equations_equation_tags]
= m.getStaticOnlyEquationsInfo();
addEquation(static_only_equations[static_only_index]->toStatic(*this),
static_only_equations_lineno[static_only_index],
@ -97,13 +96,13 @@ StaticModel::StaticModel(const DynamicModel &m) :
static_only_index++;
}
else
addEquation(m.equations[i]->toStatic(*this),
m.equations_lineno[i],
addEquation(m.equations[i]->toStatic(*this), m.equations_lineno[i],
m.equation_tags.getTagsByEqn(i));
}
catch (DataTree::DivisionByZeroException)
{
cerr << "...division by zero error encountered when converting equation " << i << " to static" << endl;
cerr << "...division by zero error encountered when converting equation " << i
<< " to static" << endl;
exit(EXIT_FAILURE);
}
@ -198,7 +197,9 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
}
void
StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_context_t &eval_context, bool no_tmp_terms, bool block, bool use_dll)
StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder,
const eval_context_t& eval_context, bool no_tmp_terms, bool block,
bool use_dll)
{
initializeVariablesAndEquations();
@ -211,7 +212,8 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co
with DynamicModel::computingPass(). */
if (log2(symbol_table.endo_nbr()) * 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);
}
@ -230,7 +232,8 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co
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);
}
@ -242,7 +245,9 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co
computingPassBlock(eval_context, no_tmp_terms);
if (!block_decomposed && block)
{
cerr << "ERROR: Block decomposition requested but failed. If your model does not have a steady state, you may want to try the 'no_static' option of the 'model' block." << endl;
cerr << "ERROR: Block decomposition requested but failed. If your model does not have a "
"steady state, you may want to try the 'no_static' option of the 'model' block."
<< endl;
exit(EXIT_FAILURE);
}
}
@ -255,23 +260,22 @@ StaticModel::writeStaticMFile(const string &basename) const
ostringstream init_output, end_output;
init_output << "residual = zeros(" << equations.size() << ", 1);";
writeStaticMFileHelper(basename, "static_resid", "residual", "static_resid_tt",
temporary_terms_derivatives[0].size(),
"", init_output, end_output,
temporary_terms_derivatives[0].size(), "", init_output, end_output,
d_output[0], tt_output[0]);
init_output.str("");
end_output.str("");
init_output << "g1 = zeros(" << equations.size() << ", " << symbol_table.endo_nbr() << ");";
writeStaticMFileHelper(basename, "static_g1", "g1", "static_g1_tt",
temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size(),
"static_resid_tt",
init_output, end_output,
d_output[1], tt_output[1]);
temporary_terms_derivatives[0].size()
+ temporary_terms_derivatives[1].size(),
"static_resid_tt", init_output, end_output, d_output[1], tt_output[1]);
writeStaticMWrapperFunction(basename, "g1");
// For order ≥ 2
int ncols {symbol_table.endo_nbr()};
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++)
{
ncols *= symbol_table.endo_nbr();
@ -286,18 +290,14 @@ StaticModel::writeStaticMFile(const string &basename) const
init_output << gname << "_i = zeros(" << NNZDerivatives[i] << ",1);" << endl
<< gname << "_j = zeros(" << NNZDerivatives[i] << ",1);" << endl
<< gname << "_v = zeros(" << NNZDerivatives[i] << ",1);" << endl;
end_output << gname << " = sparse("
<< gname << "_i," << gname << "_j," << gname << "_v,"
end_output << gname << " = sparse(" << gname << "_i," << gname << "_j," << gname << "_v,"
<< equations.size() << "," << ncols << ");";
}
else
init_output << gname << " = sparse([],[],[]," << equations.size() << "," << ncols << ");";
writeStaticMFileHelper(basename, "static_" + gname, gname,
"static_" + gname + "_tt",
ntt,
"static_" + gprevname + "_tt",
init_output, end_output,
d_output[i], tt_output[i]);
writeStaticMFileHelper(basename, "static_" + gname, gname, "static_" + gname + "_tt", ntt,
"static_" + gprevname + "_tt", init_output, end_output, d_output[i],
tt_output[i]);
if (i <= 3)
writeStaticMWrapperFunction(basename, gname);
}
@ -346,10 +346,12 @@ StaticModel::writeStaticMWrapperFunction(const string &basename, const string &e
output << " residual = " << basename << ".static_resid(T, y, x, params, false);" << endl
<< " g1 = " << basename << ".static_g1(T, y, x, params, false);" << endl;
else if (ending == "g2")
output << " [residual, g1] = " << basename << ".static_resid_g1(T, y, x, params, false);" << endl
output << " [residual, g1] = " << basename << ".static_resid_g1(T, y, x, params, false);"
<< endl
<< " g2 = " << basename << ".static_g2(T, y, x, params, false);" << endl;
else if (ending == "g3")
output << " [residual, g1, g2] = " << basename << ".static_resid_g1_g2(T, y, x, params, false);" << endl
output << " [residual, g1, g2] = " << basename
<< ".static_resid_g1_g2(T, y, x, params, false);" << endl
<< " g3 = " << basename << ".static_g3(T, y, x, params, false);" << endl;
output << endl << "end" << endl;
@ -357,12 +359,11 @@ StaticModel::writeStaticMWrapperFunction(const string &basename, const string &e
}
void
StaticModel::writeStaticMFileHelper(const string &basename,
const string &name, const string &retvalname,
const string &name_tt, size_t ttlen,
const string &previous_tt_name,
const ostringstream &init_s, const ostringstream &end_s,
const ostringstream &s, const ostringstream &s_tt) const
StaticModel::writeStaticMFileHelper(const string& basename, const string& name,
const string& retvalname, const string& name_tt, size_t ttlen,
const string& previous_tt_name, const ostringstream& init_s,
const ostringstream& end_s, const ostringstream& s,
const ostringstream& s_tt) const
{
filesystem::path filename {packageDir(basename) / (name_tt + ".m")};
ofstream output {filename, ios::out | ios::binary};
@ -378,22 +379,30 @@ StaticModel::writeStaticMFileHelper(const string &basename,
<< "% File created by Dynare Preprocessor from .mod file" << endl
<< "%" << endl
<< "% Inputs:" << endl
<< "% T [#temp variables by 1] double vector of temporary terms to be filled by function" << endl
<< "% y [M_.endo_nbr by 1] double vector of endogenous variables in declaration order" << endl
<< "% x [M_.exo_nbr by 1] double vector of exogenous variables in declaration order" << endl
<< "% params [M_.param_nbr by 1] double vector of parameter values in declaration order" << endl
<< "% T [#temp variables by 1] double vector of temporary terms to be filled "
"by function"
<< endl
<< "% y [M_.endo_nbr by 1] double vector of endogenous variables in "
"declaration order"
<< endl
<< "% x [M_.exo_nbr by 1] double vector of exogenous variables in "
"declaration order"
<< endl
<< "% params [M_.param_nbr by 1] double vector of parameter values in "
"declaration order"
<< endl
<< "%" << endl
<< "% Output:" << endl
<< "% T [#temp variables by 1] double vector of temporary terms" << endl
<< "%" << endl << endl
<< "%" << endl
<< endl
<< "assert(length(T) >= " << ttlen << ");" << endl
<< endl;
if (!previous_tt_name.empty())
output << "T = " << basename << "." << previous_tt_name << "(T, y, x, params);" << endl << endl;
output << s_tt.str() << endl
<< "end" << endl;
output << s_tt.str() << endl << "end" << endl;
output.close();
filename = packageDir(basename) / (name + ".m");
@ -410,26 +419,34 @@ StaticModel::writeStaticMFileHelper(const string &basename,
<< "% File created by Dynare Preprocessor from .mod file" << endl
<< "%" << endl
<< "% Inputs:" << endl
<< "% T [#temp variables by 1] double vector of temporary terms to be filled by function" << endl
<< "% y [M_.endo_nbr by 1] double vector of endogenous variables in declaration order" << endl
<< "% x [M_.exo_nbr by 1] double vector of exogenous variables in declaration order" << endl
<< "% params [M_.param_nbr by 1] double vector of parameter values in declaration order" << endl
<< "% T [#temp variables by 1] double vector of temporary terms to be filled "
"by function"
<< endl
<< "% y [M_.endo_nbr by 1] double vector of endogenous variables in "
"declaration order"
<< endl
<< "% x [M_.exo_nbr by 1] double vector of exogenous variables in "
"declaration order"
<< endl
<< "% params [M_.param_nbr by 1] double vector of parameter values in "
"declaration order"
<< 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
<< "% Output:" << endl
<< "% " << retvalname << endl
<< "%" << endl << endl;
<< "%" << endl
<< endl;
if (!name_tt.empty())
output << "if T_flag" << endl
<< " T = " << basename << "." << name_tt << "(T, y, x, params);" << endl
<< "end" << endl;
output << init_s.str() << endl
<< s.str()
<< end_s.str() << endl
<< "end" << endl;
output << init_s.str() << endl << s.str() << end_s.str() << endl << "end" << endl;
output.close();
}
@ -443,18 +460,23 @@ StaticModel::writeStaticMCompatFile(const string &basename) const
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
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] = static(y, x, params)" << endl
<< " T = NaN(" << ntt << ", 1);" << endl
<< " if nargout <= 1" << endl
<< " residual = " << basename << ".static_resid(T, y, x, params, true);" << endl
<< " elseif nargout == 2" << endl
<< " [residual, g1] = " << basename << ".static_resid_g1(T, y, x, params, true);" << endl
<< " [residual, g1] = " << basename << ".static_resid_g1(T, y, x, params, true);"
<< endl
<< " elseif nargout == 3" << endl
<< " [residual, g1, g2] = " << basename << ".static_resid_g1_g2(T, y, x, params, true);" << endl
<< " [residual, g1, g2] = " << basename
<< ".static_resid_g1_g2(T, y, x, params, true);" << endl
<< " else" << endl
<< " [residual, g1, g2, g3] = " << basename << ".static_resid_g1_g2_g3(T, y, x, params, true);" << endl
<< " [residual, g1, g2, g3] = " << basename
<< ".static_resid_g1_g2_g3(T, y, x, params, true);" << endl
<< " end" << endl
<< "end" << endl;
@ -462,7 +484,8 @@ StaticModel::writeStaticMCompatFile(const string &basename) const
}
void
StaticModel::writeStaticFile(const string &basename, bool use_dll, const string &mexext, const filesystem::path &matlabroot, bool julia) const
StaticModel::writeStaticFile(const string& basename, bool use_dll, const string& mexext,
const filesystem::path& matlabroot, bool julia) const
{
filesystem::path model_dir {basename};
model_dir /= "model";
@ -549,14 +572,17 @@ StaticModel::writeBlockDriverOutput(ostream &output) const
{
for (int blk = 0; blk < static_cast<int>(blocks.size()); blk++)
{
output << "M_.block_structure_stat.block(" << blk+1 << ").Simulation_Type = " << static_cast<int>(blocks[blk].simulation_type) << ";" << endl
<< "M_.block_structure_stat.block(" << blk+1 << ").endo_nbr = " << blocks[blk].size << ";" << endl
<< "M_.block_structure_stat.block(" << blk+1 << ").mfs = " << blocks[blk].mfs_size << ";" << endl
output << "M_.block_structure_stat.block(" << blk + 1
<< ").Simulation_Type = " << static_cast<int>(blocks[blk].simulation_type) << ";"
<< endl
<< "M_.block_structure_stat.block(" << blk + 1 << ").endo_nbr = " << blocks[blk].size
<< ";" << endl
<< "M_.block_structure_stat.block(" << blk + 1 << ").mfs = " << blocks[blk].mfs_size
<< ";" << endl
<< "M_.block_structure_stat.block(" << blk + 1 << ").equation = [";
for (int eq = 0; eq < blocks[blk].size; eq++)
output << " " << getBlockEquationID(blk, eq) + 1;
output << "];" << endl
<< "M_.block_structure_stat.block(" << blk+1 << ").variable = [";
output << "];" << endl << "M_.block_structure_stat.block(" << blk + 1 << ").variable = [";
for (int var = 0; var < blocks[blk].size; var++)
output << " " << getBlockVariableID(blk, var) + 1;
output << "];" << endl;
@ -564,16 +590,14 @@ StaticModel::writeBlockDriverOutput(ostream &output) const
output << "M_.block_structure_stat.variable_reordered = [";
for (int i = 0; i < symbol_table.endo_nbr(); i++)
output << " " << endo_idx_block2orig[i] + 1;
output << "];" << endl
<< "M_.block_structure_stat.equation_reordered = [";
output << "];" << endl << "M_.block_structure_stat.equation_reordered = [";
for (int i = 0; i < symbol_table.endo_nbr(); i++)
output << " " << eq_idx_block2orig[i] + 1;
output << "];" << endl;
set<pair<int, int>> row_incidence;
for (const auto& [indices, d1] : derivatives[1])
if (int deriv_id = indices[1];
getTypeByDerivID(deriv_id) == SymbolType::endogenous)
if (int deriv_id = indices[1]; getTypeByDerivID(deriv_id) == SymbolType::endogenous)
{
int eq = indices[0];
int var {getTypeSpecificIDByDerivID(deriv_id)};
@ -583,8 +607,8 @@ StaticModel::writeBlockDriverOutput(ostream &output) const
for (auto [eq, var] : row_incidence)
output << " " << eq + 1 << " " << var + 1 << ";" << endl;
output << "];" << endl
<< "M_.block_structure_stat.tmp_nbr = " << blocks_temporary_terms_idxs.size()
<< ";" << endl;
<< "M_.block_structure_stat.tmp_nbr = " << blocks_temporary_terms_idxs.size() << ";"
<< endl;
writeBlockDriverSparseIndicesHelper<false>(output);
}
@ -665,7 +689,8 @@ StaticModel::computeChainRuleJacobian()
map<int, BinaryOpNode*> recursive_vars;
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)
recursive_vars[deriv_id] = getBlockEquationRenormalizedExpr(blk, i);
else
@ -684,7 +709,9 @@ StaticModel::computeChainRuleJacobian()
for (int var = nb_recursives; var < size; var++)
{
int var_orig = getBlockVariableID(blk, var);
expr_t d1 = equations[eq_orig]->getChainRuleDerivative(getDerivID(symbol_table.getID(SymbolType::endogenous, var_orig), 0), recursive_vars, non_null_chain_rule_derivatives, chain_rule_deriv_cache);
expr_t d1 = equations[eq_orig]->getChainRuleDerivative(
getDerivID(symbol_table.getID(SymbolType::endogenous, var_orig), 0),
recursive_vars, non_null_chain_rule_derivatives, chain_rule_deriv_cache);
if (d1 != Zero)
blocks_derivatives[blk][{eq, var, 0}] = d1;
}
@ -698,9 +725,11 @@ StaticModel::computeChainRuleJacobian()
{
auto& [eq, var, lag] {indices};
assert(eq >= nb_recursives && var >= nb_recursives && lag == 0);
blocks_jacobian_sparse_column_major_order[blk].try_emplace({eq-nb_recursives, var-nb_recursives}, d1);
blocks_jacobian_sparse_column_major_order[blk].try_emplace(
{eq - nb_recursives, var - nb_recursives}, d1);
}
blocks_jacobian_sparse_colptr[blk] = computeCSCColPtr(blocks_jacobian_sparse_column_major_order[blk], blocks[blk].mfs_size);
blocks_jacobian_sparse_colptr[blk] = computeCSCColPtr(
blocks_jacobian_sparse_column_major_order[blk], blocks[blk].mfs_size);
}
}
}
@ -708,7 +737,8 @@ StaticModel::computeChainRuleJacobian()
void
StaticModel::writeLatexFile(const string& basename, bool write_equation_tags) const
{
writeLatexModelFile(basename, "static", ExprNodeOutputType::latexStaticModel, write_equation_tags);
writeLatexModelFile(basename, "static", ExprNodeOutputType::latexStaticModel,
write_equation_tags);
}
void
@ -734,7 +764,8 @@ StaticModel::writeLatexAuxVarRecursiveDefinitions(ostream &output) const
for (auto aux_equation : aux_equations)
{
output << R"(\begin{dmath})" << endl;
dynamic_cast<ExprNode *>(aux_equation)->writeOutput(output, ExprNodeOutputType::latexStaticModel);
dynamic_cast<ExprNode*>(aux_equation)
->writeOutput(output, ExprNodeOutputType::latexStaticModel);
output << endl << R"(\end{dmath})" << endl;
}
}
@ -750,8 +781,7 @@ StaticModel::writeJsonAuxVarRecursiveDefinitions(ostream &output) const
{
vector<string> efout;
aux_equation->writeJsonExternalFunctionOutput(efout, temporary_terms, tef_terms, false);
for (bool printed_something{false};
const auto &it : efout)
for (bool printed_something {false}; const auto& it : efout)
{
if (exchange(printed_something, true))
output << ", ";
@ -773,8 +803,7 @@ void
StaticModel::writeJsonOutput(ostream& output) const
{
output << R"("static_tmp_nbr": [)";
for (bool printed_something {false};
const auto &tts : temporary_terms_derivatives)
for (bool printed_something {false}; const auto& tts : temporary_terms_derivatives)
{
if (exchange(printed_something, true))
output << ", ";
@ -805,22 +834,17 @@ StaticModel::writeJsonParamsDerivatives(ostream &output, bool writeDetails) cons
if (!params_derivatives.size())
return;
auto [mlv_output, tt_output, rp_output, gp_output, rpp_output, gpp_output, hp_output, g3p_output]
{ writeJsonParamsDerivativesHelper<false>(writeDetails) };
auto [mlv_output, tt_output, rp_output, gp_output, rpp_output, gpp_output, hp_output,
g3p_output] {writeJsonParamsDerivativesHelper<false>(writeDetails)};
// g3p_output is ignored
if (writeDetails)
output << R"("static_model_params_derivative": {)";
else
output << R"("static_model_params_derivatives_simple": {)";
output << mlv_output.str()
<< ", " << tt_output.str()
<< ", " << rp_output.str()
<< ", " << gp_output.str()
<< ", " << rpp_output.str()
<< ", " << gpp_output.str()
<< ", " << hp_output.str()
<< "}";
output << mlv_output.str() << ", " << tt_output.str() << ", " << rp_output.str() << ", "
<< gp_output.str() << ", " << rpp_output.str() << ", " << gpp_output.str() << ", "
<< hp_output.str() << "}";
}
void
@ -866,17 +890,16 @@ StaticModel::computeRamseyMultipliersDerivatives(int ramsey_orig_endo_nbr, bool
not optional) */
if (no_tmp_terms)
for (auto& it : temp_terms_map)
erase_if(it.second,
[](expr_t e) { return !dynamic_cast<AbstractExternalFunctionNode *>(e); });
erase_if(it.second, [](expr_t e) { return !dynamic_cast<AbstractExternalFunctionNode*>(e); });
copy(temp_terms_map[{1, 0}].begin(), temp_terms_map[{1, 0}].end(),
inserter(ramsey_multipliers_derivatives_temporary_terms, ramsey_multipliers_derivatives_temporary_terms.begin()));
for (int idx {0};
auto it : ramsey_multipliers_derivatives_temporary_terms)
inserter(ramsey_multipliers_derivatives_temporary_terms,
ramsey_multipliers_derivatives_temporary_terms.begin()));
for (int idx {0}; auto it : ramsey_multipliers_derivatives_temporary_terms)
ramsey_multipliers_derivatives_temporary_terms_idxs[it] = idx++;
// Compute the CSC format
ramsey_multipliers_derivatives_sparse_colptr = computeCSCColPtr(ramsey_multipliers_derivatives,
mult_deriv_ids.size());
ramsey_multipliers_derivatives_sparse_colptr
= computeCSCColPtr(ramsey_multipliers_derivatives, mult_deriv_ids.size());
}
void
@ -885,19 +908,18 @@ StaticModel::writeDriverRamseyMultipliersDerivativesSparseIndices(ostream &outpu
output << "M_.ramsey_multipliers_static_g1_sparse_rowval = int32([";
for (auto& [row_col, d] : ramsey_multipliers_derivatives)
output << row_col.first + 1 << ' ';
output << "]);" << endl
<< "M_.ramsey_multipliers_static_g1_sparse_colval = int32([";
output << "]);" << endl << "M_.ramsey_multipliers_static_g1_sparse_colval = int32([";
for (auto& [row_col, d] : ramsey_multipliers_derivatives)
output << row_col.second + 1 << ' ';
output << "]);" << endl
<< "M_.ramsey_multipliers_static_g1_sparse_colptr = int32([";
output << "]);" << endl << "M_.ramsey_multipliers_static_g1_sparse_colptr = int32([";
for (int it : ramsey_multipliers_derivatives_sparse_colptr)
output << it + 1 << ' ';
output << "]);" << endl;
}
void
StaticModel::writeRamseyMultipliersDerivativesMFile(const string &basename, int ramsey_orig_endo_nbr) const
StaticModel::writeRamseyMultipliersDerivativesMFile(const string& basename,
int ramsey_orig_endo_nbr) const
{
constexpr auto output_type {ExprNodeOutputType::matlabStaticModel};
filesystem::path filename {packageDir(basename) / "ramsey_multipliers_static_g1.m"};
@ -908,7 +930,9 @@ StaticModel::writeRamseyMultipliersDerivativesMFile(const string &basename, int
exit(EXIT_FAILURE);
}
output_file << "function g1m = ramsey_multipliers_static_g1(y, x, params, sparse_rowval, sparse_colval, sparse_colptr)" << endl
output_file << "function g1m = ramsey_multipliers_static_g1(y, x, params, sparse_rowval, "
"sparse_colval, sparse_colptr)"
<< endl
<< "g1m_v=NaN(" << ramsey_multipliers_derivatives.size() << ",1);" << endl;
writeRamseyMultipliersDerivativesHelper<output_type>(output_file);
@ -918,13 +942,16 @@ StaticModel::writeRamseyMultipliersDerivativesMFile(const string &basename, int
<< " sparse_rowval = double(sparse_rowval);" << endl
<< " sparse_colval = double(sparse_colval);" << endl
<< "end" << endl
<< "g1m = sparse(sparse_rowval, sparse_colval, g1m_v, " << ramsey_orig_endo_nbr << ", " << symbol_table.getLagrangeMultipliers().size() << ");" << endl
<< "g1m = sparse(sparse_rowval, sparse_colval, g1m_v, " << ramsey_orig_endo_nbr
<< ", " << symbol_table.getLagrangeMultipliers().size() << ");" << endl
<< "end" << endl;
output_file.close();
}
void
StaticModel::writeRamseyMultipliersDerivativesCFile(const string &basename, const string &mexext, const filesystem::path &matlabroot, int ramsey_orig_endo_nbr) const
StaticModel::writeRamseyMultipliersDerivativesCFile(const string& basename, const string& mexext,
const filesystem::path& matlabroot,
int ramsey_orig_endo_nbr) const
{
constexpr auto output_type {ExprNodeOutputType::CStaticModel};
const filesystem::path model_src_dir {filesystem::path {basename} / "model" / "src"};
@ -941,13 +968,16 @@ StaticModel::writeRamseyMultipliersDerivativesCFile(const string &basename, cons
exit(EXIT_FAILURE);
}
output << "#include <math.h>" << endl << endl
output << "#include <math.h>" << endl
<< endl
<< R"(#include "mex.h")" << endl // Needed for calls to external functions
<< endl;
writeCHelpersDefinition(output);
writeCHelpersDeclaration(output); // Provide external definition of helpers
output << endl
<< "void ramsey_multipliers_static_g1(const double *restrict y, const double *restrict x, const double *restrict params, double *restrict T, double *restrict g1m_v)" << endl
<< "void ramsey_multipliers_static_g1(const double *restrict y, const double *restrict x, "
"const double *restrict params, double *restrict T, double *restrict g1m_v)"
<< endl
<< "{" << endl;
writeRamseyMultipliersDerivativesHelper<output_type>(output);
output << "}" << endl
@ -958,19 +988,32 @@ StaticModel::writeRamseyMultipliersDerivativesCFile(const string &basename, cons
<< R"( mexErrMsgTxt("Accepts exactly 6 input arguments");)" << endl
<< " if (nlhs != 1)" << endl
<< R"( mexErrMsgTxt("Accepts exactly 1 output argument");)" << endl
<< " if (!(mxIsDouble(prhs[0]) && !mxIsComplex(prhs[0]) && !mxIsSparse(prhs[0]) && mxGetNumberOfElements(prhs[0]) == " << symbol_table.endo_nbr() << "))" << endl
<< R"( mexErrMsgTxt("y must be a real dense numeric array with )" << symbol_table.endo_nbr() << R"( elements");)" << endl
<< " if (!(mxIsDouble(prhs[0]) && !mxIsComplex(prhs[0]) && !mxIsSparse(prhs[0]) && "
"mxGetNumberOfElements(prhs[0]) == "
<< symbol_table.endo_nbr() << "))" << endl
<< R"( mexErrMsgTxt("y must be a real dense numeric array with )"
<< symbol_table.endo_nbr() << R"( elements");)" << endl
<< " const double *restrict y = mxGetPr(prhs[0]);" << endl
<< " if (!(mxIsDouble(prhs[1]) && !mxIsComplex(prhs[1]) && !mxIsSparse(prhs[1]) && mxGetNumberOfElements(prhs[1]) == " << xlen << "))" << endl
<< R"( mexErrMsgTxt("x must be a real dense numeric array with )" << xlen << R"( elements");)" << endl
<< " if (!(mxIsDouble(prhs[1]) && !mxIsComplex(prhs[1]) && !mxIsSparse(prhs[1]) && "
"mxGetNumberOfElements(prhs[1]) == "
<< xlen << "))" << endl
<< R"( mexErrMsgTxt("x must be a real dense numeric array with )" << xlen
<< R"( elements");)" << endl
<< " const double *restrict x = mxGetPr(prhs[1]);" << endl
<< " if (!(mxIsDouble(prhs[2]) && !mxIsComplex(prhs[2]) && !mxIsSparse(prhs[2]) && mxGetNumberOfElements(prhs[2]) == " << symbol_table.param_nbr() << "))" << endl
<< R"( mexErrMsgTxt("params must be a real dense numeric array with )" << symbol_table.param_nbr() << R"( elements");)" << endl
<< " if (!(mxIsDouble(prhs[2]) && !mxIsComplex(prhs[2]) && !mxIsSparse(prhs[2]) && "
"mxGetNumberOfElements(prhs[2]) == "
<< symbol_table.param_nbr() << "))" << endl
<< R"( mexErrMsgTxt("params must be a real dense numeric array with )"
<< symbol_table.param_nbr() << R"( elements");)" << endl
<< " const double *restrict params = mxGetPr(prhs[2]);" << endl
<< " if (!(mxIsInt32(prhs[3]) && mxGetNumberOfElements(prhs[3]) == " << nzval << "))" << endl
<< R"( mexErrMsgTxt("sparse_rowval must be an int32 array with )" << nzval << R"( elements");)" << endl
<< " if (!(mxIsInt32(prhs[5]) && mxGetNumberOfElements(prhs[5]) == " << ncols+1 << "))" << endl
<< R"( mexErrMsgTxt("sparse_colptr must be an int32 array with )" << ncols+1 << R"( elements");)" << endl
<< " if (!(mxIsInt32(prhs[3]) && mxGetNumberOfElements(prhs[3]) == " << nzval << "))"
<< endl
<< R"( mexErrMsgTxt("sparse_rowval must be an int32 array with )" << nzval
<< R"( elements");)" << endl
<< " if (!(mxIsInt32(prhs[5]) && mxGetNumberOfElements(prhs[5]) == " << ncols + 1 << "))"
<< endl
<< R"( mexErrMsgTxt("sparse_colptr must be an int32 array with )" << ncols + 1
<< R"( elements");)" << endl
<< "#if MX_HAS_INTERLEAVED_COMPLEX" << endl
<< " const int32_T *restrict sparse_rowval = mxGetInt32s(prhs[3]);" << endl
<< " const int32_T *restrict sparse_colptr = mxGetInt32s(prhs[5]);" << endl
@ -978,13 +1021,15 @@ StaticModel::writeRamseyMultipliersDerivativesCFile(const string &basename, cons
<< " const int32_T *restrict sparse_rowval = (int32_T *) mxGetData(prhs[3]);" << endl
<< " const int32_T *restrict sparse_colptr = (int32_T *) mxGetData(prhs[5]);" << endl
<< "#endif" << endl
<< " plhs[0] = mxCreateSparse(" << ramsey_orig_endo_nbr << ", " << ncols << ", " << nzval << ", mxREAL);" << endl
<< " plhs[0] = mxCreateSparse(" << ramsey_orig_endo_nbr << ", " << ncols << ", " << nzval
<< ", mxREAL);" << endl
<< " mwIndex *restrict ir = mxGetIr(plhs[0]), *restrict jc = mxGetJc(plhs[0]);" << endl
<< " for (mwSize i = 0; i < " << nzval << "; i++)" << endl
<< " *ir++ = *sparse_rowval++ - 1;" << endl
<< " for (mwSize i = 0; i < " << ncols + 1 << "; i++)" << endl
<< " *jc++ = *sparse_colptr++ - 1;" << endl
<< " mxArray *T_mx = mxCreateDoubleMatrix(" << ramsey_multipliers_derivatives_temporary_terms.size() << ", 1, mxREAL);" << endl
<< " mxArray *T_mx = mxCreateDoubleMatrix("
<< ramsey_multipliers_derivatives_temporary_terms.size() << ", 1, mxREAL);" << endl
<< " ramsey_multipliers_static_g1(y, x, params, mxGetPr(T_mx), mxGetPr(plhs[0]));" << endl
<< " mxDestroyArray(T_mx);" << endl
<< "}" << endl;

View File

@ -20,11 +20,11 @@
#ifndef _STATIC_MODEL_HH
#define _STATIC_MODEL_HH
#include <fstream>
#include <filesystem>
#include <fstream>
#include "ModelTree.hh"
#include "Bytecode.hh"
#include "ModelTree.hh"
using namespace std;
@ -72,7 +72,8 @@ private:
//! Computes jacobian and prepares for equation normalization
/*! Using values from initval/endval blocks and parameter initializations:
- computes the jacobian for the model w.r. to contemporaneous variables
- removes edges of the incidence matrix when derivative w.r. to the corresponding variable is too close to zero (below the cutoff)
- removes edges of the incidence matrix when derivative w.r. to the corresponding variable is
too close to zero (below the cutoff)
*/
void evaluateJacobian(const eval_context_t& eval_context, jacob_map_t* j_m, bool dynamic);
@ -96,10 +97,8 @@ private:
/* Helper for writing MATLAB/Octave functions for residuals/derivatives and
their temporary terms (legacy representation) */
void writeStaticMFileHelper(const string &basename,
const string &name, const string &retvalname,
const string &name_tt, size_t ttlen,
const string &previous_tt_name,
void writeStaticMFileHelper(const string& basename, const string& name, const string& retvalname,
const string& name_tt, size_t ttlen, const string& previous_tt_name,
const ostringstream& init_s, const ostringstream& end_s,
const ostringstream& s, const ostringstream& s_tt) const;
/* Writes MATLAB/Octave wrapper function for computing residuals and
@ -111,7 +110,8 @@ private:
void writeStaticMCompatFile(const string& name) const;
int
getBlockJacobianEndoCol([[maybe_unused]] int blk, int var, [[maybe_unused]] int lag) const override
getBlockJacobianEndoCol([[maybe_unused]] int blk, int var,
[[maybe_unused]] int lag) const override
{
assert(var >= blocks[blk].getRecursiveSize());
return var - blocks[blk].getRecursiveSize();
@ -137,8 +137,7 @@ protected:
}
public:
StaticModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants,
StaticModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants,
ExternalFunctionsTable& external_functions_table_arg);
StaticModel(const StaticModel& m);
@ -155,12 +154,15 @@ public:
\param eval_context evaluation context for normalization
\param no_tmp_terms if true, no temporary terms will be computed in the static files
\param derivsOrder order of derivation with respect to endogenous
\param paramsDerivsOrder order of derivatives w.r. to a pair (endogenous, parameter) to be computed
\param paramsDerivsOrder order of derivatives w.r. to a pair (endogenous, parameter) to be
computed
*/
void computingPass(int derivsOrder, int paramsDerivsOrder, const eval_context_t &eval_context, bool no_tmp_terms, bool block, bool use_dll);
void computingPass(int derivsOrder, int paramsDerivsOrder, const eval_context_t& eval_context,
bool no_tmp_terms, bool block, bool use_dll);
//! Writes static model file (+ bytecode)
void writeStaticFile(const string &basename, bool use_dll, const string &mexext, const filesystem::path &matlabroot, bool julia) const;
void writeStaticFile(const string& basename, bool use_dll, const string& mexext,
const filesystem::path& matlabroot, bool julia) const;
//! Write JSON Output (used by PlannerObjectiveStatement)
void writeJsonOutput(ostream& output) const;
@ -192,16 +194,20 @@ public:
void addAllParamDerivId(set<int>& deriv_id_set) override;
// Fills the ramsey_multipliers_derivatives structure (see the comment there)
void computeRamseyMultipliersDerivatives(int ramsey_orig_endo_nbr, bool is_matlab, bool no_tmp_terms);
void computeRamseyMultipliersDerivatives(int ramsey_orig_endo_nbr, bool is_matlab,
bool no_tmp_terms);
// Writes the sparse indices of ramsey_multipliers_derivatives to the driver file
void writeDriverRamseyMultipliersDerivativesSparseIndices(ostream& output) const;
// Writes ramsey_multipliers_derivatives (MATLAB/Octave version)
void writeRamseyMultipliersDerivativesMFile(const string &basename, int ramsey_orig_endo_nbr) const;
void writeRamseyMultipliersDerivativesMFile(const string& basename,
int ramsey_orig_endo_nbr) const;
// Writes ramsey_multipliers_derivatives (C version)
void writeRamseyMultipliersDerivativesCFile(const string &basename, const string &mexext, const filesystem::path &matlabroot, int ramsey_orig_endo_nbr) const;
void writeRamseyMultipliersDerivativesCFile(const string& basename, const string& mexext,
const filesystem::path& matlabroot,
int ramsey_orig_endo_nbr) const;
int
getMFS() const override
@ -217,10 +223,11 @@ StaticModel::writeParamsDerivativesFile(const string &basename) const
if (!params_derivatives.size())
return;
constexpr ExprNodeOutputType output_type { julia ? ExprNodeOutputType::juliaStaticModel : ExprNodeOutputType::matlabStaticModel };
constexpr ExprNodeOutputType output_type {julia ? ExprNodeOutputType::juliaStaticModel
: ExprNodeOutputType::matlabStaticModel};
auto [tt_output, rp_output, gp_output, rpp_output, gpp_output, hp_output, g3p_output]
{ writeParamsDerivativesFileHelper<output_type>() };
auto [tt_output, rp_output, gp_output, rpp_output, gpp_output, hp_output,
g3p_output] {writeParamsDerivativesFileHelper<output_type>()};
// g3p_output is ignored
if constexpr (!julia)
@ -232,56 +239,96 @@ StaticModel::writeParamsDerivativesFile(const string &basename) const
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
exit(EXIT_FAILURE);
}
paramsDerivsFile << "function [rp, gp, rpp, gpp, hp] = static_params_derivs(y, x, params)" << endl
paramsDerivsFile
<< "function [rp, gp, rpp, gpp, hp] = static_params_derivs(y, x, params)" << endl
<< "%" << endl
<< "% Status : Computes derivatives of the static model with respect to the parameters" << endl
<< "% Status : Computes derivatives of the static model with respect to the parameters"
<< endl
<< "%" << endl
<< "% Inputs : " << endl
<< "% y [M_.endo_nbr by 1] double vector of endogenous variables in declaration order" << endl
<< "% x [M_.exo_nbr by 1] double vector of exogenous variables in declaration order" << endl
<< "% params [M_.param_nbr by 1] double vector of parameter values in declaration order" << endl
<< "% y [M_.endo_nbr by 1] double vector of endogenous variables in "
"declaration order"
<< endl
<< "% x [M_.exo_nbr by 1] double vector of exogenous variables in "
"declaration order"
<< endl
<< "% params [M_.param_nbr by 1] double vector of parameter values in declaration "
"order"
<< endl
<< "%" << endl
<< "% Outputs:" << endl
<< "% rp [M_.eq_nbr by #params] double Jacobian matrix of static model equations with respect to parameters " << endl
<< "% Dynare may prepend or append auxiliary equations, see M_.aux_vars" << endl
<< "% gp [M_.endo_nbr by M_.endo_nbr by #params] double Derivative of the Jacobian matrix of the static model equations with respect to the parameters" << endl
<< "% rows: variables in declaration order" << endl
<< "% rows: equations in order of declaration" << endl
<< "% rpp [#second_order_residual_terms by 4] double Hessian matrix of second derivatives of residuals with respect to parameters;" << endl
<< "% rows: respective derivative term" << endl
<< "% 1st column: equation number of the term appearing" << endl
<< "% 2nd column: number of the first parameter in derivative" << endl
<< "% 3rd column: number of the second parameter in derivative" << endl
<< "% 4th column: value of the Hessian term" << 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 static 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
<< "% rp [M_.eq_nbr by #params] double Jacobian matrix of static model "
"equations with respect to parameters "
<< endl
<< "% Dynare may prepend or append "
"auxiliary equations, see M_.aux_vars"
<< endl
<< "% gp [M_.endo_nbr by M_.endo_nbr by #params] double Derivative of the "
"Jacobian matrix of the static model equations with respect to the parameters"
<< endl
<< "% rows: variables in "
"declaration order"
<< endl
<< "% rows: equations in order "
"of declaration"
<< endl
<< "% rpp [#second_order_residual_terms by 4] double Hessian matrix of second "
"derivatives of residuals with respect to parameters;"
<< endl
<< "% rows: respective "
"derivative term"
<< endl
<< "% 1st column: equation "
"number of the term appearing"
<< endl
<< "% 2nd column: number of "
"the first parameter in derivative"
<< endl
<< "% 3rd column: number of "
"the second parameter in derivative"
<< endl
<< "% 4th column: value of "
"the Hessian term"
<< 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 static 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
<< "%" << endl
<< "%" << 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
<< tt_output.str()
<< "rp = zeros(" << equations.size() << ", "
<< tt_output.str() << "rp = zeros(" << equations.size() << ", "
<< symbol_table.param_nbr() << ");" << endl
<< rp_output.str()
<< "gp = zeros(" << equations.size() << ", " << symbol_table.endo_nbr() << ", "
<< symbol_table.param_nbr() << ");" << endl
<< gp_output.str()
<< "if nargout >= 3" << endl
<< rp_output.str() << "gp = zeros(" << equations.size() << ", " << symbol_table.endo_nbr()
<< ", " << symbol_table.param_nbr() << ");" << endl
<< gp_output.str() << "if nargout >= 3" << endl
<< "rpp = zeros(" << params_derivatives.at({0, 2}).size() << ",4);" << endl
<< rpp_output.str()
<< "gpp = zeros(" << params_derivatives.at({ 1, 2 }).size() << ",5);" << endl
<< gpp_output.str()
<< "end" << endl
<< rpp_output.str() << "gpp = zeros(" << params_derivatives.at({1, 2}).size() << ",5);"
<< endl
<< gpp_output.str() << "end" << endl
<< "if nargout >= 5" << endl
<< "hp = zeros(" << params_derivatives.at({2, 1}).size() << ",5);" << endl
<< hp_output.str()
<< "end" << endl
<< hp_output.str() << "end" << endl
<< "end" << endl;
paramsDerivsFile.close();
}
@ -293,24 +340,22 @@ StaticModel::writeParamsDerivativesFile(const string &basename) const
<< "#" << endl
<< "function static_params_derivs(y, x, params)" << endl
<< "@inbounds begin" << endl
<< tt_output.str()
<< "rp = zeros(" << equations.size() << ", "
<< tt_output.str() << "rp = zeros(" << equations.size() << ", "
<< symbol_table.param_nbr() << ");" << endl
<< rp_output.str()
<< "gp = zeros(" << equations.size() << ", " << symbol_table.endo_nbr() << ", "
<< symbol_table.param_nbr() << ");" << endl
<< gp_output.str()
<< "rpp = zeros(" << params_derivatives.at({ 0, 2 }).size() << ",4);" << endl
<< rpp_output.str()
<< "gpp = zeros(" << params_derivatives.at({ 1, 2 }).size() << ",5);" << endl
<< gpp_output.str()
<< "hp = zeros(" << params_derivatives.at({ 2, 1 }).size() << ",5);" << endl
<< hp_output.str()
<< "end" << endl
<< rp_output.str() << "gp = zeros(" << equations.size() << ", "
<< symbol_table.endo_nbr() << ", " << symbol_table.param_nbr() << ");" << endl
<< gp_output.str() << "rpp = zeros(" << params_derivatives.at({0, 2}).size() << ",4);"
<< endl
<< rpp_output.str() << "gpp = zeros(" << params_derivatives.at({1, 2}).size() << ",5);"
<< endl
<< gpp_output.str() << "hp = zeros(" << params_derivatives.at({2, 1}).size() << ",5);"
<< endl
<< hp_output.str() << "end" << endl
<< "return (rp, gp, rpp, gpp, hp)" << endl
<< "end" << endl;
writeToFileIfModified(output, filesystem::path{basename} / "model" / "julia" / "StaticParamsDerivs.jl");
writeToFileIfModified(output, filesystem::path {basename} / "model" / "julia"
/ "StaticParamsDerivs.jl");
}
}
@ -321,18 +366,16 @@ StaticModel::writeRamseyMultipliersDerivativesHelper(ostream &output) const
// Write temporary terms (which includes external function stuff)
deriv_node_temp_terms_t tef_terms;
temporary_terms_t unused_tt_copy;
writeTemporaryTerms<output_type>(ramsey_multipliers_derivatives_temporary_terms,
unused_tt_copy,
ramsey_multipliers_derivatives_temporary_terms_idxs,
output, tef_terms);
writeTemporaryTerms<output_type>(ramsey_multipliers_derivatives_temporary_terms, unused_tt_copy,
ramsey_multipliers_derivatives_temporary_terms_idxs, output,
tef_terms);
// Write chain rule derivatives
for (int k {0};
auto &[row_col, d] : ramsey_multipliers_derivatives)
for (int k {0}; auto& [row_col, d] : ramsey_multipliers_derivatives)
{
output << "g1m_v" << LEFT_ARRAY_SUBSCRIPT(output_type)
<< k + ARRAY_SUBSCRIPT_OFFSET(output_type)
<< RIGHT_ARRAY_SUBSCRIPT(output_type) << "=";
<< k + ARRAY_SUBSCRIPT_OFFSET(output_type) << RIGHT_ARRAY_SUBSCRIPT(output_type)
<< "=";
d->writeOutput(output, output_type, ramsey_multipliers_derivatives_temporary_terms,
ramsey_multipliers_derivatives_temporary_terms_idxs, tef_terms);
output << ";" << endl;

File diff suppressed because it is too large Load Diff

View File

@ -20,16 +20,16 @@
#ifndef _SUBMODEL_HH
#define _SUBMODEL_HH
#include <set>
#include <map>
#include <vector>
#include <iostream>
#include <map>
#include <optional>
#include <set>
#include <vector>
#include "ExprNode.hh"
#include "SymbolTable.hh"
#include "SymbolList.hh"
#include "Statement.hh"
#include "SymbolList.hh"
#include "SymbolTable.hh"
// DynamicModel.hh cant be included here, otherwise it would be a circular dependency
class DynamicModel;
@ -46,7 +46,8 @@ private:
SymbolTable& symbol_table;
set<string> names;
map<string, vector<string>> eqtags, target_eqtags;
map<string, vector<int>> eqnums, target_eqnums, nontarget_eqnums, max_lags, lhs, target_lhs, nontarget_lhs;
map<string, vector<int>> eqnums, target_eqnums, nontarget_eqnums, max_lags, lhs, target_lhs,
nontarget_lhs;
map<string, vector<optional<int>>> orig_diff_var;
map<string, vector<set<pair<int, int>>>> rhs;
map<string, vector<bool>> diff;
@ -84,8 +85,7 @@ public:
const vector<int>& getTargetLhs(const string& name_arg) const;
void setVals(map<string, vector<int>> eqnums_arg, map<string, vector<int>> target_eqnums_arg,
map<string, vector<int>> lhs_arg,
map<string, vector<expr_t>> lhs_expr_t_arg);
map<string, vector<int>> lhs_arg, map<string, vector<expr_t>> lhs_expr_t_arg);
void setRhs(map<string, vector<set<pair<int, int>>>> rhs_arg);
void setMaxLags(map<string, vector<int>> max_lags_arg);
void setDiff(map<string, vector<bool>> diff_arg);
@ -127,10 +127,12 @@ private:
map<string, vector<string>> eqtags;
map<string, vector<int>> eqnums, max_lags, lhs, lhs_orig_symb_ids;
map<string, vector<optional<int>>> orig_diff_var;
map<string, vector<set<pair<int, int>>>> rhs; // name -> for each equation: set of pairs (var, lag)
map<string, vector<set<pair<int, int>>>>
rhs; // name -> for each equation: set of pairs (var, lag)
map<string, vector<bool>> diff;
map<string, vector<expr_t>> lhs_expr_t;
map<string, map<tuple<int, int, int>, expr_t>> AR; // name -> (eqn, lag, lhs_symb_id) -> param_expr_t
map<string, map<tuple<int, int, int>, expr_t>>
AR; // name -> (eqn, lag, lhs_symb_id) -> param_expr_t
/* The A0 matrix is mainly for structural VARs. For reduced-form VARs, it
will be equal to the identity matrix. Also note that A0 in the structural
VAR context is not the same thing as in the trend-component model
@ -206,17 +208,22 @@ private:
map<string, vector<int>> aux_param_symb_ids;
// Decomposition of the expression
map<string, vector<tuple<int, optional<int>, double>>> vars_params_constants;
public:
explicit VarExpectationModelTable(SymbolTable& symbol_table_arg);
void addVarExpectationModel(string name_arg, expr_t expression_arg, string aux_model_name_arg,
string horizon_arg, expr_t discount_arg, int time_shift_arg);
bool isExistingVarExpectationModelName(const string& name_arg) const;
bool empty() const;
void substituteUnaryOpsInExpression(const lag_equivalence_table_t &nodes, ExprNode::subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs);
void substituteUnaryOpsInExpression(const lag_equivalence_table_t& nodes,
ExprNode::subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs);
// Called by DynamicModel::substituteDiff()
void substituteDiffNodesInExpression(const lag_equivalence_table_t &diff_nodes, ExprNode::subst_table_t &diff_subst_table, vector<BinaryOpNode *> &neweqs);
void transformPass(ExprNode::subst_table_t &diff_subst_table,
DynamicModel &dynamic_model, const VarModelTable &var_model_table,
void substituteDiffNodesInExpression(const lag_equivalence_table_t& diff_nodes,
ExprNode::subst_table_t& diff_subst_table,
vector<BinaryOpNode*>& neweqs);
void transformPass(ExprNode::subst_table_t& diff_subst_table, DynamicModel& dynamic_model,
const VarModelTable& var_model_table,
const TrendComponentModelTable& trend_component_model_table);
void writeOutput(ostream& output) const;
void writeJsonOutput(ostream& output) const;
@ -280,10 +287,18 @@ private:
public:
/* Stores info about PAC equations
pac_model_name
(lhs, optim_share_index, ar_params_and_vars, ec_params_and_vars, non_optim_vars_params_and_constants, additive_vars_params_and_constants, optim_additive_vars_params_and_constants)
(lhs, optim_share_index, ar_params_and_vars, ec_params_and_vars,
non_optim_vars_params_and_constants, additive_vars_params_and_constants,
optim_additive_vars_params_and_constants)
*/
using equation_info_t = map<string,
tuple<pair<int, int>, optional<int>, vector<tuple<optional<int>, optional<int>, int>>, pair<int, vector<tuple<int, bool, int>>>, vector<tuple<int, int, optional<int>, double>>, vector<tuple<int, int, optional<int>, double>>, vector<tuple<int, int, optional<int>, double>>>>;
using equation_info_t
= map<string,
tuple<pair<int, int>, optional<int>, vector<tuple<optional<int>, optional<int>, int>>,
pair<int, vector<tuple<int, bool, int>>>,
vector<tuple<int, int, optional<int>, double>>,
vector<tuple<int, int, optional<int>, double>>,
vector<tuple<int, int, optional<int>, double>>>>;
private:
equation_info_t equation_info;
@ -291,7 +306,8 @@ public:
/* (component variable/expr, growth, auxname, kind, coeff. in the linear
combination, growth_param ID (unused if growth is nullptr), vector of h parameters,
original_growth, growth_info) */
using target_component_t = tuple<expr_t, expr_t, string, PacTargetKind, expr_t, int, vector<int>, expr_t, growth_info_t>;
using target_component_t = tuple<expr_t, expr_t, string, PacTargetKind, expr_t, int, vector<int>,
expr_t, growth_info_t>;
private:
// pac_model_name → (target variable/expr, auxname_target_nonstationary, target components)
@ -304,21 +320,26 @@ private:
public:
explicit PacModelTable(SymbolTable& symbol_table_arg);
void addPacModel(string name_arg, string aux_model_name_arg, string discount_arg, expr_t growth_arg, string auxname_arg, PacTargetKind kind_arg);
void addPacModel(string name_arg, string aux_model_name_arg, string discount_arg,
expr_t growth_arg, string auxname_arg, PacTargetKind kind_arg);
bool isExistingPacModelName(const string& name_arg) const;
bool empty() const;
void checkPass(ModFileStructure& mod_file_struct);
// Called by DynamicModel::substituteUnaryOps()
void substituteUnaryOpsInGrowth(const lag_equivalence_table_t &nodes, ExprNode::subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs);
void substituteUnaryOpsInGrowth(const lag_equivalence_table_t& nodes,
ExprNode::subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs);
void findDiffNodesInGrowth(lag_equivalence_table_t& diff_nodes) const;
// Called by DynamicModel::substituteDiff()
void substituteDiffNodesInGrowth(const lag_equivalence_table_t &diff_nodes, ExprNode::subst_table_t &diff_subst_table, vector<BinaryOpNode *> &neweqs);
void substituteDiffNodesInGrowth(const lag_equivalence_table_t& diff_nodes,
ExprNode::subst_table_t& diff_subst_table,
vector<BinaryOpNode*>& neweqs);
// Must be called after substituteDiffNodesInGrowth() and substituteUnaryOpsInGrowth()
void transformPass(const lag_equivalence_table_t& unary_ops_nodes,
ExprNode::subst_table_t& unary_ops_subst_table,
const lag_equivalence_table_t& diff_nodes,
ExprNode::subst_table_t &diff_subst_table,
DynamicModel &dynamic_model, const VarModelTable &var_model_table,
ExprNode::subst_table_t& diff_subst_table, DynamicModel& dynamic_model,
const VarModelTable& var_model_table,
const TrendComponentModelTable& trend_component_model_table);
void writeOutput(ostream& output) const;
void writeJsonOutput(ostream& output) const;
@ -330,5 +351,4 @@ public:
void writeTargetCoefficientsFile(const string& basename) const;
};
#endif

View File

@ -21,8 +21,7 @@
#include "SymbolList.hh"
SymbolList::SymbolList(vector<string> symbols_arg) :
symbols{move(symbols_arg)}
SymbolList::SymbolList(vector<string> symbols_arg) : symbols {move(symbols_arg)}
{
}
@ -48,7 +47,8 @@ SymbolList::checkPass(WarningConsolidation &warnings, const vector<SymbolType> &
{
if (regex_search(symbol, m, re))
{
warnings << "WARNING: symbol_list variable " << symbol << " has not yet been declared. "
warnings
<< "WARNING: symbol_list variable " << symbol << " has not yet been declared. "
<< "This is being ignored because the variable name corresponds to a possible "
<< "auxiliary variable name." << endl;
return;
@ -114,8 +114,7 @@ void
SymbolList::writeOutput(const string& varname, ostream& output) const
{
output << varname << " = {";
for (bool printed_something{false};
const auto &name : symbols)
for (bool printed_something {false}; const auto& name : symbols)
{
if (exchange(printed_something, true))
output << ";";
@ -128,8 +127,7 @@ void
SymbolList::writeJsonOutput(ostream& output) const
{
output << R"("symbol_list": [)";
for (bool printed_something{false};
const auto &name : symbols)
for (bool printed_something {false}; const auto& name : symbols)
{
if (exchange(printed_something, true))
output << ",";
@ -153,6 +151,7 @@ SymbolList::removeDuplicates(const string &dynare_command, WarningConsolidation
unique_symbols.push_back(it);
else
warnings << "WARNING: In " << dynare_command << ": " << it
<< " found more than once in symbol list. Removing all but first occurrence." << endl;
<< " found more than once in symbol list. Removing all but first occurrence."
<< endl;
symbols = unique_symbols;
}

View File

@ -20,13 +20,13 @@
#ifndef _SYMBOL_LIST_HH
#define _SYMBOL_LIST_HH
#include <algorithm>
#include <ostream>
#include <string>
#include <vector>
#include <ostream>
#include <algorithm>
#include "WarningConsolidation.hh"
#include "SymbolTable.hh"
#include "WarningConsolidation.hh"
using namespace std;
@ -36,6 +36,7 @@ class SymbolList
{
private:
vector<string> symbols;
public:
SymbolList() = default;
// This constructor is deliberately not marked explicit, to allow implicit conversion
@ -48,7 +49,8 @@ public:
//! Remove duplicate symbols
void removeDuplicates(const string& dynare_command, WarningConsolidation& warnings);
//! Check symbols to ensure variables have been declared and are endogenous
void checkPass(WarningConsolidation &warnings, const vector<SymbolType> &types, const SymbolTable &symbol_table) const noexcept(false);
void checkPass(WarningConsolidation& warnings, const vector<SymbolType>& types,
const SymbolTable& symbol_table) const noexcept(false);
//! Output content in Matlab format
/*! Creates a string array for Matlab, stored in variable "varname" */
void writeOutput(const string& varname, ostream& output) const;

View File

@ -18,9 +18,9 @@
*/
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cassert>
#include <iostream>
#include <sstream>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#include <boost/algorithm/string/replace.hpp>
@ -30,7 +30,8 @@
#include "SymbolTable.hh"
int
SymbolTable::addSymbol(const string &name, SymbolType type, const string &tex_name, const vector<pair<string, string>> &partition_value) noexcept(false)
SymbolTable::addSymbol(const string& name, SymbolType type, const string& tex_name,
const vector<pair<string, string>>& partition_value) noexcept(false)
{
if (frozen)
throw FrozenException();
@ -201,8 +202,10 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
output << "M_.exo_names_long = cell(" << exo_nbr() << ",1);" << endl;
for (int id = 0; id < exo_nbr(); id++)
output << "M_.exo_names(" << id + 1 << ") = {'" << getName(exo_ids[id]) << "'};" << endl
<< "M_.exo_names_tex(" << id+1 << ") = {'" << getTeXName(exo_ids[id]) << "'};" << endl
<< "M_.exo_names_long(" << id+1 << ") = {'" << getLongName(exo_ids[id]) << "'};" << endl;
<< "M_.exo_names_tex(" << id + 1 << ") = {'" << getTeXName(exo_ids[id]) << "'};"
<< endl
<< "M_.exo_names_long(" << id + 1 << ") = {'" << getLongName(exo_ids[id]) << "'};"
<< endl;
for (auto& partition : getPartitionsForType(SymbolType::exogenous))
if (partition.first != "long_name")
{
@ -210,8 +213,7 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
for (int id = 0; id < exo_nbr(); id++)
{
output << "'";
if (auto it1 = partition.second.find(exo_ids[id]);
it1 != partition.second.end())
if (auto it1 = partition.second.find(exo_ids[id]); it1 != partition.second.end())
output << it1->second;
output << "' ";
}
@ -235,9 +237,12 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
output << "M_.exo_det_names_tex = cell(" << exo_det_nbr() << ",1);" << endl;
output << "M_.exo_det_names_long = cell(" << exo_det_nbr() << ",1);" << endl;
for (int id = 0; id < exo_det_nbr(); id++)
output << "M_.exo_det_names(" << id+1 << ") = {'" << getName(exo_det_ids[id]) << "'};" << endl
<< "M_.exo_det_names_tex(" << id+1 << ") = {'" << getTeXName(exo_det_ids[id]) << "'};" << endl
<< "M_.exo_det_names_long(" << id+1 << ") = {'" << getLongName(exo_det_ids[id]) << "'};" << endl;
output << "M_.exo_det_names(" << id + 1 << ") = {'" << getName(exo_det_ids[id]) << "'};"
<< endl
<< "M_.exo_det_names_tex(" << id + 1 << ") = {'" << getTeXName(exo_det_ids[id])
<< "'};" << endl
<< "M_.exo_det_names_long(" << id + 1 << ") = {'" << getLongName(exo_det_ids[id])
<< "'};" << endl;
output << "M_.exo_det_partitions = struct();" << endl;
for (auto& partition : getPartitionsForType(SymbolType::exogenousDet))
if (partition.first != "long_name")
@ -262,8 +267,10 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
output << "M_.endo_names_long = cell(" << endo_nbr() << ",1);" << endl;
for (int id = 0; id < endo_nbr(); id++)
output << "M_.endo_names(" << id + 1 << ") = {'" << getName(endo_ids[id]) << "'};" << endl
<< "M_.endo_names_tex(" << id+1 << ") = {'" << getTeXName(endo_ids[id]) << "'};" << endl
<< "M_.endo_names_long(" << id+1 << ") = {'" << getLongName(endo_ids[id]) << "'};" << endl;
<< "M_.endo_names_tex(" << id + 1 << ") = {'" << getTeXName(endo_ids[id]) << "'};"
<< endl
<< "M_.endo_names_long(" << id + 1 << ") = {'" << getLongName(endo_ids[id]) << "'};"
<< endl;
output << "M_.endo_partitions = struct();" << endl;
for (auto& partition : getPartitionsForType(SymbolType::endogenous))
if (partition.first != "long_name")
@ -272,8 +279,7 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
for (int id = 0; id < endo_nbr(); id++)
{
output << "'";
if (auto it1 = partition.second.find(endo_ids[id]);
it1 != partition.second.end())
if (auto it1 = partition.second.find(endo_ids[id]); it1 != partition.second.end())
output << it1->second;
output << "' ";
}
@ -288,9 +294,12 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
output << "M_.param_names_long = cell(" << param_nbr() << ",1);" << endl;
for (int id = 0; id < param_nbr(); id++)
{
output << "M_.param_names(" << id+1 << ") = {'" << getName(param_ids[id]) << "'};" << endl
<< "M_.param_names_tex(" << id+1 << ") = {'" << getTeXName(param_ids[id]) << "'};" << endl
<< "M_.param_names_long(" << id+1 << ") = {'" << getLongName(param_ids[id]) << "'};" << endl;
output << "M_.param_names(" << id + 1 << ") = {'" << getName(param_ids[id]) << "'};"
<< endl
<< "M_.param_names_tex(" << id + 1 << ") = {'" << getTeXName(param_ids[id])
<< "'};" << endl
<< "M_.param_names_long(" << id + 1 << ") = {'" << getLongName(param_ids[id])
<< "'};" << endl;
if (getName(param_ids[id]) == "dsge_prior_weight")
output << "options_.dsge_var = 1;" << endl;
}
@ -302,8 +311,7 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
for (int id = 0; id < param_nbr(); id++)
{
output << "'";
if (auto it1 = partition.second.find(param_ids[id]);
it1 != partition.second.end())
if (auto it1 = partition.second.find(param_ids[id]); it1 != partition.second.end())
output << it1->second;
output << "' ";
}
@ -329,8 +337,10 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
else
for (int i = 0; i < static_cast<int>(aux_vars.size()); i++)
{
output << "M_.aux_vars(" << i+1 << ").endo_index = " << getTypeSpecificID(aux_vars[i].symb_id)+1 << ";" << endl
<< "M_.aux_vars(" << i+1 << ").type = " << aux_vars[i].get_type_id() << ";" << endl;
output << "M_.aux_vars(" << i + 1
<< ").endo_index = " << getTypeSpecificID(aux_vars[i].symb_id) + 1 << ";" << endl
<< "M_.aux_vars(" << i + 1 << ").type = " << aux_vars[i].get_type_id() << ";"
<< endl;
switch (aux_vars[i].type)
{
case AuxVarType::endoLead:
@ -345,24 +355,32 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
case AuxVarType::diffLag:
case AuxVarType::diffLead:
case AuxVarType::diffForward:
output << "M_.aux_vars(" << i+1 << ").orig_index = " << getTypeSpecificID(aux_vars[i].orig_symb_id.value())+1 << ";" << endl
<< "M_.aux_vars(" << i+1 << ").orig_lead_lag = " << aux_vars[i].orig_lead_lag.value() << ";" << endl;
output << "M_.aux_vars(" << i + 1
<< ").orig_index = " << getTypeSpecificID(aux_vars[i].orig_symb_id.value()) + 1
<< ";" << endl
<< "M_.aux_vars(" << i + 1
<< ").orig_lead_lag = " << aux_vars[i].orig_lead_lag.value() << ";" << endl;
break;
case AuxVarType::unaryOp:
output << "M_.aux_vars(" << i+1 << ").unary_op = '" << aux_vars[i].unary_op << "';" << endl;
output << "M_.aux_vars(" << i + 1 << ").unary_op = '" << aux_vars[i].unary_op << "';"
<< endl;
[[fallthrough]];
case AuxVarType::diff:
if (aux_vars[i].orig_symb_id)
output << "M_.aux_vars(" << i+1 << ").orig_index = " << getTypeSpecificID(*aux_vars[i].orig_symb_id)+1 << ";" << endl
<< "M_.aux_vars(" << i+1 << ").orig_lead_lag = " << aux_vars[i].orig_lead_lag.value() << ";" << endl;
output << "M_.aux_vars(" << i + 1
<< ").orig_index = " << getTypeSpecificID(*aux_vars[i].orig_symb_id) + 1 << ";"
<< endl
<< "M_.aux_vars(" << i + 1
<< ").orig_lead_lag = " << aux_vars[i].orig_lead_lag.value() << ";" << endl;
break;
case AuxVarType::multiplier:
output << "M_.aux_vars(" << i+1 << ").eq_nbr = " << aux_vars[i].equation_number_for_multiplier + 1 << ";" << endl;
output << "M_.aux_vars(" << i + 1
<< ").eq_nbr = " << aux_vars[i].equation_number_for_multiplier + 1 << ";"
<< endl;
break;
}
if (expr_t orig_expr = aux_vars[i].expr_node;
orig_expr)
if (expr_t orig_expr = aux_vars[i].expr_node; orig_expr)
{
output << "M_.aux_vars(" << i + 1 << ").orig_expr = '";
orig_expr->writeJsonOutput(output, {}, {});
@ -381,8 +399,7 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
if (observedVariablesNbr() > 0)
{
output << "options_.varobs = cell(" << observedVariablesNbr() << ", 1);" << endl;
for (int ic{1};
int it : varobs)
for (int ic {1}; int it : varobs)
output << "options_.varobs(" << ic++ << ") = {'" << getName(it) << "'};" << endl;
output << "options_.varobs_id = [ ";
@ -394,8 +411,7 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
if (observedExogenousVariablesNbr() > 0)
{
output << "options_.varexobs = cell(1);" << endl;
for (int ic{1};
int it : varexobs)
for (int ic {1}; int it : varexobs)
output << "options_.varexobs(" << ic++ << ") = {'" << getName(it) << "'};" << endl;
output << "options_.varexobs_id = [ ";
@ -416,19 +432,23 @@ SymbolTable::addLeadAuxiliaryVarInternal(bool endo, int index, expr_t expr_arg)
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: you should rename your variable called " << varname << ", this name is internally used by Dynare" << endl;
cerr << "ERROR: you should rename your variable called " << varname
<< ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
aux_vars.emplace_back(symb_id, (endo ? AuxVarType::endoLead : AuxVarType::exoLead), 0, 0, 0, 0, expr_arg, "");
aux_vars.emplace_back(symb_id, (endo ? AuxVarType::endoLead : AuxVarType::exoLead), 0, 0, 0, 0,
expr_arg, "");
return symb_id;
}
int
SymbolTable::addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag, expr_t expr_arg) noexcept(false)
SymbolTable::addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag,
expr_t expr_arg) noexcept(false)
{
string varname{(endo ? "AUX_ENDO_LAG_" : "AUX_EXO_LAG_") + to_string(orig_symb_id) + "_" + to_string(-orig_lead_lag)};
string varname {(endo ? "AUX_ENDO_LAG_" : "AUX_EXO_LAG_") + to_string(orig_symb_id) + "_"
+ to_string(-orig_lead_lag)};
int symb_id;
try
{
@ -436,11 +456,13 @@ SymbolTable::addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_le
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: you should rename your variable called " << varname << ", this name is internally used by Dynare" << endl;
cerr << "ERROR: you should rename your variable called " << varname
<< ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
aux_vars.emplace_back(symb_id, (endo ? AuxVarType::endoLag : AuxVarType::exoLag), orig_symb_id, orig_lead_lag, 0, 0, expr_arg, "");
aux_vars.emplace_back(symb_id, (endo ? AuxVarType::endoLag : AuxVarType::exoLag), orig_symb_id,
orig_lead_lag, 0, 0, expr_arg, "");
return symb_id;
}
@ -452,7 +474,8 @@ SymbolTable::addEndoLeadAuxiliaryVar(int index, expr_t expr_arg) noexcept(false)
}
int
SymbolTable::addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) noexcept(false)
SymbolTable::addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag,
expr_t expr_arg) noexcept(false)
{
return addLagAuxiliaryVarInternal(true, orig_symb_id, orig_lead_lag, expr_arg);
}
@ -464,13 +487,15 @@ SymbolTable::addExoLeadAuxiliaryVar(int index, expr_t expr_arg) noexcept(false)
}
int
SymbolTable::addExoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) noexcept(false)
SymbolTable::addExoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag,
expr_t expr_arg) noexcept(false)
{
return addLagAuxiliaryVarInternal(false, orig_symb_id, orig_lead_lag, expr_arg);
}
int
SymbolTable::addExpectationAuxiliaryVar(int information_set, int index, expr_t expr_arg) noexcept(false)
SymbolTable::addExpectationAuxiliaryVar(int information_set, int index,
expr_t expr_arg) noexcept(false)
{
string varname {"AUX_EXPECT_"s + (information_set < 0 ? "LAG" : "LEAD") + "_"
+ to_string(abs(information_set)) + "_" + to_string(index)};
@ -481,7 +506,8 @@ SymbolTable::addExpectationAuxiliaryVar(int information_set, int index, expr_t e
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: you should rename your variable called " << varname << ", this name is internally used by Dynare" << endl;
cerr << "ERROR: you should rename your variable called " << varname
<< ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
@ -491,7 +517,8 @@ SymbolTable::addExpectationAuxiliaryVar(int information_set, int index, expr_t e
}
int
SymbolTable::addLogTransformAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) noexcept(false)
SymbolTable::addLogTransformAuxiliaryVar(int orig_symb_id, int orig_lead_lag,
expr_t expr_arg) noexcept(false)
{
string varname = "LOG_" + getName(orig_symb_id);
int symb_id;
@ -501,17 +528,21 @@ SymbolTable::addLogTransformAuxiliaryVar(int orig_symb_id, int orig_lead_lag, ex
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: you should rename your variable called " << varname << ", it conflicts with the auxiliary variable created for representing the log of " << getName(orig_symb_id) << endl;
cerr << "ERROR: you should rename your variable called " << varname
<< ", it conflicts with the auxiliary variable created for representing the log of "
<< getName(orig_symb_id) << endl;
exit(EXIT_FAILURE);
}
aux_vars.emplace_back(symb_id, AuxVarType::logTransform, orig_symb_id, orig_lead_lag, 0, 0, expr_arg, "");
aux_vars.emplace_back(symb_id, AuxVarType::logTransform, orig_symb_id, orig_lead_lag, 0, 0,
expr_arg, "");
return symb_id;
}
int
SymbolTable::addDiffLagAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, int orig_lag) noexcept(false)
SymbolTable::addDiffLagAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id,
int orig_lag) noexcept(false)
{
string varname {"AUX_DIFF_LAG_" + to_string(index)};
int symb_id;
@ -521,7 +552,8 @@ SymbolTable::addDiffLagAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: you should rename your variable called " << varname << ", this name is internally used by Dynare" << endl;
cerr << "ERROR: you should rename your variable called " << varname
<< ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
@ -531,7 +563,8 @@ SymbolTable::addDiffLagAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id
}
int
SymbolTable::addDiffLeadAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, int orig_lead) noexcept(false)
SymbolTable::addDiffLeadAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id,
int orig_lead) noexcept(false)
{
string varname {"AUX_DIFF_LEAD_" + to_string(index)};
int symb_id;
@ -541,7 +574,8 @@ SymbolTable::addDiffLeadAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_i
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: you should rename your variable called " << varname << ", this name is internally used by Dynare" << endl;
cerr << "ERROR: you should rename your variable called " << varname
<< ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
@ -551,7 +585,8 @@ SymbolTable::addDiffLeadAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_i
}
int
SymbolTable::addDiffAuxiliaryVar(int index, expr_t expr_arg, optional<int> orig_symb_id, optional<int> orig_lag) noexcept(false)
SymbolTable::addDiffAuxiliaryVar(int index, expr_t expr_arg, optional<int> orig_symb_id,
optional<int> orig_lag) noexcept(false)
{
string varname {"AUX_DIFF_" + to_string(index)};
int symb_id;
@ -561,17 +596,21 @@ SymbolTable::addDiffAuxiliaryVar(int index, expr_t expr_arg, optional<int> orig_
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: you should rename your variable called " << varname << ", this name is internally used by Dynare" << endl;
cerr << "ERROR: you should rename your variable called " << varname
<< ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
aux_vars.emplace_back(symb_id, AuxVarType::diff, move(orig_symb_id), move(orig_lag), 0, 0, expr_arg, "");
aux_vars.emplace_back(symb_id, AuxVarType::diff, move(orig_symb_id), move(orig_lag), 0, 0,
expr_arg, "");
return symb_id;
}
int
SymbolTable::addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op, optional<int> orig_symb_id, optional<int> orig_lag) noexcept(false)
SymbolTable::addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op,
optional<int> orig_symb_id,
optional<int> orig_lag) noexcept(false)
{
string varname {"AUX_UOP_" + to_string(index)};
int symb_id;
@ -581,11 +620,13 @@ SymbolTable::addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op,
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: you should rename your variable called " << varname << ", this name is internally used by Dynare" << endl;
cerr << "ERROR: you should rename your variable called " << varname
<< ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
aux_vars.emplace_back(symb_id, AuxVarType::unaryOp, move(orig_symb_id), move(orig_lag), 0, 0, expr_arg, unary_op);
aux_vars.emplace_back(symb_id, AuxVarType::unaryOp, move(orig_symb_id), move(orig_lag), 0, 0,
expr_arg, unary_op);
return symb_id;
}
@ -601,7 +642,8 @@ SymbolTable::addMultiplierAuxiliaryVar(int index) noexcept(false)
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: you should rename your variable called " << varname << ", this name is internally used by Dynare" << endl;
cerr << "ERROR: you should rename your variable called " << varname
<< ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
@ -610,7 +652,8 @@ SymbolTable::addMultiplierAuxiliaryVar(int index) noexcept(false)
}
int
SymbolTable::addDiffForwardAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) noexcept(false)
SymbolTable::addDiffForwardAuxiliaryVar(int orig_symb_id, int orig_lead_lag,
expr_t expr_arg) noexcept(false)
{
string varname {"AUX_DIFF_FWRD_" + to_string(orig_symb_id + 1)};
int symb_id;
@ -620,11 +663,13 @@ SymbolTable::addDiffForwardAuxiliaryVar(int orig_symb_id, int orig_lead_lag, exp
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: you should rename your variable called " << varname << ", this name is internally used by Dynare" << endl;
cerr << "ERROR: you should rename your variable called " << varname
<< ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
aux_vars.emplace_back(symb_id, AuxVarType::diffForward, orig_symb_id, orig_lead_lag, 0, 0, expr_arg, "");
aux_vars.emplace_back(symb_id, AuxVarType::diffForward, orig_symb_id, orig_lead_lag, 0, 0,
expr_arg, "");
return symb_id;
}
@ -638,7 +683,10 @@ SymbolTable::addPacExpectationAuxiliaryVar(const string &name, expr_t expr_arg)
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: the variable/parameter '" << name << "' conflicts with a variable that will be generated for a 'pac_expectation' expression. Please rename it." << endl;
cerr << "ERROR: the variable/parameter '" << name
<< "' conflicts with a variable that will be generated for a 'pac_expectation' "
"expression. Please rename it."
<< endl;
exit(EXIT_FAILURE);
}
@ -656,7 +704,10 @@ SymbolTable::addPacTargetNonstationaryAuxiliaryVar(const string &name, expr_t ex
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: the variable/parameter '" << name << "' conflicts with a variable that will be generated for a 'pac_target_nonstationary' expression. Please rename it." << endl;
cerr << "ERROR: the variable/parameter '" << name
<< "' conflicts with a variable that will be generated for a 'pac_target_nonstationary' "
"expression. Please rename it."
<< endl;
exit(EXIT_FAILURE);
}
@ -678,19 +729,17 @@ int
SymbolTable::getOrigSymbIdForAuxVar(int aux_var_symb_id_arg) const noexcept(false)
{
for (const auto& aux_var : aux_vars)
if ((aux_var.type == AuxVarType::endoLag
|| aux_var.type == AuxVarType::exoLag
|| aux_var.type == AuxVarType::diff
|| aux_var.type == AuxVarType::diffLag
|| aux_var.type == AuxVarType::diffLead
|| aux_var.type == AuxVarType::diffForward
if ((aux_var.type == AuxVarType::endoLag || aux_var.type == AuxVarType::exoLag
|| aux_var.type == AuxVarType::diff || aux_var.type == AuxVarType::diffLag
|| aux_var.type == AuxVarType::diffLead || aux_var.type == AuxVarType::diffForward
|| aux_var.type == AuxVarType::unaryOp)
&& aux_var.symb_id == aux_var_symb_id_arg)
{
if (optional<int> r = aux_var.orig_symb_id; r)
return *r;
else
throw UnknownSymbolIDException{aux_var_symb_id_arg}; // Some diff and unaryOp auxvars have orig_symb_id unset
throw UnknownSymbolIDException {
aux_var_symb_id_arg}; // Some diff and unaryOp auxvars have orig_symb_id unset
}
throw UnknownSymbolIDException {aux_var_symb_id_arg};
}
@ -847,17 +896,18 @@ SymbolTable::getEndogenous() const
bool
SymbolTable::isAuxiliaryVariable(int symb_id) const
{
return any_of(aux_vars.begin(), aux_vars.end(), [=](const auto &av) { return av.symb_id == symb_id; });
return any_of(aux_vars.begin(), aux_vars.end(),
[=](const auto& av) { return av.symb_id == symb_id; });
}
bool
SymbolTable::isDiffAuxiliaryVariable(int symb_id) const
{
return any_of(aux_vars.begin(), aux_vars.end(),
[=](const auto &av) { return av.symb_id == symb_id
&& (av.type == AuxVarType::diff
|| av.type == AuxVarType::diffLag
|| av.type == AuxVarType::diffLead); });
return any_of(aux_vars.begin(), aux_vars.end(), [=](const auto& av) {
return av.symb_id == symb_id
&& (av.type == AuxVarType::diff || av.type == AuxVarType::diffLag
|| av.type == AuxVarType::diffLead);
});
}
set<int>
@ -953,7 +1003,8 @@ SymbolTable::writeJsonOutput(ostream &output) const
case AuxVarType::diffLag:
case AuxVarType::diffLead:
case AuxVarType::diffForward:
output << R"(, "orig_index": )" << getTypeSpecificID(aux_vars[i].orig_symb_id.value())+1
output << R"(, "orig_index": )"
<< getTypeSpecificID(aux_vars[i].orig_symb_id.value()) + 1
<< R"(, "orig_lead_lag": )" << aux_vars[i].orig_lead_lag.value();
break;
case AuxVarType::unaryOp:
@ -969,8 +1020,7 @@ SymbolTable::writeJsonOutput(ostream &output) const
break;
}
if (expr_t orig_expr = aux_vars[i].expr_node;
orig_expr)
if (expr_t orig_expr = aux_vars[i].expr_node; orig_expr)
{
output << R"(, "orig_expr": ")";
orig_expr->writeJsonOutput(output, {}, {});
@ -992,9 +1042,10 @@ SymbolTable::writeJsonVarVector(ostream &output, const vector<int> &varvec) cons
output << ", ";
output << "{"
<< R"("name":")" << getName(varvec[i]) << R"(", )"
<< R"("texName":")" << boost::replace_all_copy(getTeXName(varvec[i]), R"(\)", R"(\\)") << R"(", )"
<< R"("longName":")" << boost::replace_all_copy(getLongName(varvec[i]), R"(\)", R"(\\)") << R"("})"
<< endl;
<< R"("texName":")" << boost::replace_all_copy(getTeXName(varvec[i]), R"(\)", R"(\\)")
<< R"(", )"
<< R"("longName":")"
<< boost::replace_all_copy(getLongName(varvec[i]), R"(\)", R"(\\)") << R"("})" << endl;
}
output << "]" << endl;
}

View File

@ -21,12 +21,12 @@
#define _SYMBOLTABLE_HH
#include <map>
#include <optional>
#include <ostream>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include <set>
#include <ostream>
#include <optional>
#include "CommonEnums.hh"
#include "ExprNode.hh"
@ -50,10 +50,12 @@ enum class AuxVarType
logTransform = 7, //!< Log-transformation of a variable declared with “var(log)”
diff = 8, //!< Variable for Diff operator
diffLag = 9, //!< Variable for timing between Diff operators (lag)
unaryOp = 10, //!< Variable for allowing the undiff operator to work when diff was taken of unary op, eg diff(log(x))
unaryOp = 10, //!< Variable for allowing the undiff operator to work when diff was taken of unary
//!< op, eg diff(log(x))
diffLead = 11, //!< Variable for timing between Diff operators (lead)
pacExpectation = 12, //!< Variable created for the substitution of the pac_expectation operator
pacTargetNonstationary = 13 //!< Variable created for the substitution of the pac_target_nonstationary operator
pacTargetNonstationary
= 13 //!< Variable created for the substitution of the pac_target_nonstationary operator
};
//! Information on some auxiliary variables
@ -65,8 +67,8 @@ struct AuxVarInfo
the definition of this auxvar.
Used by endoLag, exoLag, diffForward, logTransform, diff,
diffLag, diffLead and unaryOp.
For diff and unaryOp, if the argument expression is more complex
than than a simple variable, this value is unset
For diff and unaryOp, if the argument expression is more
complex than than a simple variable, this value is unset
(hence the need for std::optional). */
const optional<int> orig_lead_lag; /* Lead/lag of the (only) endo as it appears on the RHS of the
definition of this auxvar. Only set if orig_symb_id is set
@ -196,8 +198,8 @@ public:
{
public:
int orig_symb_id, orig_lead_lag, symb_id;
SearchFailedException(int orig_symb_id_arg, int orig_lead_lag_arg) : orig_symb_id{orig_symb_id_arg},
orig_lead_lag{orig_lead_lag_arg}
SearchFailedException(int orig_symb_id_arg, int orig_lead_lag_arg) :
orig_symb_id {orig_symb_id_arg}, orig_lead_lag {orig_lead_lag_arg}
{
}
explicit SearchFailedException(int symb_id_arg) : symb_id {symb_id_arg}
@ -207,17 +209,20 @@ public:
private:
//! Factorized code for adding aux lag variables
int addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag, expr_t arg) noexcept(false);
int addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag,
expr_t arg) noexcept(false);
//! Factorized code for adding aux lead variables
int addLeadAuxiliaryVarInternal(bool endo, int index, expr_t arg) noexcept(false);
//! Factorized code for Json writing
void writeJsonVarVector(ostream& output, const vector<int>& varvec) const;
//! Factorized code for asserting that 0 <= symb_id <= symbol_table.size()
inline void validateSymbID(int symb_id) const noexcept(false);
public:
//! Add a symbol
/*! Returns the symbol ID */
int addSymbol(const string &name, SymbolType type, const string &tex_name, const vector<pair<string, string>> &partition_value) noexcept(false);
int addSymbol(const string& name, SymbolType type, const string& tex_name,
const vector<pair<string, string>>& partition_value) noexcept(false);
//! Add a symbol without its TeX name (will be equal to its name)
/*! Returns the symbol ID */
int addSymbol(const string& name, SymbolType type) noexcept(false);
@ -228,9 +233,9 @@ public:
int addEndoLeadAuxiliaryVar(int index, expr_t arg) noexcept(false);
//! Adds an auxiliary variable for endogenous with lag >= 2
/*!
\param[in] orig_symb_id symbol ID of the endogenous declared by the user that this new variable will represent
\param[in] orig_lead_lag lag value such that this new variable will be equivalent to orig_symb_id(orig_lead_lag)
\return the symbol ID of the new symbol */
\param[in] orig_symb_id symbol ID of the endogenous declared by the user that this new variable
will represent \param[in] orig_lead_lag lag value such that this new variable will be equivalent
to orig_symb_id(orig_lead_lag) \return the symbol ID of the new symbol */
int addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t arg) noexcept(false);
//! Adds an auxiliary variable for endogenous with lead >= 1
/*!
@ -239,9 +244,9 @@ public:
int addExoLeadAuxiliaryVar(int index, expr_t arg) noexcept(false);
//! Adds an auxiliary variable for exogenous with lag >= 1
/*!
\param[in] orig_symb_id symbol ID of the exogenous declared by the user that this new variable will represent
\param[in] orig_lead_lag lag value such that this new variable will be equivalent to orig_symb_id(orig_lead_lag)
\return the symbol ID of the new symbol */
\param[in] orig_symb_id symbol ID of the exogenous declared by the user that this new variable
will represent \param[in] orig_lead_lag lag value such that this new variable will be equivalent
to orig_symb_id(orig_lead_lag) \return the symbol ID of the new symbol */
int addExoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t arg) noexcept(false);
//! Adds an auxiliary variable for the expectation operator
/*!
@ -262,7 +267,8 @@ public:
orig_lead_lag is typically 0
expr_arg is typically log(orig_symb_id)
*/
int addLogTransformAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) noexcept(false);
int addLogTransformAuxiliaryVar(int orig_symb_id, int orig_lead_lag,
expr_t expr_arg) noexcept(false);
//! Adds an auxiliary variable for the (time) differentiate of a forward var
/*!
\param[in] orig_symb_id The symb_id of the forward variable
@ -296,13 +302,18 @@ public:
diffLead increases it). */
pair<int, int> unrollDiffLeadLagChain(int symb_id, int lag) const noexcept(false);
//! Adds an auxiliary variable when the diff operator is encountered
int addDiffAuxiliaryVar(int index, expr_t expr_arg, optional<int> orig_symb_id = nullopt, optional<int> orig_lag = nullopt) noexcept(false);
int addDiffAuxiliaryVar(int index, expr_t expr_arg, optional<int> orig_symb_id = nullopt,
optional<int> orig_lag = nullopt) noexcept(false);
//! Takes care of timing between diff statements
int addDiffLagAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, int orig_lag) noexcept(false);
int addDiffLagAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id,
int orig_lag) noexcept(false);
//! Takes care of timing between diff statements
int addDiffLeadAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, int orig_lead) noexcept(false);
int addDiffLeadAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id,
int orig_lead) noexcept(false);
//! An Auxiliary variable for a unary op
int addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op, optional<int> orig_symb_id = nullopt, optional<int> orig_lag = nullopt) noexcept(false);
int addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op,
optional<int> orig_symb_id = nullopt,
optional<int> orig_lag = nullopt) noexcept(false);
//! An auxiliary variable for a pac_expectation operator
int addPacExpectationAuxiliaryVar(const string& name, expr_t expr_arg);
//! An auxiliary variable for a pac_target_nonstationary operator
@ -321,7 +332,8 @@ public:
inline string getTeXName(int id) const noexcept(false);
//! Get long name
inline string getLongName(int id) const noexcept(false);
//! Returns true if the partition name is the first encountered for the type of variable represented by id
//! Returns true if the partition name is the first encountered for the type of variable
//! represented by id
bool isFirstOfPartitionForType(int id) const noexcept(false);
//! Returns a list of partitions and symbols that belong to that partition
map<string, map<int, string>> getPartitionsForType(SymbolType st) const noexcept(false);
@ -382,7 +394,8 @@ public:
int observedExogenousVariablesNbr() const;
//! Is a given symbol in the set of observed exogenous variables
bool isObservedExogenousVariable(int symb_id) const;
//! Return the index of a given observed exogenous variable in the vector of all observed variables
//! Return the index of a given observed exogenous variable in the vector of all observed
//! variables
int getObservedExogenousVariableIndex(int symb_id) const;
vector<int> getTrendVarIds() const;
//! Get list of exogenous variables
@ -404,7 +417,8 @@ public:
no original variable (e.g. aux var for lead, Lagrange Multiplier or diff
associated to a complex expression). */
int getUltimateOrigSymbID(int symb_id) const;
//! If this is a Lagrange multiplier, return its associated equation number; otherwise return nullopt
//! If this is a Lagrange multiplier, return its associated equation number; otherwise return
//! nullopt
optional<int> getEquationNumberForMultiplier(int symb_id) const;
/* Return all the information about a given auxiliary variable. Throws
UnknownSymbolIDException if it is not an aux var */
@ -465,8 +479,7 @@ SymbolTable::getType(const string &name) const noexcept(false)
inline int
SymbolTable::getID(const string& name) const noexcept(false)
{
if (auto iter = symbol_table.find(name);
iter != symbol_table.end())
if (auto iter = symbol_table.find(name); iter != symbol_table.end())
return iter->second;
else
throw UnknownSymbolNameException {name};
@ -480,8 +493,7 @@ SymbolTable::getTypeSpecificID(int id) const noexcept(false)
validateSymbID(id);
if (auto it = type_specific_ids.find(id);
it != type_specific_ids.end())
if (auto it = type_specific_ids.find(id); it != type_specific_ids.end())
return it->second;
else
throw NoTypeSpecificIDException {id};

View File

@ -17,8 +17,8 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <algorithm>
#include <iostream>
#include "VariableDependencyGraph.hh"
@ -59,16 +59,17 @@ VariableDependencyGraph::eliminate(vertex_descriptor vertex_to_eliminate)
{
if (in_degree(vertex_to_eliminate, *this) > 0 && out_degree(vertex_to_eliminate, *this) > 0)
for (auto [it_in, in_end] = in_edges(vertex_to_eliminate, *this); it_in != in_end; ++it_in)
for (auto [it_out, out_end] = out_edges(vertex_to_eliminate, *this); it_out != out_end; ++it_out)
if (auto [ed, exist] = edge(source(*it_in, *this), target(*it_out, *this), *this);
!exist)
for (auto [it_out, out_end] = out_edges(vertex_to_eliminate, *this); it_out != out_end;
++it_out)
if (auto [ed, exist] = edge(source(*it_in, *this), target(*it_out, *this), *this); !exist)
add_edge(source(*it_in, *this), target(*it_out, *this), *this);
suppress(vertex_to_eliminate);
}
bool
VariableDependencyGraph::hasCycleDFS(vertex_descriptor u, color_t &color, vector<int> &circuit_stack) const
VariableDependencyGraph::hasCycleDFS(vertex_descriptor u, color_t& color,
vector<int>& circuit_stack) const
{
auto v_index = get(vertex_index, *this);
color[u] = gray_color;
@ -199,7 +200,8 @@ VariableDependencyGraph::eliminationOfVerticesWithOneOrLessIndegreeOrOutdegree()
if (in_degree_n <= 1 || out_degree_n <= 1)
{
not_a_loop = true;
if (in_degree_n >= 1 && out_degree_n >= 1) // Do not eliminate a vertex if it loops on itself!
if (in_degree_n >= 1
&& out_degree_n >= 1) // Do not eliminate a vertex if it loops on itself!
for (auto [it_in, in_end] = in_edges(*it, *this); it_in != in_end; ++it_in)
if (source(*it_in, *this) == target(*it_in, *this))
not_a_loop = false;
@ -285,8 +287,10 @@ VariableDependencyGraph::minimalSetOfFeedbackVertices() const
while (something_has_been_done && num_vertices(G) > 0)
{
something_has_been_done = G.eliminationOfVerticesWithOneOrLessIndegreeOrOutdegree();
something_has_been_done = G.eliminationOfVerticesBelongingToAClique() || something_has_been_done;
something_has_been_done = G.suppressionOfVerticesWithLoop(feed_back_vertices) || something_has_been_done;
something_has_been_done
= G.eliminationOfVerticesBelongingToAClique() || something_has_been_done;
something_has_been_done
= G.suppressionOfVerticesWithLoop(feed_back_vertices) || something_has_been_done;
}
if (!G.hasCycle())
@ -362,7 +366,8 @@ VariableDependencyGraph::sortedStronglyConnectedComponents() const
auto v_index = get(vertex_index, *this);
// Compute SCCs and create mapping from vertices to unordered SCCs
int num_scc = strong_components(static_cast<base>(*this), make_iterator_property_map(vertex2scc.begin(), v_index));
int num_scc = strong_components(static_cast<base>(*this),
make_iterator_property_map(vertex2scc.begin(), v_index));
// Create directed acyclic graph (DAG) associated to the SCCs
adjacency_list<vecS, vecS, directedS> dag(num_scc);

View File

@ -30,20 +30,25 @@
using namespace std;
using VertexProperty_t = boost::property<boost::vertex_index_t, int,
boost::property<boost::vertex_index1_t, int,
using VertexProperty_t = boost::property<
boost::vertex_index_t, int,
boost::property<
boost::vertex_index1_t, int,
boost::property<boost::vertex_degree_t, int,
boost::property<boost::vertex_in_degree_t, int,
boost::property<boost::vertex_out_degree_t, int>>>>>;
/* Class used to store a graph representing dependencies between variables.
Used in the block decomposition. */
class VariableDependencyGraph
: public boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, VertexProperty_t>
class VariableDependencyGraph :
public boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS,
VertexProperty_t>
{
public:
using color_t = map<boost::graph_traits<VariableDependencyGraph>::vertex_descriptor, boost::default_color_type>;
using base = boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, VertexProperty_t>;
using color_t = map<boost::graph_traits<VariableDependencyGraph>::vertex_descriptor,
boost::default_color_type>;
using base
= boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, VertexProperty_t>;
VariableDependencyGraph(int n);
//! Extracts a subgraph
@ -58,7 +63,8 @@ public:
//! Return the feedback set
set<int> minimalSetOfFeedbackVertices() const;
//! Reorder the recursive variables
/*! They appear first in a quasi triangular form and they are followed by the feedback variables */
/*! They appear first in a quasi triangular form and they are followed by the feedback variables
*/
vector<int> reorderRecursiveVariables(const set<int>& feedback_vertices) const;
/* Computes the strongly connected components (SCCs) of the graph, and sort them
topologically.
@ -67,6 +73,7 @@ public:
pair<int, vector<int>> sortedStronglyConnectedComponents() const;
// Print on stdout a description of the graph
void print() const;
private:
// Remove a vertex (including all edges to and from it); takes a vertex descriptor
void suppress(vertex_descriptor vertex_to_eliminate);

View File

@ -40,9 +40,7 @@ operator<<(WarningConsolidation &wcc, const Dynare::location &loc)
stringstream ostr;
Dynare::position last = loc.end - 1;
ostr << loc.begin;
if (last.filename
&& (!loc.begin.filename
|| *loc.begin.filename != *last.filename))
if (last.filename && (!loc.begin.filename || *loc.begin.filename != *last.filename))
ostr << '-' << last;
else if (loc.begin.line != last.line)
ostr << '-' << last.line << '.' << last.column;

View File

@ -20,9 +20,9 @@
#ifndef _WARNINGCONSOLIDATION_HH
#define _WARNINGCONSOLIDATION_HH
#include "DynareBisonLocation.hh"
#include <sstream>
#include <string>
#include "DynareBisonLocation.hh"
using namespace std;
@ -36,7 +36,7 @@ private:
public:
explicit WarningConsolidation(bool no_warn_arg) : no_warn {no_warn_arg}
{
};
}
//! Add A Warning to the StringStream
friend WarningConsolidation& operator<<(WarningConsolidation& wcc, const string& warning);

View File

@ -68,8 +68,10 @@ Include::interpret(ostream &output, Environment &env, vector<filesystem::path> &
errmsg << " * " << current_path().string() << endl;
for (const auto& dir : paths)
errmsg << " * " << absolute(dir).string() << endl;
error(StackTrace("@#include", "Could not open " + filename.string()
+". The following directories were searched:\n" + errmsg.str(), location));
error(StackTrace("@#include",
"Could not open " + filename.string()
+ ". The following directories were searched:\n" + errmsg.str(),
location));
}
}
Driver m;
@ -92,7 +94,8 @@ Include::interpret(ostream &output, Environment &env, vector<filesystem::path> &
}
void
IncludePath::interpret([[maybe_unused]] ostream &output, Environment &env, vector<filesystem::path> &paths)
IncludePath::interpret([[maybe_unused]] ostream& output, Environment& env,
vector<filesystem::path>& paths)
{
using namespace filesystem;
try
@ -133,7 +136,8 @@ IncludePath::interpret([[maybe_unused]] ostream &output, Environment &env, vecto
}
void
Define::interpret([[maybe_unused]] ostream &output, Environment &env, [[maybe_unused]] vector<filesystem::path> &paths)
Define::interpret([[maybe_unused]] ostream& output, Environment& env,
[[maybe_unused]] vector<filesystem::path>& paths)
{
try
{
@ -176,7 +180,8 @@ Echo::interpret(ostream &output, Environment &env, [[maybe_unused]] vector<files
}
void
Error::interpret([[maybe_unused]] ostream &output, Environment &env, [[maybe_unused]] vector<filesystem::path> &paths)
Error::interpret([[maybe_unused]] ostream& output, Environment& env,
[[maybe_unused]] vector<filesystem::path>& paths)
{
try
{
@ -194,7 +199,8 @@ Error::interpret([[maybe_unused]] ostream &output, Environment &env, [[maybe_unu
}
void
EchoMacroVars::interpret(ostream &output, Environment &env, [[maybe_unused]] vector<filesystem::path> &paths)
EchoMacroVars::interpret(ostream& output, Environment& env,
[[maybe_unused]] vector<filesystem::path>& paths)
{
if (save)
env.print(output, vars, location.begin.line, true);
@ -237,8 +243,11 @@ For::interpret(ostream &output, Environment &env, vector<filesystem::path> &path
{
TuplePtr mtp = dynamic_pointer_cast<Tuple>(btp);
if (index_vec.size() != mtp->size())
error(StackTrace("@#for", "Encountered tuple of size " + to_string(mtp->size())
+ " but only have " + to_string(index_vec.size()) + " index variables", location));
error(StackTrace("@#for",
"Encountered tuple of size " + to_string(mtp->size())
+ " but only have " + to_string(index_vec.size())
+ " index variables",
location));
else
for (size_t j = 0; j < index_vec.size(); j++)
env.define(index_vec.at(j), mtp->at(j));
@ -262,8 +271,7 @@ For::interpret(ostream &output, Environment &env, vector<filesystem::path> &path
void
If::interpret(ostream& output, Environment& env, vector<filesystem::path>& paths)
{
for (bool first_clause{true};
const auto &[expr, body] : expr_and_body)
for (bool first_clause {true}; const auto& [expr, body] : expr_and_body)
try
{
if ((ifdef || ifndef) && exchange(first_clause, false))
@ -285,8 +293,8 @@ If::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths
RealPtr dp = dynamic_pointer_cast<Real>(tmp);
BoolPtr bp = dynamic_pointer_cast<Bool>(tmp);
if (!bp && !dp)
error(StackTrace("@#if",
"The condition must evaluate to a boolean or a double", location));
error(StackTrace("@#if", "The condition must evaluate to a boolean or a double",
location));
if ((bp && *bp) || (dp && *dp))
{
interpretBody(body, output, env, paths);
@ -307,10 +315,10 @@ If::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths
}
void
If::interpretBody(const vector<DirectivePtr> &body, ostream &output, Environment &env, vector<filesystem::path> &paths)
If::interpretBody(const vector<DirectivePtr>& body, ostream& output, Environment& env,
vector<filesystem::path>& paths)
{
for (bool printLine{true};
const auto &statement : body)
for (bool printLine {true}; const auto& statement : body)
{
if (exchange(printLine, false))
statement->printLineInfo(output);

View File

@ -30,13 +30,13 @@ namespace macro
{
// A Parent class just for clarity
public:
explicit Directive(Tokenizer::location location_arg) :
Node(move(location_arg)) { }
explicit Directive(Tokenizer::location location_arg) : Node(move(location_arg))
{
}
// Directives can be interpreted
virtual void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) = 0;
};
class TextNode : public Directive
{
// Class for text not interpreted by macroprocessor
@ -44,17 +44,20 @@ namespace macro
// Treated as such as the output is only to be interpreted
private:
const string text;
public:
TextNode(string text_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), text{move(text_arg)} { }
Directive(move(location_arg)), text {move(text_arg)}
{
}
void
interpret(ostream &output, [[maybe_unused]] Environment &env, [[maybe_unused]] vector<filesystem::path> &paths) override
interpret(ostream& output, [[maybe_unused]] Environment& env,
[[maybe_unused]] vector<filesystem::path>& paths) override
{
output << text;
}
};
class Eval : public Directive
{
// Class for @{} statements
@ -62,111 +65,123 @@ namespace macro
// Treated as such as the output is only to be interpreted
private:
const ExpressionPtr expr;
public:
Eval(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
Directive(move(location_arg)), expr {move(expr_arg)}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class Include : public Directive
{
private:
const ExpressionPtr expr;
public:
Include(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
Directive(move(location_arg)), expr {move(expr_arg)}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class IncludePath : public Directive
{
private:
const ExpressionPtr expr;
public:
IncludePath(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
Directive(move(location_arg)), expr {move(expr_arg)}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class Define : public Directive
{
private:
const VariablePtr var;
const FunctionPtr func;
const ExpressionPtr value;
public:
Define(VariablePtr var_arg,
ExpressionPtr value_arg,
Tokenizer::location location_arg) :
Directive(move(location_arg)), var{move(var_arg)}, value{move(value_arg)} { }
Define(FunctionPtr func_arg,
ExpressionPtr value_arg,
Tokenizer::location location_arg) :
Directive(move(location_arg)), func{move(func_arg)}, value{move(value_arg)} { }
Define(VariablePtr var_arg, ExpressionPtr value_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), var {move(var_arg)}, value {move(value_arg)}
{
}
Define(FunctionPtr func_arg, ExpressionPtr value_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), func {move(func_arg)}, value {move(value_arg)}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class Echo : public Directive
{
private:
const ExpressionPtr expr;
public:
Echo(ExpressionPtr expr_arg,
Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
Echo(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr {move(expr_arg)}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class Error : public Directive
{
private:
const ExpressionPtr expr;
public:
Error(ExpressionPtr expr_arg,
Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
Error(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr {move(expr_arg)}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class EchoMacroVars : public Directive
{
private:
const bool save;
const vector<string> vars;
public:
EchoMacroVars(bool save_arg,
Tokenizer::location location_arg) :
Directive(move(location_arg)), save{save_arg} { }
EchoMacroVars(bool save_arg, vector<string> vars_arg,
Tokenizer::location location_arg) :
Directive(move(location_arg)), save{save_arg}, vars{move(vars_arg)} { }
EchoMacroVars(bool save_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), save {save_arg}
{
}
EchoMacroVars(bool save_arg, vector<string> vars_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), save {save_arg}, vars {move(vars_arg)}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class For : public Directive
{
private:
const vector<VariablePtr> index_vec;
const ExpressionPtr index_vals;
const vector<DirectivePtr> statements;
public:
For(vector<VariablePtr> index_vec_arg,
ExpressionPtr index_vals_arg,
vector<DirectivePtr> statements_arg,
Tokenizer::location location_arg) :
Directive(move(location_arg)), index_vec{move(index_vec_arg)},
index_vals{move(index_vals_arg)}, statements{move(statements_arg)} { }
For(vector<VariablePtr> index_vec_arg, ExpressionPtr index_vals_arg,
vector<DirectivePtr> statements_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)),
index_vec {move(index_vec_arg)},
index_vals {move(index_vals_arg)},
statements {move(statements_arg)}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class If : public Directive
{
protected:
@ -180,16 +195,21 @@ namespace macro
*/
const vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body;
const bool ifdef, ifndef;
public:
If(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
Tokenizer::location location_arg,
bool ifdef_arg = false, bool ifndef_arg = false) :
Directive(move(location_arg)), expr_and_body{move(expr_and_body_arg)},
ifdef{ifdef_arg}, ifndef{ifndef_arg} { }
Tokenizer::location location_arg, bool ifdef_arg = false, bool ifndef_arg = false) :
Directive(move(location_arg)),
expr_and_body {move(expr_and_body_arg)},
ifdef {ifdef_arg},
ifndef {ifndef_arg}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
protected:
void interpretBody(const vector<DirectivePtr> &body, ostream &output,
Environment &env, vector<filesystem::path> &paths);
void interpretBody(const vector<DirectivePtr>& body, ostream& output, Environment& env,
vector<filesystem::path>& paths);
};
class Ifdef : public If
@ -197,16 +217,19 @@ namespace macro
public:
Ifdef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
Tokenizer::location location_arg) :
If(move(expr_and_body_arg), move(location_arg), true, false) { }
If(move(expr_and_body_arg), move(location_arg), true, false)
{
}
};
class Ifndef : public If
{
public:
Ifndef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
Tokenizer::location location_arg) :
If(move(expr_and_body_arg), move(location_arg), false, true) { }
If(move(expr_and_body_arg), move(location_arg), false, true)
{
}
};
}
#endif

View File

@ -25,9 +25,9 @@
using namespace macro;
void
Driver::parse(const string &file_arg, const istream &modfile,
bool debug, const vector<pair<string, string>> &defines,
Environment &env, vector<filesystem::path> &paths, ostream &output)
Driver::parse(const string& file_arg, const istream& modfile, bool debug,
const vector<pair<string, string>>& defines, Environment& env,
vector<filesystem::path>& paths, ostream& output)
{
file = file_arg;
@ -54,8 +54,7 @@ Driver::parse(const string &file_arg, const istream &modfile,
parser.parse();
// Interpret parsed statements
for (bool printLine{true};
const auto &statement : statements)
for (bool printLine {true}; const auto& statement : statements)
{
if (exchange(printLine, false))
statement->printLineInfo(output);

View File

@ -24,9 +24,9 @@
# error Impossible to include both ../ParsingDriver.hh and Driver.hh
#endif
#include "Parser.hh"
#include "Environment.hh"
#include "Expressions.hh"
#include "Parser.hh"
#include <stack>
@ -46,7 +46,9 @@ namespace macro
class TokenizerFlex : public TokenizerFlexLexer
{
public:
TokenizerFlex(istream *in) : TokenizerFlexLexer{in} { }
TokenizerFlex(istream* in) : TokenizerFlexLexer {in}
{
}
TokenizerFlex(const TokenizerFlex&) = delete;
TokenizerFlex& operator=(const TokenizerFlex&) = delete;
@ -63,6 +65,7 @@ namespace macro
private:
vector<DirectivePtr> statements;
stack<vector<DirectivePtr>> directive_stack;
public:
Driver() = default;
Driver(const Driver&) = delete;
@ -76,9 +79,9 @@ namespace macro
//! Starts parsing a file, modifies `env`, `paths` and `output`
//! as they are modified by various macro directives
void parse(const string &file, const istream &modfile,
bool debug, const vector<pair<string, string>> &defines,
Environment &env, vector<filesystem::path> &paths, ostream &output);
void parse(const string& file, const istream& modfile, bool debug,
const vector<pair<string, string>>& defines, Environment& env,
vector<filesystem::path>& paths, ostream& output);
//! Name of main file being parsed (for error reporting purposes)
string file;

View File

@ -101,7 +101,8 @@ Environment::isFunctionDefined(const string &name) const noexcept
}
void
Environment::print(ostream &output, const vector<string> &vars, const optional<int> &line, bool save) const
Environment::print(ostream& output, const vector<string>& vars, const optional<int>& line,
bool save) const
{
if (!save && !variables.empty())
output << "Macro Variables:" << endl;
@ -130,11 +131,11 @@ Environment::print(ostream &output, const vector<string> &vars, const optional<i
}
void
Environment::printVariable(ostream &output, const string &name, const optional<int> &line, bool save) const
Environment::printVariable(ostream& output, const string& name, const optional<int>& line,
bool save) const
{
assert(!save || line);
output << (save ? "options_.macrovars_line_" + to_string(*line) + "." : " ")
<< name << " = ";
output << (save ? "options_.macrovars_line_" + to_string(*line) + "." : " ") << name << " = ";
getVariable(name)->eval(const_cast<Environment&>(*this))->print(output, save);
if (save)
output << ";";
@ -142,7 +143,8 @@ Environment::printVariable(ostream &output, const string &name, const optional<i
}
void
Environment::printFunction(ostream &output, const tuple<FunctionPtr, ExpressionPtr> &function, const optional<int> &line, bool save) const
Environment::printFunction(ostream& output, const tuple<FunctionPtr, ExpressionPtr>& function,
const optional<int>& line, bool save) const
{
assert(!save || line);
output << (save ? "options_.macrovars_line_" + to_string(*line) + ".function." : " ");

View File

@ -23,8 +23,8 @@
#include "ForwardDeclarationsAndEnums.hh"
#include <map>
#include <vector>
#include <optional>
#include <vector>
namespace macro
{
@ -34,9 +34,12 @@ namespace macro
const Environment* parent {nullptr};
map<string, ExpressionPtr> variables;
map<string, tuple<FunctionPtr, ExpressionPtr>> functions;
public:
Environment() = default;
Environment(const Environment *parent_arg) : parent{parent_arg} { }
Environment(const Environment* parent_arg) : parent {parent_arg}
{
}
void define(VariablePtr var, ExpressionPtr value);
void define(FunctionPtr func, ExpressionPtr value);
ExpressionPtr getVariable(const string& name) const;
@ -44,13 +47,17 @@ namespace macro
codes::BaseType getType(const string& name) const;
bool isVariableDefined(const string& name) const noexcept;
bool isFunctionDefined(const string& name) const noexcept;
bool isSymbolDefined(const string &name) const noexcept
bool
isSymbolDefined(const string& name) const noexcept
{
return isVariableDefined(name) || isFunctionDefined(name);
}
void print(ostream &output, const vector<string> &vars, const optional<int> &line = nullopt, bool save = false) const;
void printVariable(ostream &output, const string &name, const optional<int> &line, bool save) const;
void printFunction(ostream &output, const tuple<FunctionPtr, ExpressionPtr> &function, const optional<int> &line, bool save) const;
void print(ostream& output, const vector<string>& vars, const optional<int>& line = nullopt,
bool save = false) const;
void printVariable(ostream& output, const string& name, const optional<int>& line,
bool save) const;
void printFunction(ostream& output, const tuple<FunctionPtr, ExpressionPtr>& function,
const optional<int>& line, bool save) const;
size_t
size() const noexcept
{

View File

@ -17,8 +17,8 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <utility>
#include <numbers>
#include <utility>
#include "Expressions.hh"
@ -241,7 +241,9 @@ Real::normpdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const
auto btp22 = dynamic_pointer_cast<Real>(btp2);
if (!btp12 || !btp22)
throw StackTrace("Type mismatch for operands of `normpdf` operator");
return make_shared<Real>((1/(btp22->value*std::sqrt(2*numbers::pi)*std::exp(pow((value-btp12->value)/btp22->value, 2)/2))));
return make_shared<Real>((1
/ (btp22->value * std::sqrt(2 * numbers::pi)
* std::exp(pow((value - btp12->value) / btp22->value, 2) / 2))));
}
RealPtr
@ -251,7 +253,8 @@ Real::normcdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const
auto btp22 = dynamic_pointer_cast<Real>(btp2);
if (!btp12 || !btp22)
throw StackTrace("Type mismatch for operands of `normpdf` operator");
return make_shared<Real>((0.5*(1+std::erf((value-btp12->value)/btp22->value/numbers::sqrt2))));
return make_shared<Real>(
(0.5 * (1 + std::erf((value - btp12->value) / btp22->value / numbers::sqrt2))));
}
BaseTypePtr
@ -657,12 +660,15 @@ Variable::eval(Environment &env) const
vector<int> ind;
for (const auto& it : map->getValue())
// Necessary to handle indexes like: y[1:2,2]
// In general this evaluates to [[1:2],2] but when subscripting we want to expand it to [1,2,2]
// In general this evaluates to [[1:2],2] but when subscripting we want to expand it to
// [1,2,2]
if (auto db = dynamic_pointer_cast<Real>(it); db)
{
if (!*(db->isinteger()))
throw StackTrace("variable", "When indexing a variable you must pass "
"an int or an int array", location);
throw StackTrace("variable",
"When indexing a variable you must pass "
"an int or an int array",
location);
ind.emplace_back(*db);
}
else if (dynamic_pointer_cast<Array>(it))
@ -670,16 +676,22 @@ Variable::eval(Environment &env) const
if (db = dynamic_pointer_cast<Real>(it1); db)
{
if (!*(db->isinteger()))
throw StackTrace("variable", "When indexing a variable you must pass "
"an int or an int array", location);
throw StackTrace("variable",
"When indexing a variable you must pass "
"an int or an int array",
location);
ind.emplace_back(*db);
}
else
throw StackTrace("variable", "You cannot index a variable with a "
"nested array", location);
throw StackTrace("variable",
"You cannot index a variable with a "
"nested array",
location);
else
throw StackTrace("variable", "You can only index a variable with an int or "
"an int array", location);
throw StackTrace("variable",
"You can only index a variable with an int or "
"an int array",
location);
switch (env.getType(name))
{
@ -693,8 +705,7 @@ Variable::eval(Environment &env) const
throw StackTrace("variable", "Internal Error: Range: should not arrive here", location);
case codes::BaseType::String:
{
string orig_string
= dynamic_pointer_cast<String>(env.getVariable(name))->to_string();
string orig_string = dynamic_pointer_cast<String>(env.getVariable(name))->to_string();
string retvals;
for (auto it : ind)
try
@ -749,8 +760,10 @@ Function::eval(Environment &env) const
}
if (func->args.size() != args.size())
throw StackTrace("Function", "The number of arguments used to call " + name
+" does not match the number used in its definition", location);
throw StackTrace("Function",
"The number of arguments used to call " + name
+ " does not match the number used in its definition",
location);
try
{
@ -970,8 +983,10 @@ Comprehension::eval(Environment &env) const
vp = dynamic_pointer_cast<Variable>(c_vars);
mt = dynamic_pointer_cast<Tuple>(c_vars);
if ((!vp && !mt) || (vp && mt))
throw StackTrace("Comprehension", "the loop variables must be either "
"a tuple or a variable", location);
throw StackTrace("Comprehension",
"the loop variables must be either "
"a tuple or a variable",
location);
}
catch (StackTrace& ex)
{
@ -985,27 +1000,32 @@ Comprehension::eval(Environment &env) const
auto btp = dynamic_pointer_cast<BaseType>(input_set->at(i));
if (vp)
env.define(vp, btp);
else
if (btp->getType() == codes::BaseType::Tuple)
else if (btp->getType() == codes::BaseType::Tuple)
{
auto mt2 = dynamic_pointer_cast<Tuple>(btp);
if (mt->size() != mt2->size())
throw StackTrace("Comprehension", "The number of elements in the input "
throw StackTrace("Comprehension",
"The number of elements in the input "
" set tuple are not the same as the number of elements in "
"the output expression tuple", location);
"the output expression tuple",
location);
for (size_t j = 0; j < mt->size(); j++)
{
auto vp2 = dynamic_pointer_cast<Variable>(mt->at(j));
if (!vp2)
throw StackTrace("Comprehension", "Output expression tuple must be "
"comprised of variable names", location);
throw StackTrace("Comprehension",
"Output expression tuple must be "
"comprised of variable names",
location);
env.define(vp2, mt2->at(j));
}
}
else
throw StackTrace("Comprehension", "assigning to tuple in output expression "
"but input expression does not contain tuples", location);
throw StackTrace("Comprehension",
"assigning to tuple in output expression "
"but input expression does not contain tuples",
location);
if (!c_when)
if (!c_expr)
@ -1227,9 +1247,11 @@ TrinaryOp::to_string() const noexcept
switch (op_code)
{
case codes::TrinaryOp::normpdf:
return "normpdf(" + arg1->to_string() + ", " + arg2->to_string() + ", " + arg3->to_string() + ")";
return "normpdf(" + arg1->to_string() + ", " + arg2->to_string() + ", " + arg3->to_string()
+ ")";
case codes::TrinaryOp::normcdf:
return "normcdf(" + arg1->to_string() + ", " + arg2->to_string() + ", " + arg3->to_string() + ")";
return "normcdf(" + arg1->to_string() + ", " + arg2->to_string() + ", " + arg3->to_string()
+ ")";
}
// Suppress GCC warning
exit(EXIT_FAILURE);
@ -1250,17 +1272,14 @@ Comprehension::to_string() const noexcept
void
String::print(ostream& output, bool matlab_output) const noexcept
{
output << (matlab_output ? "'" : R"(")")
<< value
<< (matlab_output ? "'" : R"(")");
output << (matlab_output ? "'" : R"(")") << value << (matlab_output ? "'" : R"(")");
}
void
Array::print(ostream& output, bool matlab_output) const noexcept
{
output << (matlab_output ? "{" : "[");
for (bool printed_something{false};
auto e : arr)
for (bool printed_something {false}; auto e : arr)
{
if (exchange(printed_something, true))
output << ", ";
@ -1273,8 +1292,7 @@ void
Tuple::print(ostream& output, bool matlab_output) const noexcept
{
output << (matlab_output ? "{" : "(");
for (bool printed_something{false};
auto e : tup)
for (bool printed_something {false}; auto e : tup)
{
if (exchange(printed_something, true))
output << ", ";
@ -1287,8 +1305,7 @@ void
Function::printArgs(ostream& output) const noexcept
{
output << "(";
for (bool printed_something{false};
auto e : args)
for (bool printed_something {false}; auto e : args)
{
if (exchange(printed_something, true))
output << ", ";
@ -1423,24 +1440,18 @@ UnaryOp::print(ostream &output, bool matlab_output) const noexcept
arg->print(output, matlab_output);
if (op_code != codes::UnaryOp::cast_bool
&& op_code != codes::UnaryOp::cast_real
&& op_code != codes::UnaryOp::cast_string
&& op_code != codes::UnaryOp::cast_tuple
&& op_code != codes::UnaryOp::cast_array
&& op_code != codes::UnaryOp::logical_not
&& op_code != codes::UnaryOp::unary_plus
&& op_code != codes::UnaryOp::unary_minus)
if (op_code != codes::UnaryOp::cast_bool && op_code != codes::UnaryOp::cast_real
&& op_code != codes::UnaryOp::cast_string && op_code != codes::UnaryOp::cast_tuple
&& op_code != codes::UnaryOp::cast_array && op_code != codes::UnaryOp::logical_not
&& op_code != codes::UnaryOp::unary_plus && op_code != codes::UnaryOp::unary_minus)
output << ")";
}
void
BinaryOp::print(ostream& output, bool matlab_output) const noexcept
{
if (op_code == codes::BinaryOp::set_union
|| op_code == codes::BinaryOp::set_intersection
|| op_code == codes::BinaryOp::max
|| op_code == codes::BinaryOp::min
if (op_code == codes::BinaryOp::set_union || op_code == codes::BinaryOp::set_intersection
|| op_code == codes::BinaryOp::max || op_code == codes::BinaryOp::min
|| op_code == codes::BinaryOp::mod)
{
switch (op_code)

File diff suppressed because it is too large Load Diff