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,14 +17,14 @@
* 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"
BytecodeWriter::BytecodeWriter(const filesystem::path &filename)
BytecodeWriter::BytecodeWriter(const filesystem::path& filename)
{
open(filename, ios::out | ios::binary);
if (!is_open())
@ -35,14 +35,13 @@ BytecodeWriter::BytecodeWriter(const filesystem::path &filename)
}
template<>
BytecodeWriter &
operator<<(BytecodeWriter &code_file, const FCALL_ &instr)
BytecodeWriter&
operator<<(BytecodeWriter& code_file, const FCALL_& instr)
{
code_file.instructions_positions.push_back(code_file.tellp());
auto write_member = [&code_file](const auto &member)
{
code_file.write(reinterpret_cast<const char *>(&member), sizeof member);
auto write_member = [&code_file](const auto& member) {
code_file.write(reinterpret_cast<const char*>(&member), sizeof member);
};
write_member(instr.op_code);
@ -56,24 +55,23 @@ operator<<(BytecodeWriter &code_file, const FCALL_ &instr)
int size = static_cast<int>(instr.func_name.size());
write_member(size);
code_file.write(instr.func_name.c_str(), size+1);
code_file.write(instr.func_name.c_str(), size + 1);
size = static_cast<int>(instr.arg_func_name.size());
write_member(size);
code_file.write(instr.arg_func_name.c_str(), size+1);
code_file.write(instr.arg_func_name.c_str(), size + 1);
return code_file;
}
template<>
BytecodeWriter &
operator<<(BytecodeWriter &code_file, const FBEGINBLOCK_ &instr)
BytecodeWriter&
operator<<(BytecodeWriter& code_file, const FBEGINBLOCK_& instr)
{
code_file.instructions_positions.push_back(code_file.tellp());
auto write_member = [&code_file](const auto &member)
{
code_file.write(reinterpret_cast<const char *>(&member), sizeof member);
auto write_member = [&code_file](const auto& member) {
code_file.write(reinterpret_cast<const char*>(&member), sizeof member);
};
write_member(instr.op_code);

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"
@ -33,77 +33,91 @@ using namespace std;
// The different opcodes of bytecode
enum class Tags
{
FLDZ, // Loads a zero onto the stack
FLDC, // Loads a constant term onto the stack
{
FLDZ, // Loads a zero onto the stack
FLDC, // Loads a constant term onto the stack
FDIMT, // Defines the number of temporary terms - dynamic context (the period has to be indicated)
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)
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)
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)
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
FLDR, // Loads a residual onto the stack
FSTPR, // Stores a residual from the stack
FSTPG, // Stores a derivative from the stack
FSTPG2, // Stores a derivative matrix for a static model from the stack
FSTPG3, // Stores a derivative matrix for a dynamic model from the stack
FSTPG, // Stores a derivative from the stack
FSTPG2, // Stores a derivative matrix for a static model from the stack
FSTPG3, // Stores a derivative matrix for a dynamic model from the stack
FUNARY, // A unary operator
FBINARY, // A binary operator
FTRINARY, // A trinary operator
FUNARY, // A unary operator
FBINARY, // A binary operator
FTRINARY, // A trinary operator
FJMPIFEVAL, // Jump if evaluate = true
FJMP, // Jump
FJMPIFEVAL, // Jump if evaluate = true
FJMP, // Jump
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
FEND, // Marks the end of the model code
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
FEND, // Marks the end of the model code
FNUMEXPR, // Stores the expression type and references
FNUMEXPR, // Stores the expression type and references
FCALL, // Call an external function
FLDTEF, // Loads the result of an external function onto the stack
FSTPTEF, // Stores the result of an external function from the stack
FLDTEFD, // Loads the result of the 1st derivative of an external function onto the stack
FSTPTEFD, // Stores the result of the 1st derivative of an external function from the stack
FLDTEFDD, // Loads the result of the 2nd derivative of an external function onto the stack
FSTPTEFDD // Stores the result of the 2nd derivative of an external function from the stack
};
FCALL, // Call an external function
FLDTEF, // Loads the result of an external function onto the stack
FSTPTEF, // Stores the result of an external function from the stack
FLDTEFD, // Loads the result of the 1st derivative of an external function onto the stack
FSTPTEFD, // Stores the result of the 1st derivative of an external function from the stack
FLDTEFDD, // Loads the result of the 2nd derivative of an external function onto the stack
FSTPTEFDD // Stores the result of the 2nd derivative of an external function from the stack
};
enum class ExpressionType
{
TemporaryTerm,
ModelEquation,
FirstEndoDerivative,
FirstExoDerivative,
FirstExodetDerivative,
};
{
TemporaryTerm,
ModelEquation,
FirstEndoDerivative,
FirstExoDerivative,
FirstExodetDerivative,
};
enum class ExternalFunctionCallType
{
levelWithoutDerivative,
levelWithFirstDerivative,
levelWithFirstAndSecondDerivative,
separatelyProvidedFirstDerivative,
numericalFirstDerivative,
separatelyProvidedSecondDerivative,
numericalSecondDerivative
};
{
levelWithoutDerivative,
levelWithFirstDerivative,
levelWithFirstAndSecondDerivative,
separatelyProvidedFirstDerivative,
numericalFirstDerivative,
separatelyProvidedSecondDerivative,
numericalSecondDerivative
};
struct Block_contain_type
{
@ -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}
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}
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;
@ -198,41 +223,41 @@ protected:
class FLDZ_ final : public BytecodeInstruction
{
public:
FLDZ_() : BytecodeInstruction{Tags::FLDZ}
FLDZ_() : BytecodeInstruction {Tags::FLDZ}
{
};
}
};
class FEND_ final : public BytecodeInstruction
{
public:
FEND_() : BytecodeInstruction{Tags::FEND}
FEND_() : BytecodeInstruction {Tags::FEND}
{
};
}
};
class FENDBLOCK_ final : public BytecodeInstruction
{
public:
FENDBLOCK_() : BytecodeInstruction{Tags::FENDBLOCK}
FENDBLOCK_() : BytecodeInstruction {Tags::FENDBLOCK}
{
};
}
};
class FENDEQU_ final : public BytecodeInstruction
{
public:
FENDEQU_() : BytecodeInstruction{Tags::FENDEQU}
FENDEQU_() : BytecodeInstruction {Tags::FENDEQU}
{
};
}
};
class FDIMT_ final : public TagWithOneArgument<int>
{
public:
explicit FDIMT_(int size_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FDIMT, size_arg}
explicit FDIMT_(int size_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FDIMT, size_arg}
{
};
}
int
get_size()
{
@ -243,9 +268,9 @@ public:
class FDIMST_ final : public TagWithOneArgument<int>
{
public:
explicit FDIMST_(int size_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FDIMST, size_arg}
explicit FDIMST_(int size_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FDIMST, size_arg}
{
};
}
int
get_size()
{
@ -256,9 +281,9 @@ public:
class FLDC_ final : public TagWithOneArgument<double>
{
public:
explicit FLDC_(double value_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FLDC, value_arg}
explicit FLDC_(double value_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FLDC, value_arg}
{
};
}
double
get_value()
{
@ -269,9 +294,9 @@ public:
class FLDU_ final : public TagWithOneArgument<int>
{
public:
explicit FLDU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FLDU, pos_arg}
explicit FLDU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FLDU, pos_arg}
{
};
}
int
get_pos()
{
@ -282,9 +307,9 @@ public:
class FLDSU_ final : public TagWithOneArgument<int>
{
public:
explicit FLDSU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FLDSU, pos_arg}
explicit FLDSU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FLDSU, pos_arg}
{
};
}
int
get_pos()
{
@ -295,9 +320,9 @@ public:
class FLDR_ final : public TagWithOneArgument<int>
{
public:
explicit FLDR_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FLDR, pos_arg}
explicit FLDR_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FLDR, pos_arg}
{
};
}
int
get_pos()
{
@ -308,9 +333,9 @@ public:
class FLDT_ final : public TagWithOneArgument<int>
{
public:
explicit FLDT_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FLDT, pos_arg}
explicit FLDT_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FLDT, pos_arg}
{
};
}
int
get_pos()
{
@ -321,9 +346,9 @@ public:
class FLDST_ final : public TagWithOneArgument<int>
{
public:
explicit FLDST_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FLDST, pos_arg}
explicit FLDST_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FLDST, pos_arg}
{
};
}
int
get_pos()
{
@ -334,9 +359,9 @@ public:
class FSTPT_ final : public TagWithOneArgument<int>
{
public:
explicit FSTPT_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPT, pos_arg}
explicit FSTPT_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPT, pos_arg}
{
};
}
int
get_pos()
{
@ -347,9 +372,9 @@ public:
class FSTPST_ final : public TagWithOneArgument<int>
{
public:
explicit FSTPST_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPST, pos_arg}
explicit FSTPST_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPST, pos_arg}
{
};
}
int
get_pos()
{
@ -360,9 +385,9 @@ public:
class FSTPR_ final : public TagWithOneArgument<int>
{
public:
explicit FSTPR_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPR, pos_arg}
explicit FSTPR_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPR, pos_arg}
{
};
}
int
get_pos()
{
@ -373,9 +398,9 @@ public:
class FSTPU_ final : public TagWithOneArgument<int>
{
public:
explicit FSTPU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPU, pos_arg}
explicit FSTPU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPU, pos_arg}
{
};
}
int
get_pos()
{
@ -386,9 +411,9 @@ public:
class FSTPSU_ final : public TagWithOneArgument<int>
{
public:
explicit FSTPSU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPSU, pos_arg}
explicit FSTPSU_(int pos_arg) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPSU, pos_arg}
{
};
}
int
get_pos()
{
@ -399,9 +424,9 @@ public:
class FSTPG_ final : public TagWithOneArgument<int>
{
public:
explicit FSTPG_(int pos_arg) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPG, pos_arg}
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()
{
@ -510,9 +542,9 @@ public:
class FJMP_ final : public TagWithOneArgument<int>
{
public:
explicit FJMP_(int arg_pos) : TagWithOneArgument::TagWithOneArgument{Tags::FJMP, arg_pos}
explicit FJMP_(int arg_pos) : TagWithOneArgument::TagWithOneArgument {Tags::FJMP, arg_pos}
{
};
}
int
get_pos()
{
@ -523,9 +555,9 @@ public:
class FLDTEF_ final : public TagWithOneArgument<int>
{
public:
explicit FLDTEF_(int number) : TagWithOneArgument::TagWithOneArgument{Tags::FLDTEF, number}
explicit FLDTEF_(int number) : TagWithOneArgument::TagWithOneArgument {Tags::FLDTEF, number}
{
};
}
int
get_number()
{
@ -536,9 +568,9 @@ public:
class FSTPTEF_ final : public TagWithOneArgument<int>
{
public:
explicit FSTPTEF_(int number) : TagWithOneArgument::TagWithOneArgument{Tags::FSTPTEF, number}
explicit FSTPTEF_(int number) : TagWithOneArgument::TagWithOneArgument {Tags::FSTPTEF, number}
{
};
}
int
get_number()
{
@ -549,9 +581,9 @@ public:
class FLDTEFD_ final : public TagWithTwoArguments<int, int>
{
public:
FLDTEFD_(int indx, int row) : TagWithTwoArguments::TagWithTwoArguments{Tags::FLDTEFD, indx, row}
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()
{
@ -686,9 +724,9 @@ class FLDV_ final : public TagWithThreeArguments<SymbolType, int, int>
{
public:
FLDV_(SymbolType type_arg, int pos_arg, int lead_lag_arg) :
TagWithThreeArguments::TagWithThreeArguments{Tags::FLDV, type_arg, pos_arg, lead_lag_arg}
TagWithThreeArguments::TagWithThreeArguments {Tags::FLDV, type_arg, pos_arg, lead_lag_arg}
{
};
}
SymbolType
get_type()
{
@ -710,9 +748,9 @@ class FSTPV_ final : public TagWithThreeArguments<SymbolType, int, int>
{
public:
FSTPV_(SymbolType type_arg, int pos_arg, int lead_lag_arg) :
TagWithThreeArguments::TagWithThreeArguments{Tags::FSTPV, type_arg, pos_arg, lead_lag_arg}
TagWithThreeArguments::TagWithThreeArguments {Tags::FSTPV, type_arg, pos_arg, lead_lag_arg}
{
};
}
SymbolType
get_type()
{
@ -733,32 +771,33 @@ public:
class FCALL_ final : public BytecodeInstruction
{
template<typename B>
friend BytecodeWriter &operator<<(BytecodeWriter &code_file, const B &instr);
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};
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) :
BytecodeInstruction{Tags::FCALL},
nb_output_arguments{nb_output_arguments_arg},
nb_input_arguments{nb_input_arguments_arg},
indx{indx_arg},
func_name{move(func_name_arg)},
call_type{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},
indx {indx_arg},
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;
};
@ -774,17 +813,17 @@ public:
int size;
read_member(size);
func_name = code;
code += size+1;
code += size + 1;
read_member(size);
arg_func_name = code;
code += size+1;
code += size + 1;
}
string
get_function_name()
{
//printf("get_function_name => func_name=%s\n",func_name.c_str());fflush(stdout);
// printf("get_function_name => func_name=%s\n",func_name.c_str());fflush(stdout);
return func_name;
};
int
@ -853,34 +892,36 @@ 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
int lag1; // For derivatives, lead/lag of the derivation variable
public:
FNUMEXPR_(const ExpressionType expression_type_arg, int equation_arg) :
BytecodeInstruction{Tags::FNUMEXPR},
expression_type{expression_type_arg},
equation{equation_arg},
dvariable1{0},
lag1{0}
BytecodeInstruction {Tags::FNUMEXPR},
expression_type {expression_type_arg},
equation {equation_arg},
dvariable1 {0},
lag1 {0}
{
};
}
FNUMEXPR_(const ExpressionType expression_type_arg, int equation_arg, int dvariable1_arg) :
BytecodeInstruction{Tags::FNUMEXPR},
expression_type{expression_type_arg},
equation{equation_arg},
dvariable1{dvariable1_arg},
lag1{0}
BytecodeInstruction {Tags::FNUMEXPR},
expression_type {expression_type_arg},
equation {equation_arg},
dvariable1 {dvariable1_arg},
lag1 {0}
{
};
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}
}
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()
{
@ -906,67 +947,70 @@ public:
class FBEGINBLOCK_ final : public BytecodeInstruction
{
template<typename B>
friend BytecodeWriter &operator<<(BytecodeWriter &code_file, const B &instr);
friend BytecodeWriter& operator<<(BytecodeWriter& code_file, const B& instr);
private:
int size{0};
int size {0};
BlockSimulationType type;
vector<int> variable;
vector<int> equation;
vector<int> exogenous;
vector<int> det_exogenous;
bool is_linear{false};
bool is_linear {false};
vector<Block_contain_type> Block_Contain_;
int u_count_int{0};
int nb_col_jacob{0};
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)},
exogenous{move(exogenous_arg)},
det_exogenous{move(det_exogenous_arg)},
is_linear{is_linear_arg},
u_count_int{u_count_int_arg},
nb_col_jacob{nb_col_jacob_arg},
det_exo_size{det_exo_size_arg},
exo_size{exo_size_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)},
exogenous {move(exogenous_arg)},
det_exogenous {move(det_exogenous_arg)},
is_linear {is_linear_arg},
u_count_int {u_count_int_arg},
nb_col_jacob {nb_col_jacob_arg},
det_exo_size {det_exo_size_arg},
exo_size {exo_size_arg}
{
}
// 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) :
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)},
is_linear{is_linear_arg},
u_count_int{u_count_int_arg},
nb_col_jacob{nb_col_jacob_arg},
det_exo_size{0},
exo_size{0}
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)},
is_linear {is_linear_arg},
u_count_int {u_count_int_arg},
nb_col_jacob {nb_col_jacob_arg},
det_exo_size {0},
exo_size {0}
{
}
/* 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;
};
@ -1062,12 +1106,14 @@ public:
class BytecodeWriter : private ofstream
{
template<typename B>
friend BytecodeWriter &operator<<(BytecodeWriter &code_file, const B &instr);
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);
BytecodeWriter(const filesystem::path& filename);
// Returns the number of the next instruction to be written
int
getInstructionCounter() const
@ -1079,7 +1125,7 @@ public:
occupies exactly as many bytes as the former one. */
template<typename B>
void
overwriteInstruction(int instruction_number, const B &new_instruction)
overwriteInstruction(int instruction_number, const B& new_instruction)
{
seekp(instructions_positions.at(instruction_number));
*this << new_instruction;
@ -1091,18 +1137,18 @@ public:
// Overloads of operator<< for writing bytecode instructions
template<typename B>
BytecodeWriter &
operator<<(BytecodeWriter &code_file, const B &instr)
BytecodeWriter&
operator<<(BytecodeWriter& code_file, const B& instr)
{
code_file.instructions_positions.push_back(code_file.tellp());
code_file.write(reinterpret_cast<const char *>(&instr), sizeof(B));
code_file.write(reinterpret_cast<const char*>(&instr), sizeof(B));
return code_file;
}
template<>
BytecodeWriter &operator<<(BytecodeWriter &code_file, const FCALL_ &instr);
BytecodeWriter& operator<<(BytecodeWriter& code_file, const FCALL_& instr);
template<>
BytecodeWriter &operator<<(BytecodeWriter &code_file, const FBEGINBLOCK_ &instr);
BytecodeWriter& operator<<(BytecodeWriter& code_file, const FBEGINBLOCK_& instr);
#endif // _BYTECODE_HH

View File

@ -21,127 +21,134 @@
#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
exogenous = 1, //!< Exogenous
exogenousDet = 2, //!< Exogenous deterministic
parameter = 4, //!< Parameter
modelLocalVariable = 10, //!< Local variable whose scope is model (pound expression)
modFileLocalVariable = 11, //!< Local variable whose scope is mod file (model excluded)
externalFunction = 12, //!< External (user-defined) function
trend = 13, //!< Trend variable
statementDeclaredVariable = 14, //!< Local variable assigned within a Statement (see subsample statement for example)
logTrend = 15, //!< Log-trend variable
unusedEndogenous = 16, //!< Type to mark unused endogenous variables when `nostrict` option is passed
{
endogenous = 0, //!< Endogenous
exogenous = 1, //!< Exogenous
exogenousDet = 2, //!< Exogenous deterministic
parameter = 4, //!< Parameter
modelLocalVariable = 10, //!< Local variable whose scope is model (pound expression)
modFileLocalVariable = 11, //!< Local variable whose scope is mod file (model excluded)
externalFunction = 12, //!< External (user-defined) function
trend = 13, //!< Trend variable
statementDeclaredVariable
= 14, //!< Local variable assigned within a Statement (see subsample statement for example)
logTrend = 15, //!< Log-trend variable
unusedEndogenous
= 16, //!< Type to mark unused endogenous variables when `nostrict` option is passed
// Value 17 is unused for the time being (but could be reused)
// Value 17 is unused for the time being (but could be reused)
epilogue = 18, //!< Variables created in epilogue block
excludedVariable = 19 //!< Variable excluded via model_remove/var_remove/include_eqs/exclude_eqs
};
epilogue = 18, //!< Variables created in epilogue block
excludedVariable = 19 //!< Variable excluded via model_remove/var_remove/include_eqs/exclude_eqs
};
enum class UnaryOpcode
{
uminus,
exp,
log,
log10,
cos,
sin,
tan,
acos,
asin,
atan,
cosh,
sinh,
tanh,
acosh,
asinh,
atanh,
sqrt,
cbrt,
abs,
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
expectation,
erf,
erfc,
diff,
adl
};
{
uminus,
exp,
log,
log10,
cos,
sin,
tan,
acos,
asin,
atan,
cosh,
sinh,
tanh,
acosh,
asinh,
atanh,
sqrt,
cbrt,
abs,
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
expectation,
erf,
erfc,
diff,
adl
};
enum class BinaryOpcode
{
plus,
minus,
times,
divide,
power,
powerDeriv, // for the derivative of the power function (see trac ticket #78)
equal,
max,
min,
less,
greater,
lessEqual,
greaterEqual,
equalEqual,
different
};
{
plus,
minus,
times,
divide,
power,
powerDeriv, // for the derivative of the power function (see trac ticket #78)
equal,
max,
min,
less,
greater,
lessEqual,
greaterEqual,
equalEqual,
different
};
// Small number value used when evaluating powerDeriv opcodes.
// Put here instead of inside BinaryOpNode class, because needed by bytecode MEX.
constexpr double power_deriv_near_zero{1e-12};
constexpr double power_deriv_near_zero {1e-12};
enum class TrinaryOpcode
{
normcdf,
normpdf
};
{
normcdf,
normpdf
};
enum class PriorDistributions
{
noShape = 0,
beta = 1,
gamma = 2,
normal = 3,
invGamma = 4,
invGamma1 = 4,
uniform = 5,
invGamma2 = 6,
dirichlet = 7,
weibull = 8
};
{
noShape = 0,
beta = 1,
gamma = 2,
normal = 3,
invGamma = 4,
invGamma1 = 4,
uniform = 5,
invGamma2 = 6,
dirichlet = 7,
weibull = 8
};
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)
solve //!< No simple evaluation of the equation, it has to be solved
};
{
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
};
enum class BlockSimulationType
{
evaluateForward = 1, //!< Simple evaluation, normalized variable on left-hand side, forward
evaluateBackward, //!< Simple evaluation, normalized variable on left-hand side, backward
solveForwardSimple, //!< Block of one equation, newton solver needed, forward
solveBackwardSimple, //!< Block of one equation, newton solver needed, backward
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
};
{
evaluateForward = 1, //!< Simple evaluation, normalized variable on left-hand side, forward
evaluateBackward, //!< Simple evaluation, normalized variable on left-hand side, backward
solveForwardSimple, //!< Block of one equation, newton solver needed, forward
solveBackwardSimple, //!< Block of one equation, newton solver needed, backward
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
};
enum class PacTargetKind
{
unspecified, // Must be the first one, because its the default initializer
ll,
dl,
dd
};
{
unspecified, // Must be the first one, because its the default initializer
ll,
dl,
dd
};
#endif // _COMMON_ENUMS_HH

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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,24 +53,26 @@ 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)},
minCpuNbr{minCpuNbr_arg},
maxCpuNbr{maxCpuNbr_arg},
userName{move(userName_arg)},
password{move(password_arg)},
remoteDrive{move(remoteDrive_arg)},
remoteDirectory{move(remoteDirectory_arg)},
programPath{move(programPath_arg)},
programConfig{move(programConfig_arg)},
matlabOctavePath{move(matlabOctavePath_arg)},
singleCompThread{singleCompThread_arg},
numberOfThreadsPerJob{numberOfThreadsPerJob_arg},
operatingSystem{move(operatingSystem_arg)}
computerName {move(computerName_arg)},
port {move(port_arg)},
minCpuNbr {minCpuNbr_arg},
maxCpuNbr {maxCpuNbr_arg},
userName {move(userName_arg)},
password {move(password_arg)},
remoteDrive {move(remoteDrive_arg)},
remoteDirectory {move(remoteDirectory_arg)},
programPath {move(programPath_arg)},
programConfig {move(programConfig_arg)},
matlabOctavePath {move(matlabOctavePath_arg)},
singleCompThread {singleCompThread_arg},
numberOfThreadsPerJob {numberOfThreadsPerJob_arg},
operatingSystem {move(operatingSystem_arg)}
{
if (computerName.empty())
{
@ -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,15 +101,16 @@ 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_follower_open_mode{parallel_follower_open_mode_arg},
parallel_use_psexec{parallel_use_psexec_arg},
cluster_name{move(cluster_name_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)}
{
}
void
ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
ConfigFile::getConfigFileInfo(const filesystem::path& config_file)
{
using namespace boost;
ifstream configFile;
@ -117,9 +120,8 @@ 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)
defaultConfigFile = filesystem::path{appdata} / "dynare.ini";
if (auto appdata = getenv("APPDATA"); appdata)
defaultConfigFile = filesystem::path {appdata} / "dynare.ini";
else
{
if (parallel || parallel_test)
@ -132,9 +134,8 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
exit(EXIT_FAILURE);
}
#else
if (auto home = getenv("HOME");
home)
defaultConfigFile = filesystem::path{home} / ".dynare";
if (auto home = getenv("HOME"); home)
defaultConfigFile = filesystem::path {home} / ".dynare";
else
{
if (parallel || parallel_test)
@ -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,21 +165,21 @@ 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};
bool singleCompThread{false};
int minCpuNbr {0}, maxCpuNbr {0};
int numberOfThreadsPerJob {1};
bool singleCompThread {false};
member_nodes_t member_nodes;
bool inHooks{false}, inNode{false}, inCluster{false}, inPaths{false};
bool inHooks {false}, inNode {false}, inCluster {false}, inPaths {false};
while (configFile.good())
{
@ -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)
@ -277,7 +279,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path &config_file)
{
vector<string> tokenizedPath;
split(tokenizedPath, tokenizedLine.back(), is_any_of(":"), token_compress_on);
for (auto &it : tokenizedPath)
for (auto& it : tokenizedPath)
if (!it.empty())
{
trim(it);
@ -286,162 +288,171 @@ 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")
name = tokenizedLine.back();
else if (tokenizedLine.front() == "CPUnbr")
{
vector<string> tokenizedCpuNbr;
split(tokenizedCpuNbr, tokenizedLine.back(), is_any_of(":"));
try
{
if (tokenizedCpuNbr.size() == 1)
{
minCpuNbr = 1;
maxCpuNbr = stoi(tokenizedCpuNbr.front());
}
else if (tokenizedCpuNbr.size() == 2
&& tokenizedCpuNbr[0].at(0) == '['
&& tokenizedCpuNbr[1].at(tokenizedCpuNbr[1].size()-1) == ']')
{
tokenizedCpuNbr[0].erase(0, 1);
tokenizedCpuNbr[1].erase(tokenizedCpuNbr[1].size()-1, 1);
minCpuNbr = stoi(tokenizedCpuNbr[0]);
maxCpuNbr = stoi(tokenizedCpuNbr[1]);
}
}
catch (const invalid_argument &)
{
cerr << "ERROR: Could not convert value to integer for CPUnbr." << endl;
exit(EXIT_FAILURE);
}
if (minCpuNbr <= 0 || maxCpuNbr <= 0)
{
cerr << "ERROR: Syntax for the CPUnbr option is as follows:" << endl
<< " 1) CPUnbr = <int>" << endl
<< " or 2) CPUnbr = [<int>:<int>]" << endl
<< " where <int> is an Integer > 0." << endl;
exit(EXIT_FAILURE);
}
minCpuNbr--;
maxCpuNbr--;
if (minCpuNbr > maxCpuNbr)
{
int tmp = maxCpuNbr;
maxCpuNbr = minCpuNbr;
minCpuNbr = tmp;
}
}
else if (tokenizedLine.front() == "Port")
port = tokenizedLine.back();
else if (tokenizedLine.front() == "ComputerName")
computerName = tokenizedLine.back();
else if (tokenizedLine.front() == "UserName")
userName = tokenizedLine.back();
else if (tokenizedLine.front() == "Password")
password = tokenizedLine.back();
else if (tokenizedLine.front() == "RemoteDrive")
remoteDrive = tokenizedLine.back();
else if (tokenizedLine.front() == "RemoteDirectory")
remoteDirectory = tokenizedLine.back();
else if (tokenizedLine.front() == "DynarePath"
|| tokenizedLine.front() == "ProgramPath")
programPath = tokenizedLine.back();
else if (tokenizedLine.front() == "ProgramConfig")
programConfig = tokenizedLine.back();
else if (tokenizedLine.front() == "MatlabOctavePath")
matlabOctavePath = tokenizedLine.back();
else if (tokenizedLine.front() == "NumberOfThreadsPerJob")
numberOfThreadsPerJob = stoi(tokenizedLine.back());
else if (tokenizedLine.front() == "SingleCompThread")
if (tokenizedLine.back() == "true")
singleCompThread = true;
else if (tokenizedLine.back() == "false")
singleCompThread = false;
else
else if (tokenizedLine.front() == "Name")
name = tokenizedLine.back();
else if (tokenizedLine.front() == "CPUnbr")
{
vector<string> tokenizedCpuNbr;
split(tokenizedCpuNbr, tokenizedLine.back(), is_any_of(":"));
try
{
cerr << "ERROR (in config file): The value passed to SingleCompThread may only be 'true' or 'false'." << endl;
if (tokenizedCpuNbr.size() == 1)
{
minCpuNbr = 1;
maxCpuNbr = stoi(tokenizedCpuNbr.front());
}
else if (tokenizedCpuNbr.size() == 2 && tokenizedCpuNbr[0].at(0) == '['
&& tokenizedCpuNbr[1].at(tokenizedCpuNbr[1].size() - 1) == ']')
{
tokenizedCpuNbr[0].erase(0, 1);
tokenizedCpuNbr[1].erase(tokenizedCpuNbr[1].size() - 1, 1);
minCpuNbr = stoi(tokenizedCpuNbr[0]);
maxCpuNbr = stoi(tokenizedCpuNbr[1]);
}
}
catch (const invalid_argument&)
{
cerr << "ERROR: Could not convert value to integer for CPUnbr." << endl;
exit(EXIT_FAILURE);
}
else if (tokenizedLine.front() == "OperatingSystem")
operatingSystem = tokenizedLine.back();
else if (tokenizedLine.front() == "Members")
{
char_separator sep(" ,;", "()", drop_empty_tokens);
tokenizer tokens(tokenizedLine.back(), sep);
string node_name;
for (bool begin_weight{false};
const auto &token : tokens)
{
if (token == "(")
{
begin_weight = true;
continue;
}
else if (token == ")")
{
node_name.clear();
begin_weight = false;
continue;
}
if (!begin_weight)
{
if (!node_name.empty())
{
if (member_nodes.contains(node_name))
{
cerr << "ERROR (in config file): Node entered twice in specification of cluster." << endl;
exit(EXIT_FAILURE);
}
else
member_nodes[node_name] = 1.0;
}
node_name = token;
}
else
try
if (minCpuNbr <= 0 || maxCpuNbr <= 0)
{
cerr << "ERROR: Syntax for the CPUnbr option is as follows:" << endl
<< " 1) CPUnbr = <int>" << endl
<< " or 2) CPUnbr = [<int>:<int>]" << endl
<< " where <int> is an Integer > 0." << endl;
exit(EXIT_FAILURE);
}
minCpuNbr--;
maxCpuNbr--;
if (minCpuNbr > maxCpuNbr)
{
int tmp = maxCpuNbr;
maxCpuNbr = minCpuNbr;
minCpuNbr = tmp;
}
}
else if (tokenizedLine.front() == "Port")
port = tokenizedLine.back();
else if (tokenizedLine.front() == "ComputerName")
computerName = tokenizedLine.back();
else if (tokenizedLine.front() == "UserName")
userName = tokenizedLine.back();
else if (tokenizedLine.front() == "Password")
password = tokenizedLine.back();
else if (tokenizedLine.front() == "RemoteDrive")
remoteDrive = tokenizedLine.back();
else if (tokenizedLine.front() == "RemoteDirectory")
remoteDirectory = tokenizedLine.back();
else if (tokenizedLine.front() == "DynarePath" || tokenizedLine.front() == "ProgramPath")
programPath = tokenizedLine.back();
else if (tokenizedLine.front() == "ProgramConfig")
programConfig = tokenizedLine.back();
else if (tokenizedLine.front() == "MatlabOctavePath")
matlabOctavePath = tokenizedLine.back();
else if (tokenizedLine.front() == "NumberOfThreadsPerJob")
numberOfThreadsPerJob = stoi(tokenizedLine.back());
else if (tokenizedLine.front() == "SingleCompThread")
if (tokenizedLine.back() == "true")
singleCompThread = true;
else if (tokenizedLine.back() == "false")
singleCompThread = false;
else
{
cerr << "ERROR (in config file): The value passed to SingleCompThread may only be "
"'true' or 'false'."
<< endl;
exit(EXIT_FAILURE);
}
else if (tokenizedLine.front() == "OperatingSystem")
operatingSystem = tokenizedLine.back();
else if (tokenizedLine.front() == "Members")
{
char_separator sep(" ,;", "()", drop_empty_tokens);
tokenizer tokens(tokenizedLine.back(), sep);
string node_name;
for (bool begin_weight {false}; const auto& token : tokens)
{
if (token == "(")
{
begin_weight = true;
continue;
}
else if (token == ")")
{
node_name.clear();
begin_weight = false;
continue;
}
if (!begin_weight)
{
if (!node_name.empty())
{
auto weight = stod(token);
if (weight <= 0)
if (member_nodes.contains(node_name))
{
cerr << "ERROR (in config file): Misspecification of weights passed to Members option." << endl;
cerr << "ERROR (in config file): Node entered twice in specification "
"of cluster."
<< endl;
exit(EXIT_FAILURE);
}
member_nodes[node_name] = weight;
else
member_nodes[node_name] = 1.0;
}
catch (const invalid_argument &)
{
cerr << "ERROR (in config file): Misspecification of weights passed to Members option." << endl;
exit(EXIT_FAILURE);
}
}
if (!node_name.empty())
{
if (!member_nodes.contains(node_name))
member_nodes[node_name] = 1.0;
else
node_name = token;
}
else
try
{
cerr << "ERROR (in config file): Node entered twice in specification of cluster." << endl;
auto weight = stod(token);
if (weight <= 0)
{
cerr << "ERROR (in config file): Misspecification of weights passed to "
"Members option."
<< endl;
exit(EXIT_FAILURE);
}
member_nodes[node_name] = weight;
}
catch (const invalid_argument&)
{
cerr << "ERROR (in config file): Misspecification of weights passed to "
"Members option."
<< endl;
exit(EXIT_FAILURE);
}
}
}
else
{
cerr << "ERROR (in config file): Option " << tokenizedLine.front() << " is invalid." << endl;
exit(EXIT_FAILURE);
}
}
if (!node_name.empty())
{
if (!member_nodes.contains(node_name))
member_nodes[node_name] = 1.0;
else
{
cerr << "ERROR (in config file): Node entered twice in specification of "
"cluster."
<< endl;
exit(EXIT_FAILURE);
}
}
}
else
{
cerr << "ERROR (in config file): Option " << tokenizedLine.front() << " is invalid."
<< endl;
exit(EXIT_FAILURE);
}
}
}
@ -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,12 +495,15 @@ 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,
const string &operatingSystem)
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
if (inNode)
@ -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))
{
cerr << "ERROR: Every node must be assigned a unique name." << endl;
exit(EXIT_FAILURE);
}
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,
matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
operatingSystem);
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);
@ -535,11 +547,10 @@ ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, const member
}
void
ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
ConfigFile::checkPass([[maybe_unused]] WarningConsolidation& warnings) const
{
for (bool global_init_file_declared{false};
const auto &hook : hooks)
for (const auto &mapit : hook.get_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))
{
@ -557,10 +568,10 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
exit(EXIT_FAILURE);
}
for (const auto &follower_node : follower_nodes)
for (const auto& follower_node : follower_nodes)
{
#if !defined(_WIN32) && !defined(__CYGWIN32__)
//For Linux/Mac, check that cpuNbr starts at 0
// For Linux/Mac, check that cpuNbr starts at 0
if (follower_node.second.minCpuNbr != 0)
warnings << "WARNING: On Unix-based operating systems, you cannot specify the CPU that is "
<< "used in parallel processing. This will be adjusted for you such that the "
@ -571,21 +582,24 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation &warnings) const
{
stoi(follower_node.second.port);
}
catch (const invalid_argument &)
catch (const invalid_argument&)
{
cerr << "ERROR (node " << follower_node.first << "): the port must be an integer." << endl;
cerr << "ERROR (node " << follower_node.first << "): the port must be an integer."
<< endl;
exit(EXIT_FAILURE);
}
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,15 +669,17 @@ 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);
}
for (const auto &cluster : clusters)
for (const auto &itmn : cluster.second.member_nodes)
for (const auto& cluster : clusters)
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);
}
}
@ -661,8 +691,8 @@ ConfigFile::transformPass()
return;
#if !defined(_WIN32) && !defined(__CYGWIN32__)
//For Linux/Mac, check that cpuNbr starts at 0
for (auto &it : follower_nodes)
// For Linux/Mac, check that cpuNbr starts at 0
for (auto& it : follower_nodes)
if (it.second.minCpuNbr != 0)
{
it.second.maxCpuNbr = it.second.maxCpuNbr - it.second.minCpuNbr;
@ -670,13 +700,14 @@ 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)
double weight_denominator {0.0};
for (const auto& it : cluster_it->second.member_nodes)
weight_denominator += it.second;
for (auto &member_node : cluster_it->second.member_nodes)
for (auto& member_node : cluster_it->second.member_nodes)
member_node.second /= weight_denominator;
}
@ -685,33 +716,33 @@ ConfigFile::getIncludePaths() const
{
vector<filesystem::path> include_paths;
for (auto path : paths)
for (const auto &mapit : path.get_paths())
for (const auto &vecit : mapit.second)
for (const auto& mapit : path.get_paths())
for (const auto& vecit : mapit.second)
include_paths.emplace_back(vecit);
return include_paths;
}
void
ConfigFile::writeHooks(ostream &output) const
ConfigFile::writeHooks(ostream& output) const
{
for (auto hook : hooks)
for (const auto &mapit : hook.get_hooks())
for (const auto& mapit : hook.get_hooks())
output << "options_." << mapit.first << " = '" << mapit.second << "';" << endl;
}
void
ConfigFile::writeCluster(ostream &output) const
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)
for (const auto& itmn : cluster_it->second.member_nodes)
if (follower_node.first == itmn.first)
follower_node_in_member_nodes = true;
@ -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 << "', "
// The following should be switched back to “ProgramPath” once we move to Dragonfly
<< "'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,14 +794,18 @@ 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
<< "diary off;" << endl
<< "return;" << endl;
output
<< "ErrorCode = AnalyseComputationalEnvironment(options_.parallel, options_.parallel_info);"
<< endl
<< "disp(['AnalyseComputationalEnvironment returned with Error Code: ' "
"num2str(ErrorCode)]);"
<< endl
<< "diary off;" << endl
<< "return;" << endl;
}
void
ConfigFile::writeEndParallel(ostream &output) const
ConfigFile::writeEndParallel(ostream& output) const
{
if ((!parallel && !parallel_test) || !parallel_follower_open_mode)
return;

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,27 +119,30 @@ 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);
void getConfigFileInfo(const filesystem::path& parallel_config_file);
//! Check Pass
void checkPass(WarningConsolidation &warnings) const;
void checkPass(WarningConsolidation& warnings) const;
//! Check Pass
void transformPass();
//! Get Path Info
vector<filesystem::path> getIncludePaths() const;
//! Write any hooks
void writeHooks(ostream &output) const;
void writeHooks(ostream& output) const;
//! Create options_.parallel structure, write options
void writeCluster(ostream &output) const;
void writeCluster(ostream& output) const;
//! Close follower nodes if needed
void writeEndParallel(ostream &output) const;
void writeEndParallel(ostream& output) const;
};
#endif // ! CONFIG_FILE_HH

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,39 +46,37 @@ 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) :
symbol_table{symbol_table_arg},
num_constants{num_constants_arg},
external_functions_table{external_functions_table_arg},
is_dynamic{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},
is_dynamic {is_dynamic_arg}
{
initConstants();
}
DataTree::DataTree(const DataTree &d) :
symbol_table{d.symbol_table},
num_constants{d.num_constants},
external_functions_table{d.external_functions_table},
is_dynamic{d.is_dynamic},
local_variables_vector{d.local_variables_vector}
DataTree::DataTree(const DataTree& d) :
symbol_table {d.symbol_table},
num_constants {d.num_constants},
external_functions_table {d.external_functions_table},
is_dynamic {d.is_dynamic},
local_variables_vector {d.local_variables_vector}
{
// Constants must be initialized first because they are used in some Add* methods
initConstants();
for (const auto &it : d.node_list)
for (const auto& it : d.node_list)
it->clone(*this);
assert(node_list.size() == d.node_list.size());
for (const auto &[symb_id, value] : d.local_variables_table)
for (const auto& [symb_id, value] : d.local_variables_table)
local_variables_table[symb_id] = value->clone(*this);
}
DataTree &
DataTree::operator=(const DataTree &d)
DataTree&
DataTree::operator=(const DataTree& d)
{
assert(&symbol_table == &d.symbol_table);
assert(&num_constants == &d.num_constants);
@ -110,7 +108,7 @@ DataTree::operator=(const DataTree &d)
for (int symb_id : d.local_variables_vector)
local_variables_table[symb_id] = d.local_variables_table.at(symb_id)->clone(*this);
for (const auto &it : d.node_list)
for (const auto& it : d.node_list)
it->clone(*this);
assert(node_list.size() == d.node_list.size());
@ -120,13 +118,12 @@ DataTree::operator=(const DataTree &d)
return *this;
}
NumConstNode *
DataTree::AddNonNegativeConstant(const string &value)
NumConstNode*
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);
@ -136,7 +133,7 @@ DataTree::AddNonNegativeConstant(const string &value)
return p;
}
VariableNode *
VariableNode*
DataTree::AddVariable(int symb_id, int lag)
{
if (lag != 0 && !is_dynamic)
@ -145,24 +142,24 @@ 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);
auto p = sp.get();
node_list.push_back(move(sp));
variable_node_map.try_emplace({ symb_id, lag }, p);
variable_node_map.try_emplace({symb_id, lag}, p);
return p;
}
VariableNode *
VariableNode*
DataTree::getVariable(int symb_id, int lag) const
{
auto it = variable_node_map.find({ symb_id, lag });
auto it = variable_node_map.find({symb_id, lag});
if (it == variable_node_map.end())
{
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;
@ -171,7 +168,7 @@ DataTree::getVariable(int symb_id, int lag) const
bool
DataTree::ParamUsedWithLeadLagInternal() const
{
for (const auto &[symb_lag, expr] : variable_node_map)
for (const auto& [symb_lag, expr] : variable_node_map)
if (symbol_table.getType(symb_lag.first) == SymbolType::parameter && symb_lag.second != 0)
return true;
return false;
@ -187,22 +184,22 @@ DataTree::AddPlus(expr_t iArg1, expr_t iArg2)
return iArg2;
// Simplify x+(-y) in x-y
if (auto uarg2 = dynamic_cast<UnaryOpNode *>(iArg2);
if (auto uarg2 = dynamic_cast<UnaryOpNode*>(iArg2);
uarg2 && uarg2->op_code == UnaryOpcode::uminus)
return AddMinus(iArg1, uarg2->arg);
// Simplify (-x)+y in y-x
if (auto uarg1 = dynamic_cast<UnaryOpNode *>(iArg1);
if (auto uarg1 = dynamic_cast<UnaryOpNode*>(iArg1);
uarg1 && uarg1->op_code == UnaryOpcode::uminus)
return AddMinus(iArg2, uarg1->arg);
// Simplify (x-y)+y in x
if (auto barg1 = dynamic_cast<BinaryOpNode *>(iArg1);
if (auto barg1 = dynamic_cast<BinaryOpNode*>(iArg1);
barg1 && barg1->op_code == BinaryOpcode::minus && barg1->arg2 == iArg2)
return barg1->arg1;
// Simplify y+(x-y) in x
if (auto barg2 = dynamic_cast<BinaryOpNode *>(iArg2);
if (auto barg2 = dynamic_cast<BinaryOpNode*>(iArg2);
barg2 && barg2->op_code == BinaryOpcode::minus && barg2->arg2 == iArg1)
return barg2->arg1;
@ -226,12 +223,12 @@ DataTree::AddMinus(expr_t iArg1, expr_t iArg2)
return Zero;
// Simplify x-(-y) in x+y
if (auto uarg2 = dynamic_cast<UnaryOpNode *>(iArg2);
if (auto uarg2 = dynamic_cast<UnaryOpNode*>(iArg2);
uarg2 && uarg2->op_code == UnaryOpcode::uminus)
return AddPlus(iArg1, uarg2->arg);
// Simplify (x+y)-y and (y+x)-y in x
if (auto barg1 = dynamic_cast<BinaryOpNode *>(iArg1);
if (auto barg1 = dynamic_cast<BinaryOpNode*>(iArg1);
barg1 && barg1->op_code == BinaryOpcode::plus)
{
if (barg1->arg2 == iArg2)
@ -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);
@ -276,12 +272,12 @@ DataTree::AddTimes(expr_t iArg1, expr_t iArg2)
return AddUMinus(iArg1);
// Simplify (x/y)*y in x
if (auto barg1 = dynamic_cast<BinaryOpNode *>(iArg1);
if (auto barg1 = dynamic_cast<BinaryOpNode*>(iArg1);
barg1 && barg1->op_code == BinaryOpcode::divide && barg1->arg2 == iArg2)
return barg1->arg1;
// Simplify y*(x/y) in x
if (auto barg2 = dynamic_cast<BinaryOpNode *>(iArg2);
if (auto barg2 = dynamic_cast<BinaryOpNode*>(iArg2);
barg2 && barg2->op_code == BinaryOpcode::divide && barg2->arg2 == iArg1)
return barg2->arg1;
@ -312,12 +308,12 @@ DataTree::AddDivide(expr_t iArg1, expr_t iArg2) noexcept(false)
return One;
// Simplify x/(1/y) in x*y
if (auto barg2 = dynamic_cast<BinaryOpNode *>(iArg2);
if (auto barg2 = dynamic_cast<BinaryOpNode*>(iArg2);
barg2 && barg2->op_code == BinaryOpcode::divide && barg2->arg1 == One)
return AddTimes(iArg1, barg2->arg2);
// Simplify (x*y)/y and (y*x)/y in x
if (auto barg1 = dynamic_cast<BinaryOpNode *>(iArg1);
if (auto barg1 = dynamic_cast<BinaryOpNode*>(iArg1);
barg1 && barg1->op_code == BinaryOpcode::times)
{
if (barg1->arg2 == iArg2)
@ -401,7 +397,7 @@ DataTree::AddDiff(expr_t iArg1)
}
expr_t
DataTree::AddAdl(expr_t iArg1, const string &name, const vector<int> &lags)
DataTree::AddAdl(expr_t iArg1, const string& name, const vector<int>& lags)
{
return AddUnaryOp(UnaryOpcode::adl, iArg1, 0, 0, 0, name, lags);
}
@ -428,7 +424,7 @@ DataTree::AddLog(expr_t iArg1)
}
// Simplify log(1/x) in log(x)
if (auto barg1 = dynamic_cast<BinaryOpNode *>(iArg1);
if (auto barg1 = dynamic_cast<BinaryOpNode*>(iArg1);
barg1 && barg1->op_code == BinaryOpcode::divide && barg1->arg1 == One)
return AddUMinus(AddLog(barg1->arg2));
@ -448,7 +444,7 @@ DataTree::AddLog10(expr_t iArg1)
}
// Simplify log₁₀(1/x) in log₁₀(x)
if (auto barg1 = dynamic_cast<BinaryOpNode *>(iArg1);
if (auto barg1 = dynamic_cast<BinaryOpNode*>(iArg1);
barg1 && barg1->op_code == BinaryOpcode::divide && barg1->arg1 == One)
return AddUMinus(AddLog10(barg1->arg2));
@ -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
@ -678,10 +675,9 @@ DataTree::AddExpectation(int iArg1, expr_t iArg2)
}
expr_t
DataTree::AddVarExpectation(const string &model_name)
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);
@ -692,10 +688,9 @@ DataTree::AddVarExpectation(const string &model_name)
}
expr_t
DataTree::AddPacExpectation(const string &model_name)
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);
@ -706,7 +701,7 @@ DataTree::AddPacExpectation(const string &model_name)
}
expr_t
DataTree::AddPacTargetNonstationary(const string &model_name)
DataTree::AddPacTargetNonstationary(const string& model_name)
{
if (auto it = pac_target_nonstationary_node_map.find(model_name);
it != pac_target_nonstationary_node_map.end())
@ -719,12 +714,12 @@ DataTree::AddPacTargetNonstationary(const string &model_name)
return p;
}
BinaryOpNode *
BinaryOpNode*
DataTree::AddEqual(expr_t iArg1, expr_t iArg2)
{
/* We know that we can safely cast to BinaryOpNode because
BinaryOpCode::equal can never be reduced to a constant. */
return dynamic_cast<BinaryOpNode *>(AddBinaryOp(iArg1, BinaryOpcode::equal, iArg2));
return dynamic_cast<BinaryOpNode*>(AddBinaryOp(iArg1, BinaryOpcode::equal, iArg2));
}
void
@ -734,65 +729,72 @@ DataTree::AddLocalVariable(int symb_id, expr_t value) noexcept(false)
// Throw an exception if symbol already declared
if (local_variables_table.contains(symb_id))
throw LocalVariableException{symbol_table.getName(symb_id)};
throw LocalVariableException {symbol_table.getName(symb_id)};
local_variables_table.emplace(symb_id, value);
local_variables_vector.push_back(symb_id);
}
expr_t
DataTree::AddExternalFunction(int symb_id, const vector<expr_t> &arguments)
DataTree::AddExternalFunction(int symb_id, const vector<expr_t>& arguments)
{
assert(symbol_table.getType(symb_id) == SymbolType::externalFunction);
if (auto it = external_function_node_map.find({ arguments, symb_id });
if (auto it = external_function_node_map.find({arguments, symb_id});
it != external_function_node_map.end())
return it->second;
auto sp = make_unique<ExternalFunctionNode>(*this, node_list.size(), symb_id, arguments);
auto p = sp.get();
node_list.push_back(move(sp));
external_function_node_map.try_emplace({ arguments, symb_id }, p);
external_function_node_map.try_emplace({arguments, symb_id}, p);
return p;
}
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 });
it != second_deriv_external_function_node_map.end())
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;
}
bool
DataTree::isSymbolUsed(int symb_id) const
{
for (const auto &[symb_lag, expr] : variable_node_map)
for (const auto& [symb_lag, expr] : variable_node_map)
if (symb_lag.first == symb_id)
return true;
@ -833,7 +835,7 @@ DataTree::getTypeSpecificIDByDerivID([[maybe_unused]] int deriv_id) const
}
void
DataTree::addAllParamDerivId([[maybe_unused]] set<int> &deriv_id_set)
DataTree::addAllParamDerivId([[maybe_unused]] set<int>& deriv_id_set)
{
}
@ -841,14 +843,14 @@ bool
DataTree::isUnaryOpUsed(UnaryOpcode opcode) const
{
return any_of(unary_op_node_map.begin(), unary_op_node_map.end(),
[=](const auto &it) { return get<1>(it.first) == opcode; });
[=](const auto& it) { return get<1>(it.first) == opcode; });
}
bool
DataTree::isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const
{
set<int> var;
for (const auto &it : unary_op_node_map)
for (const auto& it : unary_op_node_map)
if (get<1>(it.first) == opcode)
{
it.second->collectVariables(type, var);
@ -862,14 +864,14 @@ bool
DataTree::isBinaryOpUsed(BinaryOpcode opcode) const
{
return any_of(binary_op_node_map.begin(), binary_op_node_map.end(),
[=](const auto &it) { return get<2>(it.first) == opcode; });
[=](const auto& it) { return get<2>(it.first) == opcode; });
}
bool
DataTree::isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) const
{
set<int> var;
for (const auto &it : binary_op_node_map)
for (const auto& it : binary_op_node_map)
if (get<2>(it.first) == opcode)
{
it.second->collectVariables(type, var);
@ -883,21 +885,23 @@ int
DataTree::minLagForSymbol(int symb_id) const
{
int r = 0;
for (const auto &[symb_lag, expr] : variable_node_map)
for (const auto& [symb_lag, expr] : variable_node_map)
if (symb_lag.first == symb_id)
r = min(r, symb_lag.second);
return r;
}
void
DataTree::writeCHelpersDefinition(ostream &output) const
DataTree::writeCHelpersDefinition(ostream& output) const
{
if (isBinaryOpUsed(BinaryOpcode::powerDeriv))
output << "// The k-th derivative of x^p" << endl
<< "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
@ -917,7 +921,7 @@ DataTree::writeCHelpersDefinition(ostream &output) const
}
void
DataTree::writeCHelpersDeclaration(ostream &output) const
DataTree::writeCHelpersDeclaration(ostream& output) const
{
if (isBinaryOpUsed(BinaryOpcode::powerDeriv))
output << "extern inline double getPowerDeriv(double x, double p, int k);" << endl;
@ -932,12 +936,11 @@ 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;
str.remove_prefix(idx+1);
str.remove_prefix(idx + 1);
}
return result;
}
@ -946,30 +949,30 @@ filesystem::path
DataTree::packageDir(string_view package)
{
filesystem::path d;
for (const auto &it : strsplit(move(package), '.'))
for (const auto& it : strsplit(move(package), '.'))
d /= "+" + it;
return d;
}
void
DataTree::writeToFileIfModified(stringstream &new_contents, const filesystem::path &filename)
DataTree::writeToFileIfModified(stringstream& new_contents, const filesystem::path& filename)
{
ifstream old_file{filename, ios::in | ios::binary};
ifstream old_file {filename, ios::in | ios::binary};
if (old_file.is_open()
&& equal(istreambuf_iterator<char>{old_file}, istreambuf_iterator<char>{},
istreambuf_iterator<char>{new_contents}, istreambuf_iterator<char>{}))
&& equal(istreambuf_iterator<char> {old_file}, istreambuf_iterator<char> {},
istreambuf_iterator<char> {new_contents}, istreambuf_iterator<char> {}))
return;
old_file.close();
new_contents.seekg(0);
ofstream new_file{filename, ios::out | ios::binary};
ofstream new_file {filename, ios::out | ios::binary};
if (!new_file.is_open())
{
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
exit(EXIT_FAILURE);
}
copy(istreambuf_iterator<char>{new_contents}, istreambuf_iterator<char>{},
ostreambuf_iterator<char>{new_file});
copy(istreambuf_iterator<char> {new_contents}, istreambuf_iterator<char> {},
ostreambuf_iterator<char> {new_file});
new_file.close();
}

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;
@ -43,57 +43,61 @@ class DataTree
{
public:
//! A reference to the symbol table
SymbolTable &symbol_table;
SymbolTable& symbol_table;
//! Reference to numerical constants table
NumericalConstants &num_constants;
NumericalConstants& num_constants;
//! A reference to the external functions table
ExternalFunctionsTable &external_functions_table;
ExternalFunctionsTable& external_functions_table;
//! Is it possible to use leads/lags on variable nodes?
const bool is_dynamic;
private:
//! num_constant_id -> NumConstNode
using num_const_node_map_t = map<int, NumConstNode *>;
using num_const_node_map_t = map<int, NumConstNode*>;
num_const_node_map_t num_const_node_map;
//! (symbol_id, lag) -> VariableNode
using variable_node_map_t = map<pair<int, int>, VariableNode *>;
using variable_node_map_t = map<pair<int, int>, VariableNode*>;
variable_node_map_t variable_node_map;
//! (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
using binary_op_node_map_t = map<tuple<expr_t, expr_t, BinaryOpcode, int>, BinaryOpNode *>;
using binary_op_node_map_t = map<tuple<expr_t, expr_t, BinaryOpcode, int>, BinaryOpNode*>;
binary_op_node_map_t binary_op_node_map;
//! ( arg1, arg2, arg3, opCode) -> TrinaryOpNode
using trinary_op_node_map_t = map<tuple<expr_t, expr_t, expr_t, TrinaryOpcode>, TrinaryOpNode *>;
using trinary_op_node_map_t = map<tuple<expr_t, expr_t, expr_t, TrinaryOpcode>, TrinaryOpNode*>;
trinary_op_node_map_t trinary_op_node_map;
// (arguments, symb_id) -> ExternalFunctionNode
using external_function_node_map_t = map<pair<vector<expr_t>, int>, ExternalFunctionNode *>;
using external_function_node_map_t = map<pair<vector<expr_t>, int>, ExternalFunctionNode*>;
external_function_node_map_t external_function_node_map;
// (model_name, symb_id, forecast_horizon) -> VarExpectationNode
using var_expectation_node_map_t = map<string, VarExpectationNode *>;
using var_expectation_node_map_t = map<string, VarExpectationNode*>;
var_expectation_node_map_t var_expectation_node_map;
// model_name -> PacExpectationNode
using pac_expectation_node_map_t = map<string, PacExpectationNode *>;
using pac_expectation_node_map_t = map<string, PacExpectationNode*>;
pac_expectation_node_map_t pac_expectation_node_map;
// model_name -> PacTargetNonstationaryNode
using pac_target_nonstationary_node_map_t = map<string, PacTargetNonstationaryNode *>;
using pac_target_nonstationary_node_map_t = map<string, PacTargetNonstationaryNode*>;
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()
@ -111,31 +116,33 @@ protected:
/* Writes the contents of “new_contents” to the file “filename”. However, if
the file already exists and would not be modified by this operation, then do
nothing. */
static void writeToFileIfModified(stringstream &new_contents, const filesystem::path &filename);
static void writeToFileIfModified(stringstream& new_contents, const filesystem::path& filename);
private:
constexpr static int constants_precision{16};
constexpr static int constants_precision {16};
//! 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;
DataTree(const DataTree &d);
DataTree &operator=(const DataTree &d);
DataTree(const DataTree& d);
DataTree& operator=(const DataTree& d);
//! Some predefined constants
NumConstNode *Zero, *One, *Two, *Three, *NaN, *Infinity, *Pi;
@ -153,13 +160,13 @@ public:
inline expr_t AddPossiblyNegativeConstant(double val);
//! Adds a non-negative numerical constant (possibly Inf or NaN)
NumConstNode *AddNonNegativeConstant(const string &value);
NumConstNode* AddNonNegativeConstant(const string& value);
//! Adds a variable
VariableNode *AddVariable(int symb_id, int lag = 0);
VariableNode* AddVariable(int symb_id, int lag = 0);
//! Gets a variable
/*! Same as AddVariable, except that it fails if the variable node has not
already been created */
VariableNode *getVariable(int symb_id, int lag = 0) const;
VariableNode* getVariable(int symb_id, int lag = 0) const;
//! Adds "arg1+arg2" to model tree
expr_t AddPlus(expr_t iArg1, expr_t iArg2);
//! Adds "arg1-arg2" to model tree
@ -191,7 +198,7 @@ public:
//! Adds "diff(arg)" to model tree
expr_t AddDiff(expr_t iArg1);
//! Adds "adl(arg1, name, lag/lags)" to model tree
expr_t AddAdl(expr_t iArg1, const string &name, const vector<int> &lags);
expr_t AddAdl(expr_t iArg1, const string& name, const vector<int>& lags);
//! Adds "exp(arg)" to model tree
expr_t AddExp(expr_t iArg1);
//! Adds "log(arg)" to model tree
@ -249,21 +256,23 @@ public:
//! Add 2nd derivative of steady state w.r.t. parameter to model tree
expr_t AddSteadyStateParam2ndDeriv(expr_t iArg1, int param1_symb_id, int param2_symb_id);
//! Adds "arg1=arg2" to model tree
BinaryOpNode *AddEqual(expr_t iArg1, expr_t iArg2);
BinaryOpNode* AddEqual(expr_t iArg1, expr_t iArg2);
//! Adds "var_expectation(model_name)" to model tree
expr_t AddVarExpectation(const string &model_name);
expr_t AddVarExpectation(const string& model_name);
//! Adds pac_expectation command to model tree
expr_t AddPacExpectation(const string &model_name);
expr_t AddPacExpectation(const string& model_name);
//! Adds a pac_target_nonstationary node to model tree
expr_t AddPacTargetNonstationary(const string &model_name);
expr_t AddPacTargetNonstationary(const string& model_name);
//! Adds a model local variable with its value
void AddLocalVariable(int symb_id, expr_t value) noexcept(false);
//! Adds an external function node
expr_t AddExternalFunction(int symb_id, const vector<expr_t> &arguments);
expr_t AddExternalFunction(int symb_id, const vector<expr_t>& arguments);
//! Adds an external function node for the first derivative of an external function
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,18 +283,19 @@ 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
inline functions */
void writeCHelpersDefinition(ostream &output) const;
void writeCHelpersDefinition(ostream& output) const;
/* Writes declarations of C function helpers (getPowerDeriv(), sign()) as
extern inline (external definition). Those need to be included in exactly
one translation unit. That external definition will be used or not,
depending on the optimization decision by the compiler.
See https://en.cppreference.com/w/c/language/inline */
void writeCHelpersDeclaration(ostream &output) const;
void writeCHelpersDeclaration(ostream& output) const;
//! Thrown when trying to access an unknown variable by deriv_id
class UnknownDerivIDException
{
@ -333,9 +343,10 @@ public:
}
//! Adds to the set all the deriv IDs corresponding to parameters
virtual void addAllParamDerivId(set<int> &deriv_id_set);
virtual void addAllParamDerivId(set<int>& deriv_id_set);
//! Returns bool indicating whether DataTree represents a Dynamic Model (returns true in DynamicModel.hh)
//! Returns bool indicating whether DataTree represents a Dynamic Model (returns true in
//! DynamicModel.hh)
virtual bool
isDynamic() const
{
@ -353,7 +364,7 @@ public:
{
auto it = local_variables_table.find(symb_id);
if (it == local_variables_table.end())
throw UnknownLocalVariableException{symb_id};
throw UnknownLocalVariableException {symb_id};
return it->second;
}
@ -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
{
@ -422,22 +435,25 @@ DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int
double val = UnaryOpNode::eval_opcode(op_code, argval);
return AddPossiblyNegativeConstant(val);
}
catch (ExprNode::EvalException &e)
catch (ExprNode::EvalException& e)
{
}
}
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;
}
inline expr_t
DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder)
{
if (auto it = binary_op_node_map.find({ arg1, arg2, op_code, powerDerivOrder });
if (auto it = binary_op_node_map.find({arg1, arg2, op_code, powerDerivOrder});
it != binary_op_node_map.end())
return it->second;
@ -449,21 +465,22 @@ DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerD
double val = BinaryOpNode::eval_opcode(argval1, op_code, argval2, powerDerivOrder);
return AddPossiblyNegativeConstant(val);
}
catch (ExprNode::EvalException &e)
catch (ExprNode::EvalException& e)
{
}
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);
binary_op_node_map.try_emplace({arg1, arg2, op_code, powerDerivOrder}, p);
return p;
}
inline expr_t
DataTree::AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3)
{
if (auto it = trinary_op_node_map.find({ arg1, arg2, arg3, op_code });
if (auto it = trinary_op_node_map.find({arg1, arg2, arg3, op_code});
it != trinary_op_node_map.end())
return it->second;
@ -476,14 +493,14 @@ DataTree::AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t a
double val = TrinaryOpNode::eval_opcode(argval1, op_code, argval2, argval3);
return AddPossiblyNegativeConstant(val);
}
catch (ExprNode::EvalException &e)
catch (ExprNode::EvalException& e)
{
}
auto sp = make_unique<TrinaryOpNode>(*this, node_list.size(), arg1, op_code, arg2, arg3);
auto p = sp.get();
node_list.push_back(move(sp));
trinary_op_node_map.try_emplace({ arg1, arg2, arg3, op_code }, p);
trinary_op_node_map.try_emplace({arg1, arg2, arg3, op_code}, p);
return 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;
@ -34,23 +34,24 @@ class DynamicModel : public ModelTree
friend class StaticModel; // For reading static_mfs from converting constructor
public:
//! A reference to the trend component model table
TrendComponentModelTable &trend_component_model_table;
TrendComponentModelTable& trend_component_model_table;
//! A reference to the VAR model table
VarModelTable &var_model_table;
VarModelTable& var_model_table;
/* Used in the balanced growth test, for determining whether the
cross-derivative of a given equation, w.r.t. an endogenous and a trend
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};
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
be too large, otherwise the test becomes less powerful. */
constexpr static double zero_band{1e-8};
constexpr static double zero_band {1e-8};
//! Stores equations declared as [static]
/*! They will be used in the conversion to StaticModel to replace equations marked as [dynamic] */
vector<BinaryOpNode *> static_only_equations;
vector<BinaryOpNode*> static_only_equations;
//! Stores line numbers of equations declared as [static]
vector<optional<int>> static_only_equations_lineno;
@ -73,24 +74,25 @@ private:
//! Maximum lag and lead over all types of variables (positive values)
/*! Set by computeDerivIDs() */
int max_lag{0}, max_lead{0};
int max_lag {0}, max_lead {0};
//! Maximum lag and lead over endogenous variables (positive values)
/*! Set by computeDerivIDs() */
int max_endo_lag{0}, max_endo_lead{0};
int max_endo_lag {0}, max_endo_lead {0};
//! Maximum lag and lead over exogenous variables (positive values)
/*! Set by computeDerivIDs() */
int max_exo_lag{0}, max_exo_lead{0};
int max_exo_lag {0}, max_exo_lead {0};
//! Maximum lag and lead over deterministic exogenous variables (positive values)
/*! Set by computeDerivIDs() */
int max_exo_det_lag{0}, max_exo_det_lead{0};
int max_exo_det_lag {0}, max_exo_det_lead {0};
//! Maximum lag and lead over all types of variables (positive values) of original model
int max_lag_orig{0}, max_lead_orig{0}, max_lag_with_diffs_expanded_orig{0};
int max_lag_orig {0}, max_lead_orig {0}, max_lag_with_diffs_expanded_orig {0};
//! Maximum lag and lead over endogenous variables (positive values) of original model
int max_endo_lag_orig{0}, max_endo_lead_orig{0};
int max_endo_lag_orig {0}, max_endo_lead_orig {0};
//! Maximum lag and lead over exogenous variables (positive values) of original model
int max_exo_lag_orig{0}, max_exo_lead_orig{0};
//! Maximum lag and lead over deterministic exogenous variables (positive values) of original model
int max_exo_det_lag_orig{0}, max_exo_det_lead_orig{0};
int max_exo_lag_orig {0}, max_exo_lead_orig {0};
//! 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
map<int, ExprNode::EquationInfo> xrefs;
@ -111,30 +113,30 @@ private:
map<string, set<int>> var_expectation_functions_to_write;
// Value of the “mfs” option of “model” block (or ”model_options” command)
int mfs{1};
int mfs {1};
/* Value of the “static_mfs” option of “model” block (or the “model_options”
command).
Only used when converting to StaticModel class. */
int static_mfs{0};
int static_mfs {0};
// Writes dynamic model file (MATLAB/Octave version, legacy representation)
void writeDynamicMFile(const string &basename) const;
void writeDynamicMFile(const string& basename) const;
//! Writes the code of the block-decomposed model in virtual machine bytecode
void writeDynamicBlockBytecode(const string &basename) const;
void writeDynamicBlockBytecode(const string& basename) const;
//! Writes the code of the model in virtual machine bytecode
void writeDynamicBytecode(const string &basename) const;
void writeDynamicBytecode(const string& basename) const;
// Write the block structure of the model in the driver file
void writeBlockDriverOutput(ostream &output) const;
void writeBlockDriverOutput(ostream& output) const;
// Used by determineBlockDerivativesType()
enum class BlockDerivativeType
{
standard,
chainRule,
normalizedChainRule
};
{
standard,
chainRule,
normalizedChainRule
};
/* For each tuple (lag, eq, var) within the given block, determine the type
of the derivative to be computed. Indices are within the block (i.e.
@ -143,7 +145,7 @@ private:
void computeChainRuleJacobian() override;
string reform(const string &name) const;
string reform(const string& name) const;
SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override;
int getLagByDerivID(int deriv_id) const noexcept(false) override;
@ -153,10 +155,11 @@ private:
//! Compute the column indices of the dynamic Jacobian
void computeDynJacobianCols();
//! Computes derivatives of the Jacobian w.r. to trend vars and tests that they are equal to zero
void testTrendDerivativesEqualToZero(const eval_context_t &eval_context);
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,37 +170,39 @@ 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;
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,
const ostringstream &init_s, const ostringstream &end_s,
const ostringstream &s, const ostringstream &s_tt) const;
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;
/* Create the compatibility dynamic.m file for MATLAB/Octave not yet using
the temporary terms array interface (legacy representation) */
void writeDynamicMCompatFile(const string &basename) const;
void writeDynamicMCompatFile(const string& basename) const;
//! Internal helper for the copy constructor and assignment operator
/*! Copies all the structures that contain ExprNode*, by the converting the
pointers into their equivalent in the new tree */
void copyHelper(const DynamicModel &m);
void copyHelper(const DynamicModel& m);
/* Handles parsing of argument passed to exclude_eqs/include_eqs.
@ -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<BinaryOpNode *> &all_equations,
vector<optional<int>> &all_equations_lineno,
EquationTags &all_equation_tags,
bool static_equations) const;
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;
//! 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
@ -267,7 +273,7 @@ private:
int
getBlockJacobianEndoCol(int blk, int var, int lag) const override
{
return blocks_jacob_cols_endo[blk].at({ var, lag });
return blocks_jacob_cols_endo[blk].at({var, lag});
}
protected:
@ -278,60 +284,60 @@ protected:
}
public:
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);
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);
DynamicModel(const DynamicModel &m);
DynamicModel &operator=(const DynamicModel &m);
DynamicModel(const DynamicModel& m);
DynamicModel& operator=(const DynamicModel& m);
//! Compute cross references
void computeXrefs();
//! Write cross references
void writeXrefs(ostream &output) const;
void writeXrefs(ostream& output) const;
//! 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,
void computingPass(int derivsOrder, int paramsDerivsOrder, const eval_context_t& eval_context,
bool no_tmp_terms, bool block, bool use_dll);
//! Writes information about the dynamic model to the driver file
void writeDriverOutput(ostream &output, bool compute_xrefs) const;
void writeDriverOutput(ostream& output, bool compute_xrefs) const;
//! Write JSON AST
void writeJsonAST(ostream &output) const;
void writeJsonAST(ostream& output) const;
//! Write JSON variable mapping
void writeJsonVariableMapping(ostream &output) const;
void writeJsonVariableMapping(ostream& output) const;
//! Write JSON Output
void writeJsonOutput(ostream &output) const;
void writeJsonOutput(ostream& output) const;
//! Write JSON Output representation of original dynamic model
void writeJsonOriginalModelOutput(ostream &output) const;
void writeJsonOriginalModelOutput(ostream& output) const;
//! Write JSON Output representation of model info (useful stuff from M_)
void writeJsonDynamicModelInfo(ostream &output) const;
void writeJsonDynamicModelInfo(ostream& output) const;
//! Write JSON Output representation of dynamic model after computing pass
void writeJsonComputingPassOutput(ostream &output, bool writeDetails) const;
void writeJsonComputingPassOutput(ostream& output, bool writeDetails) const;
//! Write JSON params derivatives
void writeJsonParamsDerivatives(ostream &output, bool writeDetails) const;
void writeJsonParamsDerivatives(ostream& output, bool writeDetails) const;
//! Write cross reference output if the xref maps have been filed
void writeJsonXrefs(ostream &output) const;
void writeJsonXrefsHelper(ostream &output, const map<pair<int, int>, set<int>> &xrefmap) const;
void writeJsonXrefs(ostream& output) const;
void writeJsonXrefsHelper(ostream& output, const map<pair<int, int>, set<int>>& xrefmap) const;
//! Print equations that have non-zero second derivatives
void printNonZeroHessianEquations(ostream &output) const;
void printNonZeroHessianEquations(ostream& output) const;
//! Tells whether Hessian has been computed
/*! This is needed to know whether no non-zero equation in Hessian means a
@ -357,7 +363,7 @@ public:
components, available from the transformed model. Needs to be called after
fillTrendComponentModelTableFromOrigModel() has been called on the
original model */
void fillTrendComponentModelTableAREC(const ExprNode::subst_table_t &diff_subst_table) const;
void fillTrendComponentModelTableAREC(const ExprNode::subst_table_t& diff_subst_table) const;
//! Fill the VAR model table with information available from the transformed model
// NB: Does not fill the AR and A0 matrices
@ -374,16 +380,18 @@ 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>
void writeParamsDerivativesFile(const string &basename) const;
void writeParamsDerivativesFile(const string& basename) const;
//! 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
@ -395,14 +403,14 @@ public:
void setLeadsLagsOrig();
//! Implements the include_eqs/exclude_eqs options
void includeExcludeEquations(const string &inc_exc_option_value, bool exclude_eqs);
void includeExcludeEquations(const string& inc_exc_option_value, bool exclude_eqs);
/* Removes equations from the model (identified by one or more tags; if
multiple tags are present for a single equation, they are understood as a
conjunction).
Used for include_eqs/exclude_eqs options and for model_remove and
model_replace blocks */
void removeEquations(const vector<map<string, string>> &listed_eqs_by_tag, bool exclude_eqs,
void removeEquations(const vector<map<string, string>>& listed_eqs_by_tag, bool exclude_eqs,
bool excluded_vars_change_type);
/* Replaces model equations with derivatives of Lagrangian w.r.t. endogenous.
@ -411,13 +419,13 @@ public:
Returns the number of optimality FOCs, which is by construction equal to
the number of endogenous before adding the Lagrange multipliers
(internally called ramsey_endo_nbr). */
int computeRamseyPolicyFOCs(const StaticModel &static_model);
int computeRamseyPolicyFOCs(const StaticModel& static_model);
//! Clears all equations
void clearEquations();
//! Replaces the model equations in dynamic_model with those in this model
void replaceMyEquations(DynamicModel &dynamic_model) const;
void replaceMyEquations(DynamicModel& dynamic_model) const;
//! Adds an equation marked as [static]
void addStaticOnlyEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags);
@ -433,13 +441,14 @@ 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;
void writeLatexFile(const string& basename, bool write_equation_tags) const;
//! Writes LaTeX file with the equations of the dynamic model (for the original model)
void writeLatexOriginalFile(const string &basename, bool write_equation_tags) const;
void writeLatexOriginalFile(const string& basename, bool write_equation_tags) const;
int getDerivID(int symb_id, int lag) const noexcept(false) override;
@ -454,25 +463,24 @@ public:
if (type == SymbolType::endogenous)
{
assert(lag >= -1 && lag <= 1);
return tsid+(lag+1)*symbol_table.endo_nbr();
return tsid + (lag + 1) * symbol_table.endo_nbr();
}
else if (type == SymbolType::exogenous)
{
assert(lag == 0);
return tsid+3*symbol_table.endo_nbr();
return tsid + 3 * symbol_table.endo_nbr();
}
else if (type == SymbolType::exogenousDet)
{
assert(lag == 0);
return tsid+3*symbol_table.endo_nbr()+symbol_table.exo_nbr();
return tsid + 3 * symbol_table.endo_nbr() + symbol_table.exo_nbr();
}
else
throw UnknownDerivIDException();
}
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,12 +489,12 @@ 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;
void addAllParamDerivId(set<int>& deriv_id_set) override;
//! Returns true indicating that this is a dynamic model
bool
@ -496,7 +504,7 @@ public:
};
//! Drive test of detrended equations
void runTrendTest(const eval_context_t &eval_context);
void runTrendTest(const eval_context_t& eval_context);
//! Transforms the model by removing all leads greater or equal than 2 on endos
/*! Note that this can create new lags on endos and exos */
@ -515,25 +523,26 @@ 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)”
void substituteLogTransform();
// Check that no variable was declared with “var(log)” in the given equations
void checkNoWithLogTransform(const set<int> &eqnumbers);
void checkNoWithLogTransform(const set<int>& eqnumbers);
//! Transforms the model by removing trends specified by the user
void detrendEquations();
const nonstationary_symbols_map_t &
const nonstationary_symbols_map_t&
getNonstationarySymbolsMap() const
{
return nonstationary_symbols_map;
}
const map<int, expr_t> &
const map<int, expr_t>&
getTrendSymbolsMap() const
{
return trend_symbols_map;
@ -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 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
@ -570,7 +587,7 @@ public:
};
//! Return target of the pac equation
int getPacTargetSymbId(const string &pac_model_name) const;
int getPacTargetSymbId(const string& pac_model_name) const;
/* For a PAC MCE model, fill pac_expectation_substitution with the
expression that will be substituted for the pac_expectation operator.
@ -578,29 +595,22 @@ 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,
map<string, expr_t> &pac_expectation_substitution);
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,
map<string, int> &pac_aux_var_symb_ids,
map<string, vector<int>> &pac_aux_param_symb_ids,
map<string, expr_t> &pac_expectation_substitution);
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);
/* Same as above, but for PAC models which have an associated
pac_target_info.
@ -610,23 +620,21 @@ 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,
vector<PacModelTable::target_component_t> &pac_target_components,
map<string, expr_t> &pac_expectation_substitution);
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);
//! Substitutes pac_expectation operator with expectation based on auxiliary model
void substitutePacExpectation(const map<string, expr_t> &pac_expectation_substitution,
const map<string, string> &pac_eq_name);
void substitutePacExpectation(const map<string, expr_t>& pac_expectation_substitution,
const map<string, string>& pac_eq_name);
//! Substitutes the pac_target_nonstationary operator of a given pac_model
void substitutePacTargetNonstationary(const string &pac_model_name, expr_t substexpr);
void substitutePacTargetNonstationary(const string& pac_model_name, expr_t substexpr);
//! Table to undiff LHS variables for pac vector z
vector<int> getUndiffLHSForPac(const string &aux_model_name,
const ExprNode::subst_table_t &diff_subst_table) const;
vector<int> getUndiffLHSForPac(const string& aux_model_name,
const ExprNode::subst_table_t& diff_subst_table) const;
//! Transforms the model by replacing trend variables with a 1
void removeTrendVariableFromEquations();
@ -634,10 +642,10 @@ public:
//! Transforms the model by creating aux vars for the diff of forward vars
/*! If subset is empty, does the transformation for all fwrd vars; otherwise
restrict it to the vars in subset */
void differentiateForwardVars(const vector<string> &subset);
void differentiateForwardVars(const vector<string>& subset);
//! Fills eval context with values of model local variables and auxiliary variables
void fillEvalContext(eval_context_t &eval_context) const;
void fillEvalContext(eval_context_t& eval_context) const;
/*! Checks that all pac_expectation operators have been substituted, error
out otherwise */
@ -650,20 +658,22 @@ 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
bool ParamUsedWithLeadLag() const;
bool isChecksumMatching(const string &basename) const;
bool isChecksumMatching(const string& basename) const;
//! Simplify model equations: if a variable is equal to a constant, replace that variable elsewhere in the model
//! Simplify model equations: if a variable is equal to a constant, replace that variable
//! elsewhere in the model
/*! Equations with MCP tags are excluded, see dynare#1697 */
void simplifyEquations();
// Converts a set of equation tags into the corresponding set of equation numbers
set<int> getEquationNumbersFromTags(const set<string> &eqtags) const;
set<int> getEquationNumbersFromTags(const set<string>& eqtags) const;
// Returns the set of equations (as numbers) which have a pac_expectation operator
set<int> findPacExpectationEquationNumbers() const;
@ -689,17 +699,18 @@ public:
template<bool julia>
void
DynamicModel::writeParamsDerivativesFile(const string &basename) const
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)
if constexpr (!julia)
{
filesystem::path filename {packageDir(basename) / "dynamic_params_derivs.m"};
ofstream paramsDerivsFile {filename, ios::out | ios::binary};
@ -708,80 +719,160 @@ 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
<< "%" << 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
<< "% 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
<< "%" << 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
<< "%" << endl
<< "%" << endl
<< "% Warning : this file is generated automatically by Dynare" << endl
<< "% from model file (.mod)" << endl << endl
<< "T = NaN(" << params_derivs_temporary_terms_idxs.size() << ",1);" << endl
<< 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
<< "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
<< "if nargout >= 5" << endl
<< "hp = zeros(" << params_derivatives.at({ 2, 1 }).size() << ",5);" << 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
<< "end" << 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
<< "% 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
<< "%" << 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
<< "%" << endl
<< "%" << endl
<< "% Warning : this file is generated automatically by Dynare" << endl
<< "% from model file (.mod)" << endl
<< endl
<< "T = NaN(" << params_derivs_temporary_terms_idxs.size() << ",1);" << endl
<< 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
<< "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
<< "if nargout >= 5" << endl
<< "hp = zeros(" << params_derivatives.at({2, 1}).size() << ",5);" << 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
<< "end" << endl;
paramsDerivsFile.close();
}
else
@ -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,
vector<filesystem::path> paths);
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);
}
@ -65,23 +71,22 @@ usage()
the input stream afterwards).
This function should be kept in sync with the one with the same name in matlab/dynare.m */
vector<string>
parse_options_line(istream &modfile)
parse_options_line(istream& modfile)
{
vector<string> options;
string first_nonempty_line;
regex pat{R"(^\s*//\s*--\+\s*options:([^\+]*)\+--)"};
regex pat {R"(^\s*//\s*--\+\s*options:([^\+]*)\+--)"};
smatch matches;
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)
regex pat2 {R"([^,\s]+)"};
string s {matches[1]};
for (sregex_iterator p(s.begin(), s.end(), pat2); p != sregex_iterator {}; ++p)
options.push_back(p->str());
}
break;
@ -93,7 +98,7 @@ parse_options_line(istream &modfile)
}
int
main(int argc, char **argv)
main(int argc, char** argv)
{
/*
Redirect stderr to stdout.
@ -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;
@ -153,12 +159,12 @@ main(int argc, char **argv)
string exclude_eqs, include_eqs;
vector<pair<string, string>> defines;
vector<filesystem::path> paths;
OutputType output_mode{OutputType::standard};
JsonOutputPointType json{JsonOutputPointType::nojson};
JsonFileOutputType json_output_mode{JsonFileOutputType::file};
OutputType output_mode {OutputType::standard};
JsonOutputPointType json {JsonOutputPointType::nojson};
JsonFileOutputType json_output_mode {JsonFileOutputType::file};
bool onlyjson = false;
bool jsonderivsimple = false;
LanguageOutputType language{LanguageOutputType::matlab};
LanguageOutputType language {LanguageOutputType::matlab};
string mexext;
filesystem::path matlabroot;
bool onlymodel = false;
@ -289,9 +295,8 @@ main(int argc, char **argv)
usage();
}
if (auto equal_index = s.find('=');
equal_index != string::npos)
defines.emplace_back(s.substr(2, equal_index-2), s.substr(equal_index+1));
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");
}
@ -411,7 +416,7 @@ main(int argc, char **argv)
cerr << "Incorrect syntax for matlabroot option" << endl;
usage();
}
matlabroot = filesystem::path{s.substr(11)};
matlabroot = filesystem::path {s.substr(11)};
}
else if (s == "onlymodel")
onlymodel = true;
@ -431,7 +436,7 @@ main(int argc, char **argv)
cout << "Starting preprocessing of the model file ..." << endl;
// Determine root of Dynare installation
const filesystem::path argv0{argv[0]};
const filesystem::path argv0 {argv[0]};
// Normal case: binary is in preprocessor/dynare-preprocessor(.exe)?
filesystem::path dynareroot = argv0.parent_path().parent_path();
if (argv0.filename().stem() == "dynare_m")
@ -445,7 +450,7 @@ main(int argc, char **argv)
const string basename {filename.stem().string()};
// Forbid some basenames, since they will cause trouble (see preprocessor#62)
set<string> forbidden_basenames = { "T", "y", "x", "params", "steady_state", "it_", "true" };
set<string> forbidden_basenames = {"T", "y", "x", "params", "steady_state", "it_", "true"};
if (forbidden_basenames.contains(basename))
{
cerr << "ERROR: Please use another name for your .mod file. The one you have chosen ("
@ -456,22 +461,23 @@ 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();
// If Include option was passed to the [paths] block of the config file, add
// it to paths before macroprocessing
for (const auto &it : config_file.getIncludePaths())
for (const auto& it : config_file.getIncludePaths())
paths.emplace_back(it);
/*
* Macro-expand MOD file
*/
stringstream macro_output =
macroExpandModFile(filename, modfile, debug, save_macro, move(save_macro_file), line_macro,
defines, move(paths));
stringstream macro_output
= macroExpandModFile(filename, modfile, debug, save_macro, move(save_macro_file), line_macro,
defines, move(paths));
if (only_macro)
return EXIT_SUCCESS;
@ -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,63 +19,62 @@
#include "EquationTags.hh"
#include <regex>
#include <ostream>
#include <regex>
#include <utility>
set<int>
EquationTags::getEqnsByKey(const string &key) const
EquationTags::getEqnsByKey(const string& key) const
{
set<int> retval;
for (const auto & [eqn, tags] : eqn_tags)
for (const auto& [eqn, tags] : eqn_tags)
if (tags.contains(key))
retval.insert(eqn);
return retval;
}
set<int>
EquationTags::getEqnsByTag(const string &key, const string &value) const
EquationTags::getEqnsByTag(const string& key, const string& value) const
{
set<int> retval;
for (const auto & [eqn, tags] : eqn_tags)
for (const auto& [eqn, tags] : eqn_tags)
if (auto tmp = tags.find(key); tmp != tags.end() && tmp->second == value)
retval.insert(eqn);
return retval;
}
optional<int>
EquationTags::getEqnByTag(const string &key, const string &value) const
EquationTags::getEqnByTag(const string& key, const string& value) const
{
for (const auto & [eqn, tags] : eqn_tags)
for (const auto& [eqn, tags] : eqn_tags)
if (auto tmp = tags.find(key); tmp != tags.end() && tmp->second == value)
return eqn;
return nullopt;
}
set<int>
EquationTags::getEqnsByTags(const map<string, string> &tags_selected) const
EquationTags::getEqnsByTags(const map<string, string>& tags_selected) const
{
set<int> retval;
for (const auto &[eqn, tags] : eqn_tags)
for (const auto& [eqn, tags] : eqn_tags)
{
for (const auto &[key, value] : tags_selected)
for (const auto& [key, value] : tags_selected)
if (auto tmp = tags.find(key); tmp == tags.end() || tmp->second != value)
goto next_eq;
retval.insert(eqn);
next_eq:
;
next_eq:;
}
return retval;
}
void
EquationTags::erase(const set<int> &eqns, const map<int, int> &old_eqn_num_2_new)
EquationTags::erase(const set<int>& eqns, const map<int, int>& old_eqn_num_2_new)
{
for (int eqn : eqns)
eqn_tags.erase(eqn);
for (const auto & [oldeqn, neweqn] : old_eqn_num_2_new)
for (auto & [eqn, tags] : eqn_tags)
for (const auto& [oldeqn, neweqn] : old_eqn_num_2_new)
for (auto& [eqn, tags] : eqn_tags)
if (eqn == oldeqn)
{
auto tmp = eqn_tags.extract(eqn);
@ -85,38 +84,35 @@ EquationTags::erase(const set<int> &eqns, const map<int, int> &old_eqn_num_2_new
}
void
EquationTags::writeCheckSumInfo(ostream &output) const
EquationTags::writeCheckSumInfo(ostream& output) const
{
for (const auto & [eqn, tags] : eqn_tags)
for (const auto & [key, value] : tags)
output << " " << eqn + 1
<< key << " " << value << endl;
for (const auto& [eqn, tags] : eqn_tags)
for (const auto& [key, value] : tags)
output << " " << eqn + 1 << key << " " << value << endl;
}
void
EquationTags::writeOutput(ostream &output) const
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;
for (const auto& [eqn, tags] : eqn_tags)
for (const auto& [key, value] : tags)
output << " " << eqn + 1 << " , '" << key << "' , '" << value << "' ;" << endl;
output << "};" << endl;
}
void
EquationTags::writeLatexOutput(ostream &output, int eqn) const
EquationTags::writeLatexOutput(ostream& output, int eqn) const
{
if (!eqn_tags.contains(eqn))
return;
auto escape_special_latex_symbols = [](string str)
{
const regex special_latex_chars (R"([&%$#_{}])");
const regex backslash (R"(\\)");
const regex tilde (R"(~)");
const regex carrot (R"(\^)");
const regex textbackslash (R"(\\textbackslash)");
auto escape_special_latex_symbols = [](string str) {
const regex special_latex_chars(R"([&%$#_{}])");
const regex backslash(R"(\\)");
const regex tilde(R"(~)");
const regex carrot(R"(\^)");
const regex textbackslash(R"(\\textbackslash)");
str = regex_replace(str, backslash, R"(\textbackslash)");
str = regex_replace(str, special_latex_chars, R"(\$&)");
str = regex_replace(str, carrot, 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 << ", ";
@ -139,14 +134,13 @@ EquationTags::writeLatexOutput(ostream &output, int eqn) const
}
void
EquationTags::writeJsonAST(ostream &output, int eqn) const
EquationTags::writeJsonAST(ostream& output, int eqn) const
{
if (!eqn_tags.contains(eqn))
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,13 +31,14 @@ class EquationTags
{
private:
map<int, map<string, string>> eqn_tags;
public:
// Add multiple equation tags for the given equation
void
add(int eqn, map<string, string> tags)
{
if (eqn_tags.contains(eqn))
eqn_tags[eqn].insert(move_iterator{tags.begin()}, move_iterator{tags.end()});
eqn_tags[eqn].insert(move_iterator {tags.begin()}, move_iterator {tags.end()});
else
eqn_tags[eqn] = move(tags);
}
@ -58,7 +59,7 @@ public:
//! Erase tags for given equations, using old_eqn_num_2_new as the mapping
//! to use for the remaining equation numbers
void erase(const set<int> &eqns, const map<int, int> &old_eqn_num_2_new);
void erase(const set<int>& eqns, const map<int, int>& old_eqn_num_2_new);
//! Various functions to get info from equation tags
//! Get equation tags for a given equation
@ -71,20 +72,20 @@ public:
}
//! Get equations that have the given key
set<int> getEqnsByKey(const string &key) const;
set<int> getEqnsByKey(const string& key) const;
//! Get equations that have the given key and value
set<int> getEqnsByTag(const string &key, const string &value) const;
set<int> getEqnsByTag(const string& key, const string& value) const;
//! Get the first equation that has the given key and value
optional<int> getEqnByTag(const string &key, const string &value) const;
optional<int> getEqnByTag(const string& key, const string& value) const;
// Get equations that have all the given keys and values (seen as a conjunction)
set<int> getEqnsByTags(const map<string, string> &tags_selected) const;
set<int> getEqnsByTags(const map<string, string>& tags_selected) const;
//! Get the tag value given the equation number and key
optional<string>
getTagValueByEqnAndKey(int eqn, const string &key) const
getTagValueByEqnAndKey(int eqn, const string& key) const
{
if (auto it = eqn_tags.find(eqn); it != eqn_tags.end())
if (auto it2 = it->second.find(key); it2 != it->second.end())
@ -101,24 +102,24 @@ public:
//! Returns true if equation tag with key and value exists
bool
exists(const string &key, const string &value) const
exists(const string& key, const string& value) const
{
return getEqnByTag(key, value).has_value();
}
//! Returns true if equation tag with key exists for a given equation
bool
exists(int eqn, const string &key) const
exists(int eqn, const string& key) const
{
auto it = eqn_tags.find(eqn);
return it != eqn_tags.end() && it->second.contains(key);
}
//! Various functions to write equation tags
void writeCheckSumInfo(ostream &output) const;
void writeOutput(ostream &output) const;
void writeLatexOutput(ostream &output, int eqn) const;
void writeJsonAST(ostream &output, int eq) const;
void writeCheckSumInfo(ostream& output) const;
void writeOutput(ostream& output) const;
void writeLatexOutput(ostream& output, int eqn) const;
void writeJsonAST(ostream& output, int eq) const;
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -22,33 +22,33 @@
// Values for the “output” option
enum class OutputType
{
standard, // Default value, infer the derivation order from .mod file only
second, // Output at least 2nd dynamic derivatives
third, // Output at least 3rd dynamic derivatives
};
{
standard, // Default value, infer the derivation order from .mod file only
second, // Output at least 2nd dynamic derivatives
third, // Output at least 3rd dynamic derivatives
};
// Values for the “language” option
enum class LanguageOutputType
{
matlab, // outputs files for MATLAB/Octave processing
julia, // outputs files for Julia
};
{
matlab, // outputs files for MATLAB/Octave processing
julia, // outputs files for Julia
};
enum class JsonFileOutputType
{
file, // output JSON files to file
standardout, // output JSON files to stdout
};
{
file, // output JSON files to file
standardout, // output JSON files to stdout
};
// Values for the “json” option
enum class JsonOutputPointType
{
nojson, // don't output JSON
parsing, // output JSON after the parsing step
checkpass, // output JSON after the check pass
transformpass, // output JSON after the transform pass
computingpass // output JSON after the computing pass
};
{
nojson, // don't output JSON
parsing, // output JSON after the parsing step
checkpass, // output JSON after the check pass
transformpass, // output JSON after the transform pass
computingpass // output JSON after the computing pass
};
#endif

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,31 +84,28 @@ 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};
throw UnknownExternalFunctionSymbolIDException {symb_id};
}
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};
throw UnknownExternalFunctionSymbolIDException {symb_id};
}
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};
throw UnknownExternalFunctionSymbolIDException {symb_id};
}
#endif

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;
@ -43,7 +42,7 @@ macroExpandModFile(const filesystem::path &filename, const istream &modfile,
{
if (save_macro_file.empty())
save_macro_file = filename.stem().string() + "-macroexp.mod";
ofstream macro_output_file{save_macro_file};
ofstream macro_output_file {save_macro_file};
if (macro_output_file.fail())
{
cerr << "Cannot open " << save_macro_file.string() << " for macro output" << endl;

File diff suppressed because it is too large Load Diff

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;
@ -45,7 +45,7 @@ using namespace std;
class ModFile
{
public:
explicit ModFile(WarningConsolidation &warnings_arg);
explicit ModFile(WarningConsolidation& warnings_arg);
//! Symbol table
SymbolTable symbol_table;
//! External Functions table
@ -78,23 +78,24 @@ public:
SteadyStateModel steady_state_model;
//! Option linear
bool linear{false};
bool linear {false};
//! Was the “block” option passed to the “model” block?
bool block{false};
bool block {false};
//! Is the model stored in bytecode format (bytecode=true) or in a M-file (bytecode=false)
bool bytecode{false};
bool bytecode {false};
/*! Is the model stored in a MEX file ? (option “use_dll”, either in the
model block or on the preprocessor command line) */
bool use_dll{false};
bool use_dll {false};
//! Is the static model have to computed (no_static=false) or not (no_static=true). Option of 'model'
bool no_static{false};
//! 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?
bool differentiate_forward_vars{false};
bool differentiate_forward_vars {false};
/*! If the 'differentiate_forward_vars' option is used, contains the set of
endogenous with respect to which to do the transformation;
@ -103,14 +104,14 @@ public:
vector<string> differentiate_forward_vars_subset;
//! Are nonstationary variables present ?
bool nonstationary_variables{false};
bool nonstationary_variables {false};
//! Global evaluation context
/*! Filled using initval blocks and parameters initializations */
eval_context_t global_eval_context;
//! Parameter used with lead/lag
bool param_used_with_lead_lag{false};
bool param_used_with_lead_lag {false};
//! Stores the list of extra files to be transefered during a parallel run
/*! (i.e. option parallel_local_files of model block) */
@ -122,11 +123,13 @@ private:
//! Structure of the mod file
ModFileStructure mod_file_struct;
//! Warnings Encountered
WarningConsolidation &warnings;
WarningConsolidation& warnings;
//! Functions used in writing of JSON outut. See writeJsonOutput
void writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType json_output_mode, bool transformpass, bool computingpass) const;
void writeJsonComputingPassOutput(const string &basename, JsonFileOutputType json_output_mode, bool jsonderivsimple) const;
void writeJsonFileHelper(const filesystem::path &fname, ostringstream &output) 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
is no better portable solution. Maybe in a later C++ standard? */
@ -137,14 +140,16 @@ private:
same directory, otherwise it may fail if the destination is not on the
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);
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 */
@ -152,15 +157,16 @@ public:
//! Perform some transformations on the model (creation of auxiliary vars and equations)
/*! \param compute_xrefs if true, equation cross references will be computed */
void transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool transform_unary_ops,
const string &exclude_eqs, const string &include_eqs);
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?
@ -169,20 +175,23 @@ public:
\param mingw Should the MEX command of use_dll be adapted for MinGW?
\param compute_xrefs if true, equation cross references will be computed
*/
void writeMOutput(const string &basename, bool clear_all, bool clear_global, bool no_warn,
bool console, bool nograph, bool nointeractive, const ConfigFile &config_file,
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 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,69 +17,67 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <algorithm>
#include <cassert>
#include <sstream>
#include "ModelEquationBlock.hh"
PlannerObjective::PlannerObjective(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg) :
StaticModel {symbol_table_arg, num_constants_arg, external_functions_table_arg}
PlannerObjective::PlannerObjective(SymbolTable& symbol_table_arg,
NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg) :
StaticModel {symbol_table_arg, num_constants_arg, external_functions_table_arg}
{
}
void
PlannerObjective::computingPassBlock([[maybe_unused]] const eval_context_t &eval_context,
PlannerObjective::computingPassBlock([[maybe_unused]] const eval_context_t& eval_context,
[[maybe_unused]] bool no_tmp_terms)
{
// Disable block decomposition on planner objective
}
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) :
DynamicModel {symbol_table_arg, num_constants_arg, external_functions_table_arg,
trend_component_model_table_arg, var_model_table_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) :
DynamicModel {symbol_table_arg, num_constants_arg, external_functions_table_arg,
trend_component_model_table_arg, var_model_table_arg}
{
}
OrigRamseyDynamicModel &
OrigRamseyDynamicModel::operator=(const DynamicModel &m)
OrigRamseyDynamicModel&
OrigRamseyDynamicModel::operator=(const DynamicModel& m)
{
DynamicModel::operator=(m);
return *this;
}
SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg,
const StaticModel &static_model_arg) :
DataTree{symbol_table_arg, num_constants_arg, external_functions_table_arg},
static_model{static_model_arg}
SteadyStateModel::SteadyStateModel(SymbolTable& symbol_table_arg,
NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
const StaticModel& static_model_arg) :
DataTree {symbol_table_arg, num_constants_arg, external_functions_table_arg},
static_model {static_model_arg}
{
}
SteadyStateModel::SteadyStateModel(const SteadyStateModel &m) :
DataTree{m},
static_model{m.static_model}
SteadyStateModel::SteadyStateModel(const SteadyStateModel& m) :
DataTree {m}, static_model {m.static_model}
{
for (const auto &it : m.def_table)
for (const auto& it : m.def_table)
def_table.emplace_back(it.first, it.second->clone(*this));
}
SteadyStateModel &
SteadyStateModel::operator=(const SteadyStateModel &m)
SteadyStateModel&
SteadyStateModel::operator=(const SteadyStateModel& m)
{
DataTree::operator=(m);
assert(&static_model == &m.static_model);
def_table.clear();
for (const auto &it : m.def_table)
for (const auto& it : m.def_table)
def_table.emplace_back(it.first, it.second->clone(*this));
return *this;
@ -95,12 +93,12 @@ SteadyStateModel::addDefinition(int symb_id, expr_t expr)
|| symbol_table.getType(symb_id) == SymbolType::parameter);
// Add the variable
vector v{symb_id};
vector v {symb_id};
def_table.emplace_back(v, expr);
}
void
SteadyStateModel::addMultipleDefinitions(const vector<int> &symb_ids, expr_t expr)
SteadyStateModel::addMultipleDefinitions(const vector<int>& symb_ids, expr_t expr)
{
for (int symb_id : symb_ids)
{
@ -113,7 +111,7 @@ SteadyStateModel::addMultipleDefinitions(const vector<int> &symb_ids, expr_t exp
}
void
SteadyStateModel::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) const
SteadyStateModel::checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) const
{
if (def_table.size() == 0)
return;
@ -121,12 +119,13 @@ SteadyStateModel::checkPass(ModFileStructure &mod_file_struct, WarningConsolidat
mod_file_struct.steady_state_model_present = true;
set<int> so_far_defined;
for (const auto &[symb_ids, expr] : def_table)
for (const auto& [symb_ids, expr] : def_table)
{
// 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);
}
}
@ -151,29 +152,30 @@ SteadyStateModel::checkPass(ModFileStructure &mod_file_struct, WarningConsolidat
*conditional* to those instruments) */
set<int> should_be_defined = symbol_table.getOrigEndogenous();
if (mod_file_struct.ramsey_model_present)
for (const auto &s : mod_file_struct.instruments.getSymbols())
for (const auto& s : mod_file_struct.instruments.getSymbols())
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
SteadyStateModel::writeLatexSteadyStateFile(const string &basename) const
SteadyStateModel::writeLatexSteadyStateFile(const string& basename) const
{
filesystem::create_directories(basename + "/latex");
const filesystem::path filename {basename + "/latex/steady_state.tex"},
content_filename {basename + "/latex/steady_state_content.tex"};
content_filename {basename + "/latex/steady_state_content.tex"};
ofstream output{filename, ios::out | ios::binary};
ofstream output {filename, ios::out | ios::binary};
if (!output.is_open())
{
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
exit(EXIT_FAILURE);
}
ofstream content_output{content_filename, ios::out | ios::binary};
ofstream content_output {content_filename, ios::out | ios::binary};
if (!content_output.is_open())
{
cerr << "ERROR: Can't open file " << content_filename.string() << " for writing" << endl;
@ -188,31 +190,30 @@ SteadyStateModel::writeLatexSteadyStateFile(const string &basename) const
<< "\\begin{document}" << endl
<< "\\footnotesize" << endl;
for (const auto & [ids, value] : def_table)
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();
}
void
SteadyStateModel::writeSteadyStateFile(const string &basename, bool julia) const
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)
@ -226,9 +227,9 @@ SteadyStateModel::writeSteadyStateFile(const string &basename, bool julia) const
<< "#" << endl
<< "function steady_state!(ys_::Vector{<: Real}, exo_::Vector{<: Real}, "
<< "params::Vector{<: Real})" << endl
<< "@inbounds begin" << endl;
<< "@inbounds begin" << endl;
for (const auto & [symb_ids, value] : def_table)
for (const auto& [symb_ids, value] : def_table)
{
output << " ";
if (symb_ids.size() > 1)
@ -236,7 +237,7 @@ SteadyStateModel::writeSteadyStateFile(const string &basename, bool julia) const
for (size_t j = 0; j < symb_ids.size(); j++)
{
getVariable(symb_ids[j])->ExprNode::writeOutput(output, output_type);
if (j < symb_ids.size()-1)
if (j < symb_ids.size() - 1)
output << ",";
}
if (symb_ids.size() > 1)
@ -257,13 +258,14 @@ 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
a subdirectory deleted at each preprocessor run. */
filesystem::path filename {packageDir(basename) / "steadystate.m"};
ofstream output_file{filename, ios::out | ios::binary};
ofstream output_file {filename, ios::out | ios::binary};
if (!output_file.is_open())
{
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
@ -275,7 +277,7 @@ SteadyStateModel::writeSteadyStateFile(const string &basename, bool julia) const
}
void
SteadyStateModel::writeJsonSteadyStateFile(ostream &output, bool transformComputingPass) const
SteadyStateModel::writeJsonSteadyStateFile(ostream& output, bool transformComputingPass) const
{
if (def_table.size() == 0)
return;
@ -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,30 +314,28 @@ SteadyStateModel::writeJsonSteadyStateFile(ostream &output, bool transformComput
output << "]}";
}
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) :
DynamicModel{symbol_table_arg, num_constants_arg, external_functions_table_arg,
trend_component_model_table_arg, var_model_table_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) :
DynamicModel {symbol_table_arg, num_constants_arg, external_functions_table_arg,
trend_component_model_table_arg, var_model_table_arg}
{
}
Epilogue::Epilogue(const Epilogue &m) :
DynamicModel{m}
Epilogue::Epilogue(const Epilogue& m) : DynamicModel {m}
{
for (const auto &it : m.dynamic_def_table)
for (const auto& it : m.dynamic_def_table)
dynamic_def_table.emplace_back(it.first, it.second->clone(*this));
}
Epilogue &
Epilogue::operator=(const Epilogue &m)
Epilogue&
Epilogue::operator=(const Epilogue& m)
{
DynamicModel::operator=(m);
dynamic_def_table.clear();
for (const auto &it : m.dynamic_def_table)
for (const auto& it : m.dynamic_def_table)
dynamic_def_table.emplace_back(it.first, it.second->clone(*this));
return *this;
@ -350,20 +348,22 @@ Epilogue::addDefinition(int symb_id, expr_t expr)
}
void
Epilogue::checkPass(ModFileStructure &mod_file_struct) const
Epilogue::checkPass(ModFileStructure& mod_file_struct) const
{
if (dynamic_def_table.size() == 0)
{
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;
}
set<int> so_far_defined;
for (const auto &[symb_id, expr] : dynamic_def_table)
for (const auto& [symb_id, expr] : dynamic_def_table)
if (so_far_defined.contains(symb_id))
{
cerr << "WARNING: in the 'epilogue' block, variable '" << symbol_table.getName(symb_id)
@ -377,29 +377,28 @@ Epilogue::checkPass(ModFileStructure &mod_file_struct) const
void
Epilogue::toStatic()
{
for (const auto & [symb_id, expr] : dynamic_def_table)
for (const auto& [symb_id, expr] : dynamic_def_table)
static_def_table.emplace_back(symb_id, expr->toStatic(*this));
}
void
Epilogue::detrend(const map<int, expr_t> &trend_symbols_map,
const nonstationary_symbols_map_t &nonstationary_symbols_map)
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 & [symb_id, expr] : dynamic_def_table)
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);
assert(expr);
}
for (auto & [symb_id, expr] : dynamic_def_table)
for (auto& [symb_id, expr] : dynamic_def_table)
{
expr = expr->removeTrendLeadLag(trend_symbols_map);
assert(expr);
}
for (auto & [symb_id, expr] : dynamic_def_table)
for (auto& [symb_id, expr] : dynamic_def_table)
{
expr = expr->replaceTrendVar();
assert(expr);
@ -407,7 +406,7 @@ Epilogue::detrend(const map<int, expr_t> &trend_symbols_map,
}
void
Epilogue::writeEpilogueFile(const string &basename) const
Epilogue::writeEpilogueFile(const string& basename) const
{
if (dynamic_def_table.empty())
return;
@ -417,10 +416,10 @@ Epilogue::writeEpilogueFile(const string &basename) const
}
void
Epilogue::writeStaticEpilogueFile(const string &basename) const
Epilogue::writeStaticEpilogueFile(const string& basename) const
{
filesystem::path filename {packageDir(basename) / "epilogue_static.m"};
ofstream output{filename, ios::out | ios::binary};
ofstream output {filename, ios::out | ios::binary};
if (!output.is_open())
{
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
@ -431,23 +430,27 @@ Epilogue::writeStaticEpilogueFile(const string &basename) const
<< "% function ds = epilogue_static(params, ds)" << endl
<< "% Epilogue file generated by Dynare preprocessor" << endl;
for (const auto & [symb_id, expr] : static_def_table)
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;
@ -455,10 +458,10 @@ Epilogue::writeStaticEpilogueFile(const string &basename) const
}
void
Epilogue::writeDynamicEpilogueFile(const string &basename) const
Epilogue::writeDynamicEpilogueFile(const string& basename) const
{
filesystem::path filename {packageDir(basename) / "epilogue_dynamic.m"};
ofstream output{filename, ios::out | ios::binary};
ofstream output {filename, ios::out | ios::binary};
if (!output.is_open())
{
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
@ -467,13 +470,14 @@ 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;
temporary_terms_t temporary_terms;
temporary_terms_idxs_t temporary_terms_idxs;
for (const auto & [symb_id, expr] : dynamic_def_table)
for (const auto& [symb_id, expr] : dynamic_def_table)
{
int max_lag = expr->maxLagWithDiffsExpanded();
set<int> used_symbols;
@ -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,43 +501,40 @@ 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();
}
void
Epilogue::writeOutput(ostream &output) const
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)
for (const auto& [symb_id, expr] : dynamic_def_table)
expr->collectVariables(SymbolType::endogenous, endogs);
vector<string> symbol_list;
for (auto symb_id : endogs)
symbol_list.push_back(symbol_table.getName(symb_id));
SymbolList{move(symbol_list)}.writeOutput("M_.epilogue_var_list_", output);
SymbolList {move(symbol_list)}.writeOutput("M_.epilogue_var_list_", output);
}
void
Epilogue::computingPassBlock([[maybe_unused]] const eval_context_t &eval_context,
Epilogue::computingPassBlock([[maybe_unused]] const eval_context_t& eval_context,
[[maybe_unused]] bool no_tmp_terms)
{
// Disable block decomposition on epilogue blocks

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,
ExternalFunctionsTable &external_functions_table_arg);
PlannerObjective(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg);
protected:
string
modelClassName() const override
@ -40,18 +40,17 @@ protected:
}
private:
void computingPassBlock(const eval_context_t &eval_context, bool no_tmp_terms) override;
void computingPassBlock(const eval_context_t& eval_context, bool no_tmp_terms) override;
};
class OrigRamseyDynamicModel : public DynamicModel
{
public:
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);
OrigRamseyDynamicModel &operator=(const DynamicModel &m);
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);
OrigRamseyDynamicModel& operator=(const DynamicModel& m);
protected:
string
@ -64,71 +63,73 @@ 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;
const StaticModel& static_model;
public:
SteadyStateModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg,
const StaticModel &static_model_arg);
SteadyStateModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
const StaticModel& static_model_arg);
SteadyStateModel(const SteadyStateModel &m);
SteadyStateModel &operator=(const SteadyStateModel &m);
SteadyStateModel(const SteadyStateModel& m);
SteadyStateModel& operator=(const SteadyStateModel& m);
//! Add an expression of the form "var = expr;"
void addDefinition(int symb_id, expr_t expr);
//! Add an expression of the form "[ var1, var2, ... ] = expr;"
void addMultipleDefinitions(const vector<int> &symb_ids, expr_t expr);
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;
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) const;
//! Write the steady state file
void writeSteadyStateFile(const string &basename, bool julia) const;
void writeSteadyStateFile(const string& basename, bool julia) const;
//! Writes LaTeX file with the equations of the dynamic model (for the steady state model)
void writeLatexSteadyStateFile(const string &basename) const;
void writeLatexSteadyStateFile(const string& basename) const;
//! Writes JSON output
void writeJsonSteadyStateFile(ostream &output, bool transformComputingPass) const;
void writeJsonSteadyStateFile(ostream& output, bool transformComputingPass) const;
};
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,
ExternalFunctionsTable &external_functions_table_arg,
TrendComponentModelTable &trend_component_model_table_arg,
VarModelTable &var_model_table_arg);
Epilogue(const Epilogue &m);
Epilogue &operator=(const Epilogue &m);
public:
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);
Epilogue(const Epilogue& m);
Epilogue& operator=(const Epilogue& m);
//! Add an expression of the form "var = expr;"
void addDefinition(int symb_id, expr_t expr);
//! Checks that no variable is declared twice, and that “with_epilogue” is not misused
void checkPass(ModFileStructure &mod_file_struct) const;
void checkPass(ModFileStructure& mod_file_struct) const;
//! Creates static epilogue equations
void toStatic();
//! Deal with trend variables in the epilogue block
void detrend(const map<int, expr_t> &trend_symbols_map,
const nonstationary_symbols_map_t &nonstationary_symbols_map);
void detrend(const map<int, expr_t>& trend_symbols_map,
const nonstationary_symbols_map_t& nonstationary_symbols_map);
//! Write the steady state file
void writeEpilogueFile(const string &basename) const;
void writeEpilogueFile(const string& basename) const;
//! Write Output
void writeOutput(ostream &output) const;
void writeOutput(ostream& output) const;
protected:
string
@ -139,9 +140,9 @@ protected:
private:
//! Helper for public writeEpilogueFile
void writeStaticEpilogueFile(const string &basename) const;
void writeDynamicEpilogueFile(const string &basename) const;
void computingPassBlock(const eval_context_t &eval_context, bool no_tmp_terms) override;
void writeStaticEpilogueFile(const string& basename) const;
void writeDynamicEpilogueFile(const string& basename) const;
void computingPassBlock(const eval_context_t& eval_context, bool no_tmp_terms) override;
};
#endif

File diff suppressed because it is too large Load Diff

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)
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,9 +36,10 @@ 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);
int AddNonNegativeConstant(const string& iConst);
//! Get a constant in string form
string get(int ID) const;
//! Get a constant in double form

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,
const SymbolTable &symbol_table_arg) :
symb_id{symb_id_arg},
param_value{param_value_arg},
symbol_table{symbol_table_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}
{
}
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 << ") = ";
@ -57,44 +57,46 @@ InitParamStatement::writeOutput(ostream &output, [[maybe_unused]] const string &
}
void
InitParamStatement::writeJsonOutput(ostream &output) const
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"("})";
}
void
InitParamStatement::fillEvalContext(eval_context_t &eval_context) const
InitParamStatement::fillEvalContext(eval_context_t& eval_context) const
{
try
{
eval_context[symb_id] = param_value->eval(eval_context);
}
catch (ExprNode::EvalException &e)
catch (ExprNode::EvalException& e)
{
// Do nothing
}
}
InitOrEndValStatement::InitOrEndValStatement(init_values_t init_values_arg,
const SymbolTable &symbol_table_arg,
const SymbolTable& symbol_table_arg,
bool all_values_required_arg) :
init_values{move(init_values_arg)},
symbol_table{symbol_table_arg},
all_values_required{all_values_required_arg}
init_values {move(init_values_arg)},
symbol_table {symbol_table_arg},
all_values_required {all_values_required_arg}
{
}
void
InitOrEndValStatement::fillEvalContext(eval_context_t &eval_context) const
InitOrEndValStatement::fillEvalContext(eval_context_t& eval_context) const
{
for (auto [symb_id, value] : init_values)
try
{
eval_context[symb_id] = value->eval(eval_context);
}
catch (ExprNode::EvalException &e)
catch (ExprNode::EvalException& e)
{
// Do nothing
}
@ -124,7 +126,7 @@ InitOrEndValStatement::getUninitializedVariables(SymbolType type)
}
void
InitOrEndValStatement::writeInitValues(ostream &output) const
InitOrEndValStatement::writeInitValues(ostream& output) const
{
for (auto [symb_id, value] : init_values)
{
@ -161,31 +163,31 @@ InitOrEndValStatement::writeInitValues(ostream &output) const
}
void
InitOrEndValStatement::writeJsonInitValues(ostream &output) const
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"("})";
}
}
InitValStatement::InitValStatement(init_values_t init_values_arg,
const SymbolTable &symbol_table_arg,
const SymbolTable& symbol_table_arg,
bool all_values_required_arg) :
InitOrEndValStatement{move(init_values_arg), symbol_table_arg, all_values_required_arg}
InitOrEndValStatement {move(init_values_arg), symbol_table_arg, all_values_required_arg}
{
}
void
InitValStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct,
[[maybe_unused]] WarningConsolidation &warnings)
InitValStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if (mod_file_struct.endval_present)
{
@ -217,12 +219,10 @@ InitValStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct,
}
void
InitValStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
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;
@ -230,7 +230,7 @@ InitValStatement::writeOutput(ostream &output, [[maybe_unused]] const string &ba
}
void
InitValStatement::writeJsonOutput(ostream &output) const
InitValStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "initval", "vals": [)";
writeJsonInitValues(output);
@ -238,26 +238,25 @@ InitValStatement::writeJsonOutput(ostream &output) const
}
void
InitValStatement::writeOutputPostInit(ostream &output) const
InitValStatement::writeOutputPostInit(ostream& output) const
{
output << "if M_.exo_nbr > 0" << endl
<< "\too_.exo_simul = ones(M_.maximum_lag,1)*oo_.exo_steady_state';" << endl
<<"end" << endl
<< "end" << endl
<< "if M_.exo_det_nbr > 0" << endl
<< "\too_.exo_det_simul = ones(M_.maximum_lag,1)*oo_.exo_det_steady_state';" << endl
<<"end" << endl;
<< "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}
InitOrEndValStatement {move(init_values_arg), symbol_table_arg, all_values_required_arg}
{
}
void
EndValStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct,
[[maybe_unused]] WarningConsolidation &warnings)
EndValStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.endval_present = true;
@ -285,12 +284,10 @@ EndValStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct,
}
void
EndValStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
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;
@ -299,7 +296,7 @@ EndValStatement::writeOutput(ostream &output, [[maybe_unused]] const string &bas
}
void
EndValStatement::writeJsonOutput(ostream &output) const
EndValStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "endval", "vals": [)";
writeJsonInitValues(output);
@ -308,16 +305,16 @@ EndValStatement::writeJsonOutput(ostream &output) const
EndValLearntInStatement::EndValLearntInStatement(int learnt_in_period_arg,
learnt_end_values_t learnt_end_values_arg,
const SymbolTable &symbol_table_arg) :
learnt_in_period{learnt_in_period_arg},
learnt_end_values{move(learnt_end_values_arg)},
symbol_table{symbol_table_arg}
const SymbolTable& symbol_table_arg) :
learnt_in_period {learnt_in_period_arg},
learnt_end_values {move(learnt_end_values_arg)},
symbol_table {symbol_table_arg}
{
}
void
EndValLearntInStatement::checkPass(ModFileStructure &mod_file_struct,
[[maybe_unused]] WarningConsolidation &warnings)
EndValLearntInStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.endval_learnt_in_present = true;
}
@ -338,7 +335,7 @@ EndValLearntInStatement::typeToString(LearntEndValType type)
}
void
EndValLearntInStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
EndValLearntInStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "M_.learnt_endval = [ M_.learnt_endval;" << 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;
@ -357,12 +354,10 @@ EndValLearntInStatement::writeOutput(ostream &output, [[maybe_unused]] const str
}
void
EndValLearntInStatement::writeJsonOutput(ostream &output) const
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;
@ -378,24 +373,24 @@ EndValLearntInStatement::writeJsonOutput(ostream &output) const
}
HistValStatement::HistValStatement(hist_values_t hist_values_arg,
const SymbolTable &symbol_table_arg,
const SymbolTable& symbol_table_arg,
bool all_values_required_arg) :
hist_values{move(hist_values_arg)},
symbol_table{symbol_table_arg},
all_values_required{all_values_required_arg}
hist_values {move(hist_values_arg)},
symbol_table {symbol_table_arg},
all_values_required {all_values_required_arg}
{
}
void
HistValStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct,
[[maybe_unused]] WarningConsolidation &warnings)
HistValStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if (all_values_required)
{
set<int> unused_endo = symbol_table.getEndogenous();
set<int> unused_exo = symbol_table.getExogenous();
for (const auto &[key, value] : hist_values)
for (const auto& [key, value] : hist_values)
{
int symb_id = key.first;
unused_endo.erase(symb_id);
@ -424,60 +419,71 @@ HistValStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct,
}
void
HistValStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
HistValStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
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)
for (const auto& [key, value] : hist_values)
{
auto [symb_id, lag] = key;
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
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;
auto& [symb_id, lag] = key;
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"(, "lag": )" << lag
<< R"(, "value": ")";
<< R"(, "lag": )" << lag << R"(, "value": ")";
value->writeJsonOutput(output, {}, {});
output << R"("})";
}
@ -485,12 +491,12 @@ HistValStatement::writeJsonOutput(ostream &output) const
}
InitvalFileStatement::InitvalFileStatement(OptionsList options_list_arg) :
options_list{move(options_list_arg)}
options_list {move(options_list_arg)}
{
}
void
InitvalFileStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
InitvalFileStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "%" << endl
@ -498,11 +504,13 @@ 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
InitvalFileStatement::writeJsonOutput(ostream &output) const
InitvalFileStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "initval_file")";
if (!options_list.empty())
@ -514,12 +522,12 @@ InitvalFileStatement::writeJsonOutput(ostream &output) const
}
HistvalFileStatement::HistvalFileStatement(OptionsList options_list_arg) :
options_list{move(options_list_arg)}
options_list {move(options_list_arg)}
{
}
void
HistvalFileStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
HistvalFileStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "%" << endl
@ -527,11 +535,13 @@ 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
HistvalFileStatement::writeJsonOutput(ostream &output) const
HistvalFileStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "histval_file")";
if (!options_list.empty())
@ -544,21 +554,22 @@ HistvalFileStatement::writeJsonOutput(ostream &output) const
HomotopySetupStatement::HomotopySetupStatement(bool from_initval_to_endval_arg,
homotopy_values_t homotopy_values_arg,
const SymbolTable &symbol_table_arg) :
from_initval_to_endval{from_initval_to_endval_arg},
homotopy_values{move(homotopy_values_arg)},
symbol_table{symbol_table_arg}
const SymbolTable& symbol_table_arg) :
from_initval_to_endval {from_initval_to_endval_arg},
homotopy_values {move(homotopy_values_arg)},
symbol_table {symbol_table_arg}
{
}
void
HomotopySetupStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
HomotopySetupStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
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
@ -578,12 +590,12 @@ HomotopySetupStatement::writeOutput(ostream &output, [[maybe_unused]] const stri
}
void
HomotopySetupStatement::writeJsonOutput(ostream &output) const
HomotopySetupStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "homotopy", )"
<< R"("values": [)";
for (bool printed_something{false};
const auto &[symb_id, expression1, expression2] : homotopy_values)
for (bool printed_something {false};
const auto& [symb_id, expression1, expression2] : homotopy_values)
{
if (exchange(printed_something, true))
output << ", ";
@ -603,29 +615,30 @@ HomotopySetupStatement::writeJsonOutput(ostream &output) const
}
SaveParamsAndSteadyStateStatement::SaveParamsAndSteadyStateStatement(string filename_arg) :
filename{move(filename_arg)}
filename {move(filename_arg)}
{
}
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;
}
void
SaveParamsAndSteadyStateStatement::writeJsonOutput(ostream &output) const
SaveParamsAndSteadyStateStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "save_params_and_steady_state")"
<< R"(, "filename": ")" << filename << R"(")"
<< "}";
}
LoadParamsAndSteadyStateStatement::LoadParamsAndSteadyStateStatement(const filesystem::path &filename,
const SymbolTable &symbol_table_arg,
WarningConsolidation &warnings) :
symbol_table{symbol_table_arg}
LoadParamsAndSteadyStateStatement::LoadParamsAndSteadyStateStatement(
const filesystem::path& filename, const SymbolTable& symbol_table_arg,
WarningConsolidation& warnings) :
symbol_table {symbol_table_arg}
{
cout << "Reading " << filename.string() << "." << endl;
@ -649,19 +662,21 @@ LoadParamsAndSteadyStateStatement::LoadParamsAndSteadyStateStatement(const files
int symb_id = symbol_table.getID(symb_name);
content[symb_id] = value;
}
catch (SymbolTable::UnknownSymbolNameException &e)
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)
for (const auto& [id, value] : content)
{
switch (symbol_table.getType(id))
{
@ -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);
}
@ -688,12 +704,11 @@ LoadParamsAndSteadyStateStatement::writeOutput(ostream &output, [[maybe_unused]]
}
void
LoadParamsAndSteadyStateStatement::writeJsonOutput(ostream &output) const
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 << ", ";
@ -705,9 +720,9 @@ LoadParamsAndSteadyStateStatement::writeJsonOutput(ostream &output) const
}
void
LoadParamsAndSteadyStateStatement::fillEvalContext(eval_context_t &eval_context) const
LoadParamsAndSteadyStateStatement::fillEvalContext(eval_context_t& eval_context) const
{
for (const auto & [id, value] : content)
for (const auto& [id, value] : content)
/* We use strtod() instead of stod() because we want underflows and
overflows to respectively yield 0 and ±Inf. See also the comment in
NumericalConstants.cc */

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;
@ -36,15 +36,16 @@ class InitParamStatement : public Statement
private:
const int symb_id;
const expr_t param_value;
const SymbolTable &symbol_table;
const SymbolTable& symbol_table;
public:
InitParamStatement(int symb_id_arg, const expr_t param_value_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;
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;
//! Fill eval context with parameter value
void fillEvalContext(eval_context_t &eval_context) const;
void fillEvalContext(eval_context_t& eval_context) const;
};
class InitOrEndValStatement : public Statement
@ -55,46 +56,46 @@ 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 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;
void fillEvalContext(eval_context_t& eval_context) const;
protected:
void writeInitValues(ostream &output) const;
void writeJsonInitValues(ostream &output) const;
void writeInitValues(ostream& output) const;
void writeJsonInitValues(ostream& output) const;
};
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;
void writeJsonOutput(ostream &output) const override;
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;
//! Writes initializations for oo_.exo_simul and oo_.exo_det_simul
void writeOutputPostInit(ostream &output) const;
void writeOutputPostInit(ostream& output) const;
};
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;
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class EndValLearntInStatement : public Statement
@ -102,24 +103,25 @@ class EndValLearntInStatement : public Statement
public:
const int learnt_in_period;
enum class LearntEndValType
{
level,
add,
multiply
};
{
level,
add,
multiply
};
// 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;
const SymbolTable& symbol_table;
static string typeToString(LearntEndValType type);
public:
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;
void writeJsonOutput(ostream &output) const override;
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;
void writeJsonOutput(ostream& output) const override;
};
class HistValStatement : public Statement
@ -131,38 +133,41 @@ 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 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;
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class 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;
void writeJsonOutput(ostream &output) const override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
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;
void writeJsonOutput(ostream &output) const override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class HomotopySetupStatement : public Statement
@ -171,42 +176,46 @@ 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;
const SymbolTable& symbol_table;
public:
HomotopySetupStatement(bool from_initval_to_endval_arg, homotopy_values_t homotopy_values_arg,
const SymbolTable &symbol_table_arg);
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
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;
void writeJsonOutput(ostream &output) const override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class LoadParamsAndSteadyStateStatement : public Statement
{
private:
const SymbolTable &symbol_table;
const SymbolTable& symbol_table;
//! 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,
WarningConsolidation &warnings);
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
LoadParamsAndSteadyStateStatement(const filesystem::path& filename,
const SymbolTable& symbol_table_arg,
WarningConsolidation& warnings);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
//! Fill eval context with parameters/variables values
void fillEvalContext(eval_context_t &eval_context) const;
void writeJsonOutput(ostream &output) const override;
void fillEvalContext(eval_context_t& eval_context) const;
void writeJsonOutput(ostream& output) const override;
};
#endif

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;
@ -59,22 +59,21 @@ using namespace std;
class DynareFlex : public DynareFlexLexer
{
public:
DynareFlex(istream *in = nullptr, ostream *out = nullptr);
DynareFlex(istream* in = nullptr, ostream* out = nullptr);
DynareFlex(const DynareFlex &) = delete;
DynareFlex &operator=(const DynareFlex &) = delete;
DynareFlex(const DynareFlex&) = delete;
DynareFlex& operator=(const DynareFlex&) = delete;
//! The main lexing function
Dynare::parser::token_type lex(Dynare::parser::semantic_type *yylval,
Dynare::parser::location_type *yylloc,
ParsingDriver &driver);
Dynare::parser::token_type lex(Dynare::parser::semantic_type* yylval,
Dynare::parser::location_type* yylloc, ParsingDriver& driver);
//! The filename being parsed
/*! The bison parser locations (begin and end) contain a pointer to that string */
string filename;
//! Increment the location counter given a token
static void location_increment(Dynare::parser::location_type *yylloc, const char *yytext);
static void location_increment(Dynare::parser::location_type* yylloc, const char* yytext);
//! Count parens in dates statement
int dates_parens_nb;
@ -86,29 +85,34 @@ class ParsingDriver
{
private:
//! Checks that a given symbol exists, and stops with an error message if it doesn't
void check_symbol_existence(const string &name);
void check_symbol_existence(const string& name);
//! Checks that a given symbol exists and is a parameter, and stops with an error message if it isn't
void check_symbol_is_parameter(const string &name);
//! Checks that a given symbol exists and is a parameter, and stops with an error message if it
//! isn't
void check_symbol_is_parameter(const string& name);
//! Checks that a given symbol was assigned within a Statement
void check_symbol_is_statement_variable(const string &name);
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
void check_symbol_is_endogenous_or_exogenous(const string &name, bool allow_exo_det);
//! 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
void check_symbol_is_endogenous(const string &name);
//! 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
void check_symbol_is_exogenous(const string &name, bool allow_exo_det);
//! 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
void check_symbol_existence_in_model_block(const string &name);
//! Checks for symbol existence in model block. If it doesn't exist, an error message is stored to
//! be printed at the end of the model block
void check_symbol_existence_in_model_block(const string& name);
//! Helper to add a symbol declaration (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;
@ -119,18 +123,20 @@ private:
//! The data tree in which to add expressions currently parsed
/*! The object pointed to is not owned by the parsing driver. It is essentially a
reference. */
DataTree *data_tree;
DataTree* data_tree;
//! The model tree in which to add expressions currently parsed
/*! It is only a dynamic cast of data_tree pointer, and is therefore null if data_tree is not a ModelTree instance */
ModelTree *model_tree;
/*! It is only a dynamic cast of data_tree pointer, and is therefore null if data_tree is not a
* ModelTree instance */
ModelTree* model_tree;
//! The dynamic model tree in which to add expressions currently parsed
/*! It is only a dynamic cast of data_tree pointer, and is therefore null if data_tree is not a DynamicModel instance */
DynamicModel *dynamic_model;
/*! It is only a dynamic cast of data_tree pointer, and is therefore null if data_tree is not a
* DynamicModel instance */
DynamicModel* dynamic_model;
//! Sets data_tree and model_tree pointers
void set_current_data_tree(DataTree *data_tree_arg);
void set_current_data_tree(DataTree* data_tree_arg);
//! Stores options lists
OptionsList options_list;
@ -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;
@ -200,11 +209,11 @@ private:
set<string> undeclared_model_vars;
//! Temporary storage for restriction type
enum class SvarRestrictionType
{
NOT_SET,
Qi_TYPE,
Ri_TYPE
};
{
NOT_SET,
Qi_TYPE,
Ri_TYPE
};
SvarRestrictionType svar_restriction_type;
//! Temporary storage for generate_irfs
vector<string> generate_irf_names;
@ -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;
@ -231,7 +243,7 @@ private:
vector<pair<int, int>> init2shocks;
/* Temporary storage for planner_discount and planner_discount_latex_name
options of ramsey_model and ramsey_policy */
expr_t planner_discount{nullptr};
expr_t planner_discount {nullptr};
string planner_discount_latex_name;
//! reset the values for temporary storage
void reset_current_external_function_options();
@ -246,7 +258,7 @@ private:
//! The mod file representation constructed by this ParsingDriver
unique_ptr<ModFile> mod_file;
WarningConsolidation &warnings;
WarningConsolidation& warnings;
//! Temporary storage for several options of pac_model
expr_t pac_growth;
@ -259,27 +271,27 @@ private:
vector<pair<string, string>> undeclared_model_variable_errors;
//! True when parsing the epilogue block
bool parsing_epilogue{false};
bool parsing_epilogue {false};
//! True when parsing pac_model statement
bool parsing_pac_model{false};
bool parsing_pac_model {false};
//! True if a ramsey_model statement has already been seen
bool ramsey_model_seen{false};
bool ramsey_model_seen {false};
//! True if a ramsey_policy statement has already been seen
bool ramsey_policy_seen{false};
bool ramsey_policy_seen {false};
public:
ParsingDriver(WarningConsolidation &warnings_arg, bool nostrict_arg) :
warnings{warnings_arg}, nostrict{nostrict_arg}
ParsingDriver(WarningConsolidation& warnings_arg, bool nostrict_arg) :
warnings {warnings_arg}, nostrict {nostrict_arg}
{
};
}
ParsingDriver(const ParsingDriver &) = delete;
ParsingDriver &operator=(const ParsingDriver &) = delete;
ParsingDriver(const ParsingDriver&) = delete;
ParsingDriver& operator=(const ParsingDriver&) = delete;
//! Starts parsing, and constructs the MOD file representation
unique_ptr<ModFile> parse(istream &in, bool debug);
unique_ptr<ModFile> parse(istream& in, bool debug);
//! Reference to the lexer
unique_ptr<DynareFlex> lexer;
@ -297,27 +309,30 @@ public:
PriorDistributions prior_shape;
//! Temporary storage for "expression" option of VAR_EXPECTATION_MODEL
expr_t var_expectation_model_expression{nullptr};
expr_t var_expectation_model_expression {nullptr};
//! Temporary storage for discount option of VAR_EXPECTATION_MODEL
expr_t var_expectation_model_discount{nullptr};
expr_t var_expectation_model_discount {nullptr};
//! Error handler with explicit location
void error(const Dynare::parser::location_type &l, const string &m) __attribute__ ((noreturn));
void error(const Dynare::parser::location_type& l, const string& m) __attribute__((noreturn));
//! Error handler using saved location
void error(const string &m) __attribute__ ((noreturn));
void error(const string& m) __attribute__((noreturn));
//! Warning handler using saved location
void warning(const string &m);
void warning(const string& m);
//! Error handler with explicit location (used in model block, accumulating error messages to be printed later)
void model_error(const string &m, const string &var);
void undeclared_model_variable_error(const string &m, const string &var);
//! 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);
bool symbol_exists_and_is_not_modfile_local_or_external_function(const string& s);
//! Sets mode of ModelTree class to use C output
void use_dll();
//! the modelis block decomposed
@ -332,50 +347,55 @@ public:
//! the differentiate_forward_vars option is enabled (for a subset of vars)
void differentiate_forward_vars_some(vector<string> symbol_list);
//! cutoff option of model block
void cutoff(const string &value);
void cutoff(const string& value);
//! mfs option of model block
void mfs(const string &value);
void mfs(const string& value);
//! static_mfs option of model block
void static_mfs(const string &value);
void static_mfs(const string& value);
//! the flags to substitute for the default compiler flags used by `use_dll`
void compilation_setup_substitute_flags(const string &flags);
void compilation_setup_substitute_flags(const string& flags);
//! the flags to add to the default compiler flags used by `use_dll`
void compilation_setup_add_flags(const string &flags);
void compilation_setup_add_flags(const string& flags);
//! the libs to substitute for the default compiler libs used by `use_dll`
void compilation_setup_substitute_libs(const string &libs);
void compilation_setup_substitute_libs(const string& libs);
//! the libs to add to the default compiler libs used by `use_dll`
void compilation_setup_add_libs(const string &libs);
void compilation_setup_add_libs(const string& libs);
//! the compiler to replace the default compiler used by `use_dll`
void compilation_setup_compiler(const string &path);
void compilation_setup_compiler(const string& path);
//! balanced_growth_test_tol option of model block
void balanced_growth_test_tol(const string &value);
void balanced_growth_test_tol(const string& value);
//! 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);
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);
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);
void parameters(const vector<tuple<string, string, vector<pair<string, string>>>>& symbol_list);
// Handles a “model_local_variable” statement
void model_local_variable(const vector<pair<string, string>> &symbol_list);
void model_local_variable(const vector<pair<string, string>>& symbol_list);
//! Declares a statement local variable
void declare_statement_local_variable(const string &name);
void declare_statement_local_variable(const string& name);
//! Completes a subsample statement
void set_subsamples(string name1, string name2);
//! Declares a subsample, assigning the value to name
void set_subsample_name_equal_to_date_range(string name, string date1, string date2);
//! Checks that a subsample statement (and given name) were provided for the pair name1 & name2
void check_subsample_declaration_exists(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& 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}
@ -383,45 +403,45 @@ public:
//! Sets the value of the planner_discount_latex_name option of ramsey_model
void set_planner_discount_latex_name(string tex_name);
//! Handles a “predetermined_variables” statement
void predetermined_variables(const vector<string> &symbol_list);
void predetermined_variables(const vector<string>& symbol_list);
//! Declares and initializes a local parameter
void declare_and_init_model_local_variable(const string &name, expr_t rhs);
void declare_and_init_model_local_variable(const string& name, expr_t rhs);
//! Changes type of a symbol
void change_type(SymbolType new_type, const vector<string> &symbol_list);
void change_type(SymbolType new_type, const vector<string>& symbol_list);
//! Adds a non-negative constant to DataTree
expr_t add_non_negative_constant(const string &constant);
expr_t add_non_negative_constant(const string& constant);
//! Adds a NaN constant to DataTree
expr_t add_nan_constant();
//! Adds an Inf constant to DataTree
expr_t add_inf_constant();
//! Adds a model variable to ModelTree and VariableTable
expr_t add_model_variable(const string &name);
expr_t add_model_variable(const string& name);
//! Declares a variable of type new_type OR changes a variable in the equations to type new_type
//! and removes any error messages that may have been issued in model_errors
expr_t declare_or_change_type(SymbolType new_type, const string &name);
expr_t declare_or_change_type(SymbolType new_type, const string& name);
//! Adds an Expression's variable
expr_t add_expression_variable(const string &name);
expr_t add_expression_variable(const string& name);
//! Adds a "dsample" statement
void dsample(const string &arg1);
void dsample(const string& arg1);
//! Adds a "dsample" statement
void dsample(const string &arg1, const string &arg2);
void dsample(const string& arg1, const string& arg2);
//! Writes parameter intitialisation expression
void init_param(const string &name, expr_t rhs);
void init_param(const string& name, expr_t rhs);
//! Add a line inside an initval block
void init_val(const string &name, expr_t rhs);
void init_val(const string& name, expr_t rhs);
//! Add a line inside an endval block
void end_val(EndValLearntInStatement::LearntEndValType type, const string &name, expr_t rhs);
void end_val(EndValLearntInStatement::LearntEndValType type, const string& name, expr_t rhs);
//! Add a line inside a histval block
void hist_val(const string &name, const string &lag, expr_t rhs);
void hist_val(const string& name, const string& lag, expr_t rhs);
//! Adds an entry in a homotopy_setup block
/*! Second argument "val1" can be NULL if no initial value provided */
void homotopy_val(const string &name, expr_t val1, expr_t val2);
void homotopy_val(const string& name, expr_t val1, expr_t val2);
//! Writes end of an initval block
void end_initval(bool all_values_required);
//! Writes end of an endval block
void end_endval(bool all_values_required);
//! Writes end of an endval(learnt_in=…) block
void end_endval_learnt_in(const string &learnt_in_period);
void end_endval_learnt_in(const string& learnt_in_period);
//! Writes end of an histval block
void end_histval(bool all_values_required);
//! Writes end of an homotopy_setup block
@ -431,9 +451,9 @@ public:
//! End epilogue block
void end_epilogue();
//! Add epilogue variable
void add_epilogue_variable(const string &varname);
void add_epilogue_variable(const string& varname);
//! Add equation in epilogue block
void add_epilogue_equal(const string &varname, expr_t expr);
void add_epilogue_equal(const string& varname, expr_t expr);
/* Begin a model or model_replace block, or an expression as an option value
of some statement.
Must be followed by a call to reset_data_tree(). */
@ -447,40 +467,43 @@ public:
//! Writes a shocks(surprise) statement
void end_shocks_surprise(bool overwrite);
//! Writes a shocks(learnt_in=…) block
void end_shocks_learnt_in(const string &learnt_in_period, bool overwrite);
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
conditional_forecast_paths block, or a surprise shock */
enum class DetShockType
{
standard,
add, // for “add” in “shocks(learnt_in)”
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);
{
standard,
add, // for “add” in “shocks(learnt_in)”
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);
//! 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);
void add_stderr_shock(const string& var, expr_t value);
//! Adds a variance shock
void add_var_shock(const string &var, expr_t value);
void add_var_shock(const string& var, expr_t value);
//! Adds a covariance shock
void add_covar_shock(const string &var1, const string &var2, expr_t value);
void add_covar_shock(const string& var1, const string& var2, expr_t value);
//! Adds a correlated shock
void add_correl_shock(const string &var1, const string &var2, expr_t value);
void add_correl_shock(const string& var1, const string& var2, expr_t value);
//! Adds a shock period range
void add_period(const string &p1, const string &p2);
void add_period(const string& p1, const string& p2);
//! Adds a shock period
void add_period(const string &p1);
void add_period(const string& p1);
//! Adds a deterministic shock value
void add_value(expr_t value);
//! Adds a deterministic shock value
/*! \param v a string containing a (possibly negative) numeric constant */
void add_value(const string &v);
void add_value(const string& v);
//! Write a steady command
void steady();
//! Sets an option to a numerical value
@ -530,7 +553,7 @@ public:
//! Adds a declaration for a user-defined external function
void external_function();
//! Sets an external_function option to a string value
void external_function_option(const string &name_option, const string &opt);
void external_function_option(const string& name_option, const string& opt);
//! Add a line in an estimated params block
void add_estimated_params_element();
//! Writes osr params bounds command
@ -538,25 +561,27 @@ public:
//! Add a line in an osr params block
void add_osr_params_element();
//! Sets the frequency of the data
void set_time(const string &arg);
void set_time(const string& arg);
//! Estimation Data
void estimation_data();
//! Sets the prior for a parameter
void set_prior(string name, string subsample_name);
//! Sets the joint prior for a set of parameters
void set_joint_prior(const vector<string> &symbol_vec);
void set_joint_prior(const vector<string>& symbol_vec);
//! Adds a parameters to the list of joint parameters
void add_joint_parameter(string name);
//! Adds the variance option to its temporary holding place
void set_prior_variance(expr_t variance = 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
@ -572,34 +597,34 @@ public:
//! Check that no observed variable has yet be defined
void check_varobs();
//! Add a new observed variable
void add_varobs(const string &name);
void add_varobs(const string& name);
//! Check that no observed exogenous variable has yet be defined
void check_varexobs();
//! Add a new observed exogenous variable
void add_varexobs(const string &name);
void add_varexobs(const string& name);
//! Svar_Identification Statement
void begin_svar_identification();
void end_svar_identification();
//! Svar_Identification Statement: match list of restrictions and equation number with lag
void combine_lag_and_restriction(const string &lag);
void combine_lag_and_restriction(const string& lag);
//! Svar_Identification Statement: match list of restrictions with equation number
void add_restriction_in_equation(const string &equation, const vector<string> &symbol_list);
void add_restriction_in_equation(const string& equation, const vector<string>& symbol_list);
//! Svar_Identification Statement: add exclusions of constants
void add_constants_exclusion();
//! Svar_Identification Statement: add equation number for following restriction equations
void add_restriction_equation_nbr(const string &eq_nbr);
void add_restriction_equation_nbr(const string& eq_nbr);
//! Svar_Identification Statement: record presence of equal sign
void add_restriction_equal();
//! Svar_Idenditification Statement: add coefficient of a linear restriction (positive value)
void add_positive_restriction_element(expr_t value, const string &variable, const string &lag);
void add_positive_restriction_element(expr_t value, const string& variable, const string& lag);
//! Svar_Idenditification Statement: add unit coefficient of a linear restriction
void add_positive_restriction_element(const string &variable, const string &lag);
void add_positive_restriction_element(const string& variable, const string& lag);
//! Svar_Idenditification Statement: add coefficient of a linear restriction (negative value)
void add_negative_restriction_element(expr_t value, const string &variable, const string &lag);
void add_negative_restriction_element(expr_t value, const string& variable, const string& lag);
//! Svar_Idenditification Statement: add negative unit coefficient of a linear restriction
void add_negative_restriction_element(const string &variable, const string &lag);
void add_negative_restriction_element(const string& variable, const string& lag);
//! Svar_Idenditification Statement: add restriction element
void add_restriction_element(expr_t value, const string &variable, const string &lag);
void add_restriction_element(expr_t value, const string& variable, const string& lag);
//! Svar_Identification Statement: check that restriction is homogenous
void check_restriction_expression_constant(expr_t value);
//! Svar_Identification Statement: restriction of form upper cholesky
@ -611,7 +636,7 @@ public:
//! generate_irfs Block
void end_generate_irfs();
void add_generate_irfs_element(string name);
void add_generate_irfs_exog_element(string exo, const string &value);
void add_generate_irfs_exog_element(string exo, const string& value);
//! Forecast Statement
void forecast(vector<string> symbol_list);
void set_trends();
@ -620,16 +645,16 @@ public:
//! filter_initial_state block
void set_filter_initial_state();
//! element for filter_initial_state block
void set_filter_initial_state_element(const string &name, const string &lag, expr_t rhs);
void set_filter_initial_state_element(const string& name, const string& lag, expr_t rhs);
void set_unit_root_vars();
void optim_weights();
void set_optim_weights(string name, expr_t value);
void set_optim_weights(const string &name1, const string &name2, expr_t value);
void set_optim_weights(const string& name1, const string& name2, expr_t value);
void set_osr_params(vector<string> symbol_list);
void run_osr(vector<string> symbol_list);
void run_dynasave(string filename, vector<string> symbol_list);
void run_dynatype(string filename, vector<string> symbol_list);
void run_load_params_and_steady_state(const string &filename);
void run_load_params_and_steady_state(const string& filename);
void run_save_params_and_steady_state(string filename);
void run_identification();
void add_mc_filename(string filename, string prior = "1");
@ -643,15 +668,15 @@ public:
//! Ramsey constraints statement
void add_ramsey_constraints_statement();
//! Ramsey less constraint
void ramsey_constraint_add_less(const string &name, const expr_t rhs);
void ramsey_constraint_add_less(const string& name, const expr_t rhs);
//! Ramsey greater constraint
void ramsey_constraint_add_greater(const string &name, const expr_t rhs);
void ramsey_constraint_add_greater(const string& name, const expr_t rhs);
//! Ramsey less or equal constraint
void ramsey_constraint_add_less_equal(const string &name, const expr_t rhs);
void ramsey_constraint_add_less_equal(const string& name, const expr_t rhs);
//! Ramsey greater or equal constraint
void ramsey_constraint_add_greater_equal(const string &name, const expr_t rhs);
void ramsey_constraint_add_greater_equal(const string& name, const expr_t rhs);
//! Ramsey constraint helper function
void add_ramsey_constraint(const string &name, BinaryOpcode op_code, const expr_t rhs);
void add_ramsey_constraint(const string& name, BinaryOpcode op_code, const expr_t rhs);
//! Ramsey policy statement
void ramsey_policy(vector<string> symbol_list);
//! Evaluate Planner Objective
@ -675,11 +700,11 @@ public:
//! Adds a write_latex_steady_state_model statement
void write_latex_steady_state_model();
//! BVAR marginal density
void bvar_density(const string &maxnlags);
void bvar_density(const string& maxnlags);
//! BVAR forecast
void bvar_forecast(const string &nlags);
void bvar_forecast(const string& nlags);
//! BVAR IRF
void bvar_irf(const string &nirf, string identificationname);
void bvar_irf(const string& nirf, string identificationname);
//! SBVAR statement
void sbvar();
//! Markov Switching Statement: Estimation
@ -715,7 +740,7 @@ public:
//! Conditional forecast paths block
void conditional_forecast_paths();
//! Plot conditional forecast statement
void plot_conditional_forecast(const optional<string> &periods, vector<string> symbol_list);
void plot_conditional_forecast(const optional<string>& periods, vector<string> symbol_list);
//! Smoother on calibrated models
void calib_smoother(vector<string> symbol_list);
//! Extended path
@ -749,13 +774,13 @@ public:
//! Writes token "arg1^arg2" to model tree
expr_t add_power(expr_t arg1, expr_t arg2);
//! Writes token "E(arg1)(arg2)" to model tree
expr_t add_expectation(const string &arg1, expr_t arg2);
expr_t add_expectation(const string& arg1, expr_t arg2);
//! Writes token "VAR_EXPECTATION(model_name)" to model tree
expr_t add_var_expectation(const string &model_name);
expr_t add_var_expectation(const string& model_name);
//! Writes token "PAC_EXPECTATION(model_name, discount, growth)" to model tree
expr_t add_pac_expectation(const string &model_name);
expr_t add_pac_expectation(const string& model_name);
//! Adds a pac_target_nonstationary(model_name, discount, growth) node to model tree
expr_t add_pac_target_nonstationary(const string &model_name);
expr_t add_pac_target_nonstationary(const string& model_name);
//! Creates pac_model statement
void begin_pac_model();
void pac_model();
@ -768,8 +793,8 @@ public:
//! Writes token "diff(arg1)" to model tree
expr_t add_diff(expr_t arg1);
//! Writes token "adl(arg1, lag)" to model tree
expr_t add_adl(expr_t arg1, const string &name, const string &lag);
expr_t add_adl(expr_t arg1, const string &name, const vector<int> &lags);
expr_t add_adl(expr_t arg1, const string& name, const string& lag);
expr_t add_adl(expr_t arg1, const string& name, const vector<int>& lags);
//! Writes token "exp(arg1)" to model tree
expr_t add_exp(expr_t arg1);
//! Writes token "log(arg1)" to model tree
@ -833,32 +858,39 @@ public:
//! Test to see if model/external function has exactly one integer argument
optional<int> is_there_one_integer_argument() const;
//! Adds an external function call node
expr_t add_model_var_or_external_function(const string &function_name, bool in_model_block);
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();
//! Begin a steady_state_model block
void begin_steady_state_model();
//! Add an assignment equation in steady_state_model block
void add_steady_state_model_equal(const string &varname, expr_t expr);
void add_steady_state_model_equal(const string& varname, expr_t expr);
//! 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);
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
@ -881,7 +915,7 @@ public:
//! End shock groups declaration
void end_shock_groups(string name);
//! Add a set of init2shocks
void add_init2shocks(const string &endo_name, const string &exo_name);
void add_init2shocks(const string& endo_name, const string& exo_name);
//! End init2shocks declaration
void end_init2shocks(string name);
void smoother2histval();
@ -898,17 +932,18 @@ public:
//! Start parsing a matched_moments block
void begin_matched_moments();
//! Add a matched_moments block
void end_matched_moments(const vector<expr_t> &moments);
void end_matched_moments(const vector<expr_t>& moments);
//! 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);
void model_remove(const vector<map<string, string>>& listed_eqs_by_tags);
// Begin a model_replace statement
void begin_model_replace(const vector<map<string, string>> &listed_eqs_by_tags);
void begin_model_replace(const vector<map<string, string>>& listed_eqs_by_tags);
// Add a var_remove statement
void var_remove(const vector<string> &symbol_list);
void var_remove(const vector<string>& symbol_list);
void begin_pac_target_info(string name);
void end_pac_target_info();
void set_pac_target_info_target(expr_t target);
@ -920,9 +955,10 @@ public:
// Add a resid statement
void resid();
// Returns true iff the string is a legal symbol identifier (see NAME token in lexer)
static bool isSymbolIdentifier(const string &str);
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

@ -26,30 +26,27 @@
AbstractShocksStatement::AbstractShocksStatement(bool overwrite_arg, ShockType type_arg,
det_shocks_t det_shocks_arg,
const SymbolTable &symbol_table_arg) :
overwrite{overwrite_arg},
type{type_arg},
det_shocks{move(det_shocks_arg)},
symbol_table{symbol_table_arg}
const SymbolTable& symbol_table_arg) :
overwrite {overwrite_arg},
type {type_arg},
det_shocks {move(det_shocks_arg)},
symbol_table {symbol_table_arg}
{
}
void
AbstractShocksStatement::writeDetShocks(ostream &output) const
AbstractShocksStatement::writeDetShocks(ostream& output) const
{
int exo_det_length = 0;
for (const auto & [id, shock_vec] : det_shocks)
for (const auto& [id, shock_vec] : det_shocks)
for (bool exo_det = (symbol_table.getType(id) == SymbolType::exogenousDet);
const auto &[period1, period2, value] : shock_vec)
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;
@ -60,18 +57,16 @@ AbstractShocksStatement::writeDetShocks(ostream &output) const
}
void
AbstractShocksStatement::writeJsonDetShocks(ostream &output) const
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,35 +96,33 @@ 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},
var_shocks{move(var_shocks_arg)},
std_shocks{move(std_shocks_arg)},
covar_shocks{move(covar_shocks_arg)},
corr_shocks{move(corr_shocks_arg)}
const SymbolTable& 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)},
corr_shocks {move(corr_shocks_arg)}
{
}
void
ShocksStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
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);
@ -152,14 +143,14 @@ ShocksStatement::writeOutput(ostream &output, [[maybe_unused]] const string &bas
If there are no off-diagonal elements, and we are not in overwrite mode,
then we don't reset it to 1, since there might be previous shocks blocks
with off-diagonal elements. */
if (covar_shocks.size()+corr_shocks.size() > 0)
if (covar_shocks.size() + corr_shocks.size() > 0)
output << "M_.sigma_e_is_diagonal = 0;" << endl;
else if (overwrite)
output << "M_.sigma_e_is_diagonal = 1;" << endl;
}
void
ShocksStatement::writeJsonOutput(ostream &output) const
ShocksStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "shocks")"
<< R"(, "overwrite": )" << boolalpha << overwrite;
@ -168,9 +159,8 @@ ShocksStatement::writeJsonOutput(ostream &output) const
output << ", ";
writeJsonDetShocks(output);
}
output<< R"(, "variance": [)";
for (bool printed_something{false};
auto &[id, value] : var_shocks)
output << R"(, "variance": [)";
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));
@ -252,23 +238,24 @@ ShocksStatement::writeVarOrStdShock(ostream &output, const pair<int, expr_t> &it
}
void
ShocksStatement::writeVarAndStdShocks(ostream &output) const
ShocksStatement::writeVarAndStdShocks(ostream& output) const
{
for (const auto &it : var_shocks)
for (const auto& it : var_shocks)
writeVarOrStdShock(output, it, false);
for (const auto &it : std_shocks)
for (const auto& it : std_shocks)
writeVarOrStdShock(output, it, true);
}
void
ShocksStatement::writeCovarOrCorrShock(ostream &output, const pair<pair<int, int>, expr_t> &it,
ShocksStatement::writeCovarOrCorrShock(ostream& output, const pair<pair<int, int>, expr_t>& it,
bool corr) const
{
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,89 +276,95 @@ 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;
}
}
void
ShocksStatement::writeCovarAndCorrShocks(ostream &output) const
ShocksStatement::writeCovarAndCorrShocks(ostream& output) const
{
for (const auto &it : covar_shocks)
for (const auto& it : covar_shocks)
writeCovarOrCorrShock(output, it, false);
for (const auto &it : corr_shocks)
for (const auto& it : corr_shocks)
writeCovarOrCorrShock(output, it, true);
}
void
ShocksStatement::checkPass(ModFileStructure &mod_file_struct,
[[maybe_unused]] WarningConsolidation &warnings)
ShocksStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
/* Error out if variables are not of the right type. This must be done here
and not at parsing time (see #448).
Also Determine if there is a calibrated measurement error */
for (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);
}
}
for (const auto & [ids, val] : covar_shocks)
for (const auto& [ids, val] : covar_shocks)
{
auto &[symb_id1, symb_id2] = ids;
auto& [symb_id1, symb_id2] = ids;
if (!((symbol_table.getType(symb_id1) == SymbolType::exogenous
&& symbol_table.getType(symb_id2) == SymbolType::exogenous)
|| (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);
}
}
for (const auto & [ids, val] : corr_shocks)
for (const auto& [ids, val] : corr_shocks)
{
auto &[symb_id1, symb_id2] = ids;
auto& [symb_id1, symb_id2] = ids;
if (!((symbol_table.getType(symb_id1) == SymbolType::exogenous
&& symbol_table.getType(symb_id2) == SymbolType::exogenous)
|| (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);
}
}
@ -384,9 +377,9 @@ ShocksStatement::checkPass(ModFileStructure &mod_file_struct,
val->collectVariables(SymbolType::parameter, mod_file_struct.parameters_within_shocks_values);
for (auto [id, val] : std_shocks)
val->collectVariables(SymbolType::parameter, mod_file_struct.parameters_within_shocks_values);
for (const auto &[ids, val] : covar_shocks)
for (const auto& [ids, val] : covar_shocks)
val->collectVariables(SymbolType::parameter, mod_file_struct.parameters_within_shocks_values);
for (const auto &[ids, val] : corr_shocks)
for (const auto& [ids, val] : corr_shocks)
val->collectVariables(SymbolType::parameter, mod_file_struct.parameters_within_shocks_values);
}
@ -401,14 +394,12 @@ ShocksStatement::has_calibrated_measurement_errors() const
if (symbol_table.isObservedVariable(id))
return true;
for (const auto & [ids, val] : covar_shocks)
if (symbol_table.isObservedVariable(ids.first)
|| symbol_table.isObservedVariable(ids.second))
for (const auto& [ids, val] : covar_shocks)
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))
for (const auto& [ids, val] : corr_shocks)
if (symbol_table.isObservedVariable(ids.first) || symbol_table.isObservedVariable(ids.second))
return true;
return false;
@ -416,21 +407,20 @@ ShocksStatement::has_calibrated_measurement_errors() const
MShocksStatement::MShocksStatement(bool overwrite_arg, bool relative_to_initval_arg,
det_shocks_t det_shocks_arg,
const SymbolTable &symbol_table_arg) :
AbstractShocksStatement{overwrite_arg,
relative_to_initval_arg ? ShockType::multiplyInitialSteadyState : ShockType::multiplySteadyState,
move(det_shocks_arg), symbol_table_arg},
relative_to_initval{relative_to_initval_arg}
const SymbolTable& symbol_table_arg) :
AbstractShocksStatement {overwrite_arg,
relative_to_initval_arg ? ShockType::multiplyInitialSteadyState
: ShockType::multiplySteadyState,
move(det_shocks_arg), symbol_table_arg},
relative_to_initval {relative_to_initval_arg}
{
}
void
MShocksStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
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;
@ -439,11 +429,11 @@ MShocksStatement::writeOutput(ostream &output, [[maybe_unused]] const string &ba
}
void
MShocksStatement::writeJsonOutput(ostream &output) const
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,35 +442,35 @@ MShocksStatement::writeJsonOutput(ostream &output) const
output << "}";
}
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)},
symbol_table{symbol_table_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)},
symbol_table {symbol_table_arg}
{
}
void
ShocksSurpriseStatement::checkPass(ModFileStructure &mod_file_struct,
[[maybe_unused]] WarningConsolidation &warnings)
ShocksSurpriseStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.shocks_surprise_present = true;
}
void
ShocksSurpriseStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
ShocksSurpriseStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
if (overwrite)
output << "M_.surprise_shocks = [" << endl;
else
output << "M_.surprise_shocks = [ M_.surprise_shocks;" << endl;
for (const auto &[id, shock_vec] : surprise_shocks)
for (const auto &[period1, period2, value] : shock_vec)
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;
}
@ -488,20 +478,18 @@ ShocksSurpriseStatement::writeOutput(ostream &output, [[maybe_unused]] const str
}
void
ShocksSurpriseStatement::writeJsonOutput(ostream &output) const
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 << ", ";
@ -518,15 +506,17 @@ 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}
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}
{
}
void
ShocksLearntInStatement::checkPass(ModFileStructure &mod_file_struct,
[[maybe_unused]] WarningConsolidation &warnings)
ShocksLearntInStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.shocks_learnt_in_present = true;
}
@ -551,22 +541,22 @@ ShocksLearntInStatement::typeToString(LearntShockType type)
}
void
ShocksLearntInStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
ShocksLearntInStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
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)
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;
@ -575,21 +565,18 @@ ShocksLearntInStatement::writeOutput(ostream &output, [[maybe_unused]] const str
}
void
ShocksLearntInStatement::writeJsonOutput(ostream &output) const
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,42 +592,41 @@ 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)
for (auto &[period1, period2, value] : elems)
int length {0};
for (const auto& [ignore, elems] : paths)
for (auto& [period1, period2, value] : elems)
// Period1 < Period2, as enforced in ParsingDriver::add_period()
length = max(length, period2);
return length;
}
void
ConditionalForecastPathsStatement::writeOutput(ostream &output,
[[maybe_unused]] const string &basename,
ConditionalForecastPathsStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
assert(path_length > 0);
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;
for (const auto &[period1, period2, value] : elems)
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++)
{
output << "constrained_paths_(" << k << "," << j << ")=";
@ -652,19 +638,17 @@ ConditionalForecastPathsStatement::writeOutput(ostream &output,
}
void
ConditionalForecastPathsStatement::writeJsonOutput(ostream &output) const
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,38 +664,35 @@ 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}
{
}
void
MomentCalibration::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
MomentCalibration::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_.endogenous_prior_restrictions.moment = {" << endl;
for (const auto &c : constraints)
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;
}
void
MomentCalibration::writeJsonOutput(ostream &output) const
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,37 +711,36 @@ 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)}
{
}
void
IrfCalibration::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
IrfCalibration::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
output << "options_.endogenous_prior_restrictions.irf = {" << endl;
for (const auto &c : constraints)
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;
}
void
IrfCalibration::writeJsonOutput(ostream &output) const
IrfCalibration::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "irf_calibration")";
if (!options_list.empty())
@ -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,20 +769,20 @@ 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)}
{
}
void
ShockGroupsStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
ShockGroupsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
int i = 1;
for (auto it = shock_groups.begin(); it != shock_groups.end(); ++it)
{
bool unique_label{true};
for (auto it1 = it+1; it1 != shock_groups.end(); ++it1)
bool unique_label {true};
for (auto it1 = it + 1; it1 != shock_groups.end(); ++it1)
if (it->name == it1->name)
{
unique_label = false;
@ -814,11 +793,10 @@ 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 = {";
for (const auto &it1 : it->list)
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;
i++;
@ -827,14 +805,14 @@ ShockGroupsStatement::writeOutput(ostream &output, [[maybe_unused]] const string
}
void
ShockGroupsStatement::writeJsonOutput(ostream &output) const
ShockGroupsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "shock_groups", "name": ")" << name << R"(", "groups": [)";
bool printed_something{false};
bool printed_something {false};
for (auto it = shock_groups.begin(); it != shock_groups.end(); ++it)
{
bool unique_label{true};
for (auto it1 = it+1; it1 != shock_groups.end(); ++it1)
bool unique_label {true};
for (auto it1 = it + 1; it1 != shock_groups.end(); ++it1)
if (it->name == it1->name)
{
unique_label = false;
@ -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,14 +838,14 @@ 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}
{
}
void
Init2shocksStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct,
[[maybe_unused]] WarningConsolidation &warnings)
Init2shocksStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
for (size_t i = 0; i < init2shocks.size(); i++)
for (size_t j = i + 1; j < init2shocks.size(); j++)
@ -882,21 +859,21 @@ Init2shocksStatement::checkPass([[maybe_unused]] ModFileStructure &mod_file_stru
}
void
Init2shocksStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
Init2shocksStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "M_.init2shocks." << name << " = {" << endl;
for (const auto &[id1, id2] : init2shocks)
output << "{'" << symbol_table.getName(id1) << "', '" << symbol_table.getName(id2) << "'};" << endl;
for (const auto& [id1, id2] : init2shocks)
output << "{'" << symbol_table.getName(id1) << "', '" << symbol_table.getName(id2) << "'};"
<< endl;
output << "};" << endl;
}
void
Init2shocksStatement::writeJsonOutput(ostream &output) const
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)},
symbol_table{symbol_table_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()
@ -924,43 +903,40 @@ HeteroskedasticShocksStatement::writeOutput(ostream &output, [[maybe_unused]] co
output << "M_.heteroskedastic_shocks.Qvalue_orig = [];" << endl
<< "M_.heteroskedastic_shocks.Qscale_orig = [];" << endl;
for (const auto &[symb_id, vec] : values)
for (const auto& [symb_id, vec] : values)
for (int tsid = symbol_table.getTypeSpecificID(symb_id);
const auto &[period1, period2, value] : vec)
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;
}
for (const auto &[symb_id, vec] : scales)
for (const auto& [symb_id, vec] : scales)
for (int tsid = symbol_table.getTypeSpecificID(symb_id);
const auto &[period1, period2, scale] : vec)
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;
}
}
void
HeteroskedasticShocksStatement::writeJsonOutput(ostream &output) const
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;
@ -36,24 +36,26 @@ public:
// The tuple is (period1, period2, value)
using det_shocks_t = map<int, vector<tuple<int, int, expr_t>>>;
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)”)
};
{
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)”)
};
protected:
//! Does this "shocks" statement replace the previous ones?
const bool overwrite;
const ShockType type; // Type of shocks represented by this block
const det_shocks_t det_shocks;
const SymbolTable &symbol_table;
void writeDetShocks(ostream &output) const;
void writeJsonDetShocks(ostream &output) const;
const SymbolTable& symbol_table;
void writeDetShocks(ostream& output) const;
void writeJsonDetShocks(ostream& output) const;
static string typeToString(ShockType type);
AbstractShocksStatement(bool overwrite_arg, ShockType type_arg,
det_shocks_t det_shocks_arg,
const SymbolTable &symbol_table_arg);
AbstractShocksStatement(bool overwrite_arg, ShockType type_arg, det_shocks_t det_shocks_arg,
const SymbolTable& symbol_table_arg);
};
class ShocksStatement : public AbstractShocksStatement
@ -61,36 +63,35 @@ 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 writeCovarAndCorrShocks(ostream &output) const;
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 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,
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;
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;
void writeJsonOutput(ostream& output) const override;
};
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,
const SymbolTable &symbol_table_arg);
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
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;
};
/* Represents a shocks(surprise) block.
@ -102,15 +103,17 @@ 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;
const SymbolTable& symbol_table;
public:
ShocksSurpriseStatement(bool overwrite_arg,
AbstractShocksStatement::det_shocks_t surprise_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;
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;
};
/* Represents a shocks(learnt_in=…) or mshocks(learnt_in=…) block.
@ -123,40 +126,48 @@ public:
//! Does this “shocks(learnt_in=…)” or “mshocks(learnt_in=…)” block replace the previous ones?
const bool overwrite;
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)”)
};
{
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)”)
};
// 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;
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);
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;
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;
};
class ConditionalForecastPathsStatement : public Statement
{
private:
const AbstractShocksStatement::det_shocks_t paths;
const SymbolTable &symbol_table;
const SymbolTable& symbol_table;
const int path_length;
public:
ConditionalForecastPathsStatement(AbstractShocksStatement::det_shocks_t paths_arg,
const SymbolTable &symbol_table_arg);
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
static int computePathLength(const AbstractShocksStatement::det_shocks_t &paths);
const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
static int computePathLength(const AbstractShocksStatement::det_shocks_t& paths);
};
class MomentCalibration : public Statement
@ -169,14 +180,15 @@ public:
expr_t lower_bound, upper_bound;
};
using constraints_t = vector<Constraint>;
private:
constraints_t constraints;
const SymbolTable &symbol_table;
const SymbolTable& symbol_table;
public:
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;
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;
};
class IrfCalibration : public Statement
@ -190,16 +202,17 @@ public:
expr_t lower_bound, upper_bound;
};
using constraints_t = vector<Constraint>;
private:
constraints_t constraints;
const SymbolTable &symbol_table;
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;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class ShockGroupsStatement : public Statement
@ -211,13 +224,15 @@ 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;
void writeJsonOutput(ostream &output) const override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class Init2shocksStatement : public Statement
@ -225,12 +240,14 @@ class Init2shocksStatement : public Statement
private:
const vector<pair<int, int>> init2shocks;
const string name;
const SymbolTable &symbol_table;
const SymbolTable& symbol_table;
public:
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;
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;
};
class HeteroskedasticShocksStatement : public Statement
@ -238,16 +255,18 @@ 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;
const SymbolTable& symbol_table;
public:
HeteroskedasticShocksStatement(bool overwrite_arg, heteroskedastic_shocks_t values_arg,
heteroskedastic_shocks_t scales_arg,
const SymbolTable &symbol_table_arg);
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
#endif

View File

@ -25,23 +25,23 @@
#include <utility>
void
Statement::checkPass([[maybe_unused]] ModFileStructure &mod_file_struct,
[[maybe_unused]] WarningConsolidation &warnings)
Statement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
}
void
Statement::computingPass([[maybe_unused]] const ModFileStructure &mod_file_struct)
Statement::computingPass([[maybe_unused]] const ModFileStructure& mod_file_struct)
{
}
NativeStatement::NativeStatement(string native_statement_arg) :
native_statement{move(native_statement_arg)}
native_statement {move(native_statement_arg)}
{
}
void
NativeStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
NativeStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
using namespace boost::xpressive;
@ -50,12 +50,12 @@ NativeStatement::writeOutput(ostream &output, [[maybe_unused]] const string &bas
sregex regex_dollar = sregex::compile(R"((\$))" + date_regex);
string ns = regex_replace(native_statement, regex_lookbehind, "dates('$&')");
ns = regex_replace(ns, regex_dollar, "$2"); //replace $DATE with DATE
ns = regex_replace(ns, regex_dollar, "$2"); // replace $DATE with DATE
output << ns << endl;
}
void
NativeStatement::writeJsonOutput(ostream &output) const
NativeStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "native")"
<< R"(, "string": ")";
@ -65,55 +65,55 @@ NativeStatement::writeJsonOutput(ostream &output) const
switch (ch)
{
case '\b':
output << R"(\b)";
break;
output << R"(\b)";
break;
case '\f':
output << R"(\f)";
break;
output << R"(\f)";
break;
case '\n':
output << R"(\n)";
break;
output << R"(\n)";
break;
case '\r':
output << R"(\r)";
break;
output << R"(\r)";
break;
case '\t':
output << R"(\t)";
break;
output << R"(\t)";
break;
case '"':
output << R"(\")";
break;
output << R"(\")";
break;
case '\\':
output << R"(\\)";
output << R"(\\)";
break;
default:
output << ch;
break;
output << ch;
break;
}
output << R"("})";
}
VerbatimStatement::VerbatimStatement(string verbatim_statement_arg) :
verbatim_statement{move(verbatim_statement_arg)}
verbatim_statement {move(verbatim_statement_arg)}
{
}
void
VerbatimStatement::writeOutput(ostream &output, [[maybe_unused]] const string &basename,
VerbatimStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << verbatim_statement << endl;
}
void
VerbatimStatement::writeJsonOutput(ostream &output) const
VerbatimStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "verbatim")"
<< R"(, "string": ")";
@ -123,55 +123,55 @@ VerbatimStatement::writeJsonOutput(ostream &output) const
switch (ch)
{
case '\b':
output << R"(\b)";
break;
output << R"(\b)";
break;
case '\f':
output << R"(\f)";
break;
output << R"(\f)";
break;
case '\n':
output << R"(\n)";
break;
output << R"(\n)";
break;
case '\r':
output << R"(\r)";
break;
output << R"(\r)";
break;
case '\t':
output << R"(\t)";
break;
output << R"(\t)";
break;
case '"':
output << R"(\")";
break;
output << R"(\")";
break;
case '\\':
output << R"(\\)";
output << R"(\\)";
break;
default:
output << ch;
break;
output << ch;
break;
}
output << R"("})";
}
void
OptionsList::writeOutput(ostream &output) const
OptionsList::writeOutput(ostream& output) const
{
writeOutputCommon(output, "options_");
}
void
OptionsList::writeOutput(ostream &output, const string &option_group) const
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;
}
@ -182,146 +182,145 @@ OptionsList::writeOutput(ostream &output, const string &option_group) const
}
void
OptionsList::writeOutputCommon(ostream &output, const string &option_group) const
OptionsList::writeOutputCommon(ostream& output, const string& option_group) const
{
for (const auto &[name, val] : options)
std::visit([&]<class T>(const T &v)
{
if constexpr(is_same_v<T, SymbolListVal>)
v.writeOutput(option_group + "." + name, output);
else
{
output << option_group << "." << name << " = ";
if constexpr(is_same_v<T, NumVal> || is_same_v<T, DateVal>)
output << v;
else if constexpr(is_same_v<T, pair<string, string>>)
output << '[' << v.first << "; " << v.second << ']';
else if constexpr(is_same_v<T, StringVal>)
output << "'" << v << "'";
else if constexpr(is_same_v<T, vector<int>>)
for (const auto& [name, val] : options)
std::visit(
[&]<class T>(const T& v) {
if constexpr (is_same_v<T, SymbolListVal>)
v.writeOutput(option_group + "." + name, output);
else
{
if (v.size() > 1)
output << option_group << "." << name << " = ";
if constexpr (is_same_v<T, NumVal> || is_same_v<T, DateVal>)
output << v;
else if constexpr (is_same_v<T, pair<string, string>>)
output << '[' << v.first << "; " << v.second << ']';
else if constexpr (is_same_v<T, StringVal>)
output << "'" << v << "'";
else if constexpr (is_same_v<T, vector<int>>)
{
output << '[';
for (int it : v)
output << it << ";";
output << ']';
if (v.size() > 1)
{
output << '[';
for (int it : v)
output << it << ";";
output << ']';
}
else
output << v.front();
}
else
output << v.front();
}
else if constexpr(is_same_v<T, VecStrVal>)
{
if (v.size() > 1)
else if constexpr (is_same_v<T, VecStrVal>)
{
if (v.size() > 1)
{
output << '{';
for (const auto& it : v)
output << "'" << it << "';";
output << '}';
}
else
output << v.front();
}
else if constexpr (is_same_v<T, VecCellStrVal>)
{
/* VecCellStrVal should ideally be merged into VecStrVal.
only difference is treatment of v.size==1, where VecStrVal
does not add quotes and curly brackets, i.e. allows for type conversion of
'2' into the number 2 */
output << '{';
for (const auto &it : v)
for (const auto& it : v)
output << "'" << it << "';";
output << '}';
}
else
output << v.front();
}
else if constexpr(is_same_v<T, VecCellStrVal>)
{
/* VecCellStrVal should ideally be merged into VecStrVal.
only difference is treatment of v.size==1, where VecStrVal
does not add quotes and curly brackets, i.e. allows for type conversion of
'2' into the number 2 */
output << '{';
for (const auto &it : v)
output << "'" << it << "';";
output << '}';
}
else if constexpr(is_same_v<T, VecValueVal>)
{
/* For historical reason, those vectors are output as row vectors (contrary
to vectors of integers which are output as column vectors) */
output << '[';
for (const auto &it : v)
output << it << ',';
output << ']';
}
else if constexpr(is_same_v<T, vector<vector<string>>>)
{
// Same remark as for VecValueVal
output << '{';
for (const auto &v2 : v)
else if constexpr (is_same_v<T, VecValueVal>)
{
/* For historical reason, those vectors are output as row vectors (contrary
to vectors of integers which are output as column vectors) */
output << '[';
for (const auto &it : v2)
for (const auto& it : v)
output << it << ',';
output << "], ";
output << ']';
}
output << '}';
else if constexpr (is_same_v<T, vector<vector<string>>>)
{
// Same remark as for VecValueVal
output << '{';
for (const auto& v2 : v)
{
output << '[';
for (const auto& it : v2)
output << it << ',';
output << "], ";
}
output << '}';
}
else
static_assert(always_false_v<T>, "Non-exhaustive visitor!");
output << ";" << endl;
}
else
static_assert(always_false_v<T>, "Non-exhaustive visitor!");
output << ";" << endl;
}
}, val);
},
val);
}
void
OptionsList::writeJsonOutput(ostream &output) const
OptionsList::writeJsonOutput(ostream& output) const
{
if (empty())
return;
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)
{
if constexpr(is_same_v<T, NumVal>)
output << v;
else if constexpr(is_same_v<T, pair<string, string>>)
output << '[' << v.first << ", " << v.second << ']';
else if constexpr(is_same_v<T, StringVal> || is_same_v<T, DateVal>)
output << '"' << v << '"';
else if constexpr(is_same_v<T, SymbolListVal>)
{
output << '{';
v.writeJsonOutput(output);
output << '}';
}
else if constexpr(is_same_v<T, vector<int>> || is_same_v<T, VecStrVal>
|| is_same_v<T, VecCellStrVal> || is_same_v<T, VecValueVal>
|| is_same_v<T, vector<vector<string>>>)
{
output << '[';
for (bool printed_something{false};
const auto &it : 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>>)
output << '[' << v.first << ", " << v.second << ']';
else if constexpr (is_same_v<T, StringVal> || is_same_v<T, DateVal>)
output << '"' << v << '"';
else if constexpr (is_same_v<T, SymbolListVal>)
{
if (exchange(printed_something, true))
output << ", ";
if constexpr(is_same_v<T, vector<int>> || is_same_v<T, VecValueVal>)
output << it;
else if constexpr(is_same_v<T, VecStrVal> || is_same_v<T, VecCellStrVal>)
output << '"' << it << '"';
else // vector<vector<string>>
{
output << '[';
for (bool printed_something2{false};
const auto &it2 : it)
{
if (exchange(printed_something2, true))
output << ", ";
output << it2;
}
output << ']';
}
output << '{';
v.writeJsonOutput(output);
output << '}';
}
output << ']';
}
else
static_assert(always_false_v<T>, "Non-exhaustive visitor!");
}, val);
else if constexpr (is_same_v<T, vector<int>> || is_same_v<T, VecStrVal>
|| is_same_v<T, VecCellStrVal> || is_same_v<T, VecValueVal>
|| is_same_v<T, vector<vector<string>>>)
{
output << '[';
for (bool printed_something {false}; const auto& it : v)
{
if (exchange(printed_something, true))
output << ", ";
if constexpr (is_same_v<T, vector<int>> || is_same_v<T, VecValueVal>)
output << it;
else if constexpr (is_same_v<T, VecStrVal> || is_same_v<T, VecCellStrVal>)
output << '"' << it << '"';
else // vector<vector<string>>
{
output << '[';
for (bool printed_something2 {false}; const auto& it2 : it)
{
if (exchange(printed_something2, true))
output << ", ";
output << it2;
}
output << ']';
}
}
output << ']';
}
else
static_assert(always_false_v<T>, "Non-exhaustive visitor!");
},
val);
}
output << "}";
@ -334,13 +333,13 @@ OptionsList::clear()
}
bool
OptionsList::contains(const string &name) const
OptionsList::contains(const string& name) const
{
return options.contains(name);
}
void
OptionsList::erase(const string &name)
OptionsList::erase(const string& name)
{
options.erase(name);
}

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"
@ -33,102 +33,104 @@
struct ModFileStructure
{
//! Whether check is present
bool check_present{false};
bool check_present {false};
//! Whether steady is present
bool steady_present{false};
bool steady_present {false};
//! Whether a perfect_foresight_solver/simul statement is present
bool perfect_foresight_solver_present{false};
bool perfect_foresight_solver_present {false};
//! Whether a perfect_foresight_with_expectation_errors_solver statement is present
bool perfect_foresight_with_expectation_errors_solver_present{false};
bool perfect_foresight_with_expectation_errors_solver_present {false};
//! Whether a stoch_simul statement is present
bool stoch_simul_present{false};
bool stoch_simul_present {false};
//! Whether an estimation statement is present
bool estimation_present{false};
bool estimation_present {false};
//! Whether an osr statement is present
bool osr_present{false};
bool osr_present {false};
//! Whether an osr params statement is present
bool osr_params_present{false};
bool osr_params_present {false};
//! Whether an optim weight statement is present
bool optim_weights_present{false};
bool optim_weights_present {false};
//! Whether a ramsey_model statement is present
bool ramsey_model_present{false};
bool ramsey_model_present {false};
//! Whether a discretionary_objective statement is present
bool discretionary_policy_present{false};
bool discretionary_policy_present {false};
//! Whether a planner_objective statement is present
bool planner_objective_present{false};
bool planner_objective_present {false};
//! Whether an extended_path statement is present
bool extended_path_present{false};
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 */
int order_option{0};
/*! 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};
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
bool identification_present{false};
bool svar_identification_present {false};
//! 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};
int identification_order {0};
//! Whether a sensitivity statement is present
bool sensitivity_present{false};
bool sensitivity_present {false};
//! Whether the option analytic_derivation is given to estimation
bool estimation_analytic_derivation{false};
bool estimation_analytic_derivation {false};
//! Whether the option analytic_derivation is given to osr
bool osr_analytic_derivation{false};
bool osr_analytic_derivation {false};
//! Whether the option partial_information is given to stoch_simul/estimation/osr/ramsey_policy
bool partial_information{false};
bool partial_information {false};
//! Whether the "k_order_solver" option is used (explictly, or implicitly if order >= 3)
bool k_order_solver{false};
bool k_order_solver {false};
//! Whether an method_of_moments statement is present
bool mom_estimation_present{false};
bool mom_estimation_present {false};
//! Whether an GMM-option is present
bool GMM_present{false};
bool GMM_present {false};
//! Whether an analytic_standard_errors-option is present
bool analytic_standard_errors_present{false};
bool analytic_standard_errors_present {false};
//! Whether an analytic_jacobian-option is present
bool analytic_jacobian_present{false};
bool analytic_jacobian_present {false};
//! The maximum of the “order” option in method_of_moments statements
int mom_order{0};
int mom_order {0};
//! Whether there is a calibrated measurement error
bool calibrated_measurement_errors{false};
bool calibrated_measurement_errors {false};
//! Whether dsge_prior_weight was initialized as a parameter
bool dsge_prior_weight_initialized;
//! Whether dsge_prior_weight is in the estimated_params block
bool dsge_prior_weight_in_estimated_params{false};
bool dsge_prior_weight_in_estimated_params {false};
//! Whether there is a dsge_var, with calibrated prior weight
string dsge_var_calibrated;
//! Whether there is a dsge_var, with prior weight that must be estimated
bool dsge_var_estimated{false};
bool dsge_var_estimated {false};
//! Whether there is a bayesian_irf option passed to the estimation statement
bool bayesian_irf_present{false};
bool bayesian_irf_present {false};
//! Whether there is a data statement present
bool estimation_data_statement_present{false};
bool estimation_data_statement_present {false};
//! Last chain number for Markov Switching statement2
int last_markov_switching_chain{0};
int last_markov_switching_chain {0};
//! Whether a calib_smoother statement is present
bool calib_smoother_present{false};
bool calib_smoother_present {false};
//! Whether there is an estimated_params_init with use_calibration
bool estim_params_use_calib{false};
bool estim_params_use_calib {false};
//! Set of parameters used within shocks blocks, inside the expressions
//! defining the values of covariances (stored as symbol ids)
set<int> parameters_within_shocks_values;
//! Set of estimated parameters (stored as symbol ids)
set<int> estimated_parameters;
//! Whether there is a prior statement present
bool prior_statement_present{false};
bool prior_statement_present {false};
//! Whether there is a std prior statement present
bool std_prior_statement_present{false};
bool std_prior_statement_present {false};
//! Whether there is a corr prior statement present
bool corr_prior_statement_present{false};
bool corr_prior_statement_present {false};
//! Whether there is a options statement present
bool options_statement_present{false};
bool options_statement_present {false};
//! Whether there is a std options statement present
bool std_options_statement_present{false};
bool std_options_statement_present {false};
//! Whether there is a corr options statement present
bool corr_options_statement_present{false};
bool corr_options_statement_present {false};
//! Whether a Markov Switching DSGE is present
bool ms_dsge_present{false};
bool ms_dsge_present {false};
/* The number of equations in the model present just before adding the
Lagrange multipliers and computing the Ramsey FOC; it is by construction
equal to the number of Lagrange multipliers that will be added by the
@ -144,31 +146,31 @@ struct ModFileStructure
already been added. */
int ramsey_orig_endo_nbr {0};
//! Whether there was a steady_state_model block
bool steady_state_model_present{false};
bool steady_state_model_present {false};
//! Whether there is a write_latex_steady_state_model statement present
bool write_latex_steady_state_model_present{false};
bool write_latex_steady_state_model_present {false};
//! Pac growth and discount
set<int> pac_params;
//! Instruments if ramsey_model, ramsey_policy or discretionary_policy is present
SymbolList instruments;
/* Whether any of shock_decomposition, realtime_shock_decomposition and
initial_condition_decomposition has the with_epilogue option */
bool with_epilogue_option{false};
bool with_epilogue_option {false};
/* Lists symbol IDs of parameters that appear in a “planner_discount” option.
See dynare#1173 for more details. */
set<int> parameters_in_planner_discount;
// Whether an endval block (without the learnt_it=… option) appears
bool endval_present{false};
bool endval_present {false};
// Whether a shocks(surprise) block appears
bool shocks_surprise_present{false};
bool shocks_surprise_present {false};
// Whether a shocks(learnt_in=…) block appears
bool shocks_learnt_in_present{false};
bool shocks_learnt_in_present {false};
// Whether an endval(learnt_in=…) block appears
bool endval_learnt_in_present{false};
bool endval_learnt_in_present {false};
// Whether an occbin_constraints block appears
bool occbin_constraints_present{false};
bool occbin_constraints_present {false};
// Whether a ramsey_constraints block appears
bool ramsey_constraints_present{false};
bool ramsey_constraints_present {false};
};
class Statement
@ -177,43 +179,47 @@ public:
Statement() = default;
virtual ~Statement() = default;
Statement(const Statement &) = delete;
Statement &operator=(const Statement &) = delete;
Statement(const Statement&) = delete;
Statement& operator=(const Statement&) = delete;
//! Do some internal check, and fill the ModFileStructure class
/*! Don't forget to update ComputingTasks.hh, Shocks.hh and
NumericalInitialization.hh if you modify the signature of this
method. Otherwise the default implementation (i.e. a no-op) will apply and
some checks won't be run. */
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
virtual void computingPass(const ModFileStructure &mod_file_struct);
virtual void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings);
virtual void computingPass(const ModFileStructure& mod_file_struct);
//! 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 writeJsonOutput(ostream &output) const = 0;
virtual void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const
= 0;
virtual void writeJsonOutput(ostream& output) const = 0;
};
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;
void writeJsonOutput(ostream &output) const override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
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;
void writeJsonOutput(ostream &output) const override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
/* Stores a list of named options with their values.
@ -251,15 +257,15 @@ public:
bool empty() const;
void clear();
// Whether there is an option with that name that has been given a value
bool contains(const string &name) const;
bool contains(const string& name) const;
// Erase the option with that name
void erase(const string &name);
void erase(const string& name);
/* Declares an option with a name and value. Overwrite any previous value for
that name. */
template<class T>
void
set(string name, T &&val)
set(string name, T&& val)
{
options.insert_or_assign(move(name), forward<T>(val));
}
@ -267,7 +273,7 @@ public:
struct UnknownOptionException
{
const string name;
UnknownOptionException(string name_arg) : name{move(name_arg)}
UnknownOptionException(string name_arg) : name {move(name_arg)}
{
}
};
@ -277,13 +283,13 @@ public:
Throws bad_variant_access if the option has a value of a different type. */
template<class T>
T
get(const string &name) const
get(const string& name) const
{
auto it = options.find(name);
if (it != options.end())
return std::get<T>(it->second);
else
throw UnknownOptionException{name};
throw UnknownOptionException {name};
}
/* Retrieves the value of the option with that name.
@ -291,7 +297,7 @@ public:
Throws bad_variant_access if the option has a value of a different type. */
template<class T>
optional<T>
get_if(const string &name) const
get_if(const string& name) const
{
auto it = options.find(name);
if (it != options.end())
@ -304,27 +310,29 @@ public:
Throws UnknownOptionException if there is no option with that name. */
template<class Visitor>
decltype(auto)
visit(const string &name, Visitor &&vis) const
visit(const string& name, Visitor&& vis) const
{
auto it = options.find(name);
if (it != options.end())
return std::visit(forward<Visitor>(vis), it->second);
else
throw UnknownOptionException{name};
throw UnknownOptionException {name};
}
void writeOutput(ostream &output) const;
void writeOutput(ostream &output, const string &option_group) const;
void writeJsonOutput(ostream &output) const;
void writeOutput(ostream& output) const;
void writeOutput(ostream& output, const string& option_group) const;
void writeJsonOutput(ostream& output) const;
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;
void writeOutputCommon(ostream &output, const string &option_group) const;
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,47 +17,46 @@
* 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,
ExternalFunctionsTable &external_functions_table_arg) :
ModelTree{symbol_table_arg, num_constants_arg, external_functions_table_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}
{
}
void
StaticModel::copyHelper(const StaticModel &m)
StaticModel::copyHelper(const StaticModel& m)
{
auto f = [this](const ExprNode *e) { return e->clone(*this); };
auto f = [this](const ExprNode* e) { return e->clone(*this); };
for (const auto &it : m.ramsey_multipliers_derivatives_temporary_terms)
for (const auto& it : m.ramsey_multipliers_derivatives_temporary_terms)
ramsey_multipliers_derivatives_temporary_terms.insert(f(it));
for (const auto &it : m.ramsey_multipliers_derivatives_temporary_terms_idxs)
for (const auto& it : m.ramsey_multipliers_derivatives_temporary_terms_idxs)
ramsey_multipliers_derivatives_temporary_terms_idxs.emplace(f(it.first), it.second);
}
StaticModel::StaticModel(const StaticModel &m) :
ModelTree{m},
ramsey_multipliers_derivatives{m.ramsey_multipliers_derivatives},
ramsey_multipliers_derivatives_sparse_colptr{m.ramsey_multipliers_derivatives_sparse_colptr},
static_mfs{m.static_mfs}
StaticModel::StaticModel(const StaticModel& m) :
ModelTree {m},
ramsey_multipliers_derivatives {m.ramsey_multipliers_derivatives},
ramsey_multipliers_derivatives_sparse_colptr {m.ramsey_multipliers_derivatives_sparse_colptr},
static_mfs {m.static_mfs}
{
copyHelper(m);
}
StaticModel &
StaticModel::operator=(const StaticModel &m)
StaticModel&
StaticModel::operator=(const StaticModel& m)
{
ModelTree::operator=(m);
@ -71,8 +70,8 @@ StaticModel::operator=(const StaticModel &m)
return *this;
}
StaticModel::StaticModel(const DynamicModel &m) :
ModelTree{m.symbol_table, m.num_constants, m.external_functions_table}
StaticModel::StaticModel(const DynamicModel& m) :
ModelTree {m.symbol_table, m.num_constants, m.external_functions_table}
{
// Convert model local variables (need to be done first)
for (int it : m.local_variables_vector)
@ -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);
}
@ -123,14 +122,14 @@ StaticModel::StaticModel(const DynamicModel &m) :
}
void
StaticModel::writeStaticBytecode(const string &basename) const
StaticModel::writeStaticBytecode(const string& basename) const
{
/* Bytecode only works when there are with as many endogenous as equations.
(e.g. the constructor of FBEGINBLOCK_ makes this assumption) */
assert(static_cast<int>(equations.size()) == symbol_table.endo_nbr());
// First write the .bin file
int u_count_int { writeBytecodeBinFile(basename + "/model/bytecode/static.bin", false) };
int u_count_int {writeBytecodeBinFile(basename + "/model/bytecode/static.bin", false)};
BytecodeWriter code_file {basename + "/model/bytecode/static.cod"};
vector<int> eq_idx(equations.size());
@ -139,23 +138,23 @@ StaticModel::writeStaticBytecode(const string &basename) const
iota(endo_idx.begin(), endo_idx.end(), 0);
// Declare temporary terms and the (single) block
code_file << FDIMST_{static_cast<int>(temporary_terms_derivatives[0].size()
+ temporary_terms_derivatives[1].size())}
<< FBEGINBLOCK_{symbol_table.endo_nbr(),
BlockSimulationType::solveForwardComplete,
0,
symbol_table.endo_nbr(),
endo_idx,
eq_idx,
false,
u_count_int,
symbol_table.endo_nbr()};
code_file << FDIMST_ {static_cast<int>(temporary_terms_derivatives[0].size()
+ temporary_terms_derivatives[1].size())}
<< FBEGINBLOCK_ {symbol_table.endo_nbr(),
BlockSimulationType::solveForwardComplete,
0,
symbol_table.endo_nbr(),
endo_idx,
eq_idx,
false,
u_count_int,
symbol_table.endo_nbr()};
writeBytecodeHelper<false>(code_file);
}
void
StaticModel::writeStaticBlockBytecode(const string &basename) const
StaticModel::writeStaticBlockBytecode(const string& basename) const
{
BytecodeWriter code_file {basename + "/model/bytecode/block/static.cod"};
@ -168,7 +167,7 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
}
// Temporary variables declaration
code_file << FDIMST_{static_cast<int>(blocks_temporary_terms_idxs.size())};
code_file << FDIMST_ {static_cast<int>(blocks_temporary_terms_idxs.size())};
temporary_terms_t temporary_terms_written;
@ -178,27 +177,29 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
const int block_size {blocks[block].size};
const int u_count {simulation_type == BlockSimulationType::solveBackwardComplete
|| simulation_type == BlockSimulationType::solveForwardComplete
? writeBlockBytecodeBinFile(bin_file, block)
: 0};
|| simulation_type == BlockSimulationType::solveForwardComplete
? writeBlockBytecodeBinFile(bin_file, block)
: 0};
code_file << FBEGINBLOCK_{blocks[block].mfs_size,
simulation_type,
blocks[block].first_equation,
block_size,
endo_idx_block2orig,
eq_idx_block2orig,
blocks[block].linear,
u_count,
block_size};
code_file << FBEGINBLOCK_ {blocks[block].mfs_size,
simulation_type,
blocks[block].first_equation,
block_size,
endo_idx_block2orig,
eq_idx_block2orig,
blocks[block].linear,
u_count,
block_size};
writeBlockBytecodeHelper<false>(code_file, block, temporary_terms_written);
}
code_file << FEND_{};
code_file << FEND_ {};
}
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();
@ -209,9 +210,10 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co
is not needed for parameter derivatives, since tensors for those are not
stored as matrices. This check is implemented at this place for symmetry
with DynamicModel::computingPass(). */
if (log2(symbol_table.endo_nbr())*derivsOrder >= numeric_limits<int>::digits)
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,42 +245,43 @@ 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);
}
}
void
StaticModel::writeStaticMFile(const string &basename) const
StaticModel::writeStaticMFile(const string& basename) const
{
auto [d_output, tt_output] = writeModelFileHelper<ExprNodeOutputType::matlabStaticModel>();
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()) };
for (size_t i{2}; i < derivatives.size(); i++)
int ncols {symbol_table.endo_nbr()};
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();
ntt += temporary_terms_derivatives[i].size();
string gname{"g" + to_string(i)};
string gprevname{"g" + to_string(i-1)};
string gname {"g" + to_string(i)};
string gprevname {"g" + to_string(i - 1)};
init_output.str("");
end_output.str("");
@ -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);
}
@ -306,7 +306,7 @@ StaticModel::writeStaticMFile(const string &basename) const
}
void
StaticModel::writeStaticMWrapperFunction(const string &basename, const string &ending) const
StaticModel::writeStaticMWrapperFunction(const string& basename, const string& ending) const
{
string name;
if (ending == "g1")
@ -317,7 +317,7 @@ StaticModel::writeStaticMWrapperFunction(const string &basename, const string &e
name = "static_resid_g1_g2_g3";
filesystem::path filename {packageDir(basename) / (name + ".m")};
ofstream output{filename, ios::out | ios::binary};
ofstream output {filename, ios::out | ios::binary};
if (!output.is_open())
{
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
@ -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,15 +359,14 @@ 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};
ofstream output {filename, ios::out | ios::binary};
if (!output.is_open())
{
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
@ -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,51 +419,64 @@ 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
<< " 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();
}
void
StaticModel::writeStaticMCompatFile(const string &basename) const
StaticModel::writeStaticMCompatFile(const string& basename) const
{
filesystem::path filename {packageDir(basename) / "static.m"};
ofstream output{filename, ios::out | ios::binary};
ofstream output {filename, ios::out | ios::binary};
if (!output.is_open())
{
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,9 +484,10 @@ 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};
filesystem::path model_dir {basename};
model_dir /= "model";
if (use_dll)
{
@ -531,10 +554,10 @@ StaticModel::exoPresentInEqs() const
}
void
StaticModel::writeDriverOutput(ostream &output) const
StaticModel::writeDriverOutput(ostream& output) const
{
output << "M_.static_tmp_nbr = [";
for (const auto &temporary_terms_derivative : temporary_terms_derivatives)
for (const auto& temporary_terms_derivative : temporary_terms_derivatives)
output << temporary_terms_derivative.size() << "; ";
output << "];" << endl;
@ -545,46 +568,47 @@ StaticModel::writeDriverOutput(ostream &output) const
}
void
StaticModel::writeBlockDriverOutput(ostream &output) const
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
<< "M_.block_structure_stat.block(" << blk+1 << ").equation = [";
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 << " " << getBlockEquationID(blk, eq) + 1;
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 << " " << getBlockVariableID(blk, var) + 1;
output << "];" << endl;
}
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 << " " << endo_idx_block2orig[i] + 1;
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 << " " << 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)
for (const auto& [indices, d1] : derivatives[1])
if (int deriv_id = indices[1]; getTypeByDerivID(deriv_id) == SymbolType::endogenous)
{
int eq = indices[0];
int var { getTypeSpecificIDByDerivID(deriv_id) };
int var {getTypeSpecificIDByDerivID(deriv_id)};
row_incidence.emplace(eq, var);
}
output << "M_.block_structure_stat.incidence.sparse_IM = [" << endl;
for (auto [eq, var] : row_incidence)
output << " " << eq+1 << " " << var+1 << ";" << endl;
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);
}
@ -638,11 +662,11 @@ StaticModel::getDerivID(int symb_id, [[maybe_unused]] int lag) const noexcept(fa
else
/* See the special treatment in VariableNode::prepareForDerivation(),
VariableNode::computeDerivative() and VariableNode::getChainRuleDerivative() */
throw UnknownDerivIDException{};
throw UnknownDerivIDException {};
}
void
StaticModel::addAllParamDerivId(set<int> &deriv_id_set)
StaticModel::addAllParamDerivId(set<int>& deriv_id_set)
{
for (int i = 0; i < symbol_table.param_nbr(); i++)
deriv_id_set.insert(i + symbol_table.endo_nbr());
@ -660,12 +684,13 @@ StaticModel::computeChainRuleJacobian()
for (int blk = 0; blk < nb_blocks; blk++)
{
int nb_recursives = blocks[blk].getRecursiveSize();
BlockSimulationType simulation_type { blocks[blk].simulation_type };
BlockSimulationType simulation_type {blocks[blk].simulation_type};
map<int, BinaryOpNode *> recursive_vars;
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,9 +709,11 @@ 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;
blocks_derivatives[blk][{eq, var, 0}] = d1;
}
}
@ -694,35 +721,38 @@ StaticModel::computeChainRuleJacobian()
if (simulation_type != BlockSimulationType::evaluateForward
&& simulation_type != BlockSimulationType::evaluateBackward)
{
for (const auto &[indices, d1] : blocks_derivatives[blk])
for (const auto& [indices, d1] : blocks_derivatives[blk])
{
auto &[eq, var, lag] { indices };
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);
}
}
}
void
StaticModel::writeLatexFile(const string &basename, bool write_equation_tags) const
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
StaticModel::writeAuxVarInitval(ostream &output, ExprNodeOutputType output_type) const
StaticModel::writeAuxVarInitval(ostream& output, ExprNodeOutputType output_type) const
{
for (auto aux_equation : aux_equations)
{
dynamic_cast<ExprNode *>(aux_equation)->writeOutput(output, output_type);
dynamic_cast<ExprNode*>(aux_equation)->writeOutput(output, output_type);
output << ";" << endl;
}
}
void
StaticModel::writeLatexAuxVarRecursiveDefinitions(ostream &output) const
StaticModel::writeLatexAuxVarRecursiveDefinitions(ostream& output) const
{
deriv_node_temp_terms_t tef_terms;
temporary_terms_t temporary_terms;
@ -734,13 +764,14 @@ 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;
}
}
void
StaticModel::writeJsonAuxVarRecursiveDefinitions(ostream &output) const
StaticModel::writeJsonAuxVarRecursiveDefinitions(ostream& output) const
{
deriv_node_temp_terms_t tef_terms;
temporary_terms_t temporary_terms;
@ -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 << ", ";
@ -770,11 +800,10 @@ StaticModel::writeJsonAuxVarRecursiveDefinitions(ostream &output) const
}
void
StaticModel::writeJsonOutput(ostream &output) const
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 << ", ";
@ -785,42 +814,37 @@ StaticModel::writeJsonOutput(ostream &output) const
}
void
StaticModel::writeJsonComputingPassOutput(ostream &output, bool writeDetails) const
StaticModel::writeJsonComputingPassOutput(ostream& output, bool writeDetails) const
{
auto [mlv_output, d_output] { writeJsonComputingPassOutputHelper<false>(writeDetails) };
auto [mlv_output, d_output] {writeJsonComputingPassOutputHelper<false>(writeDetails)};
if (writeDetails)
output << R"("static_model": {)";
else
output << R"("static_model_simple": {)";
output << mlv_output.str();
for (const auto &it : d_output)
for (const auto& it : d_output)
output << ", " << it.str();
output << "}";
}
void
StaticModel::writeJsonParamsDerivatives(ostream &output, bool writeDetails) const
StaticModel::writeJsonParamsDerivatives(ostream& output, bool writeDetails) const
{
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
@ -828,16 +852,16 @@ StaticModel::computeRamseyMultipliersDerivatives(int ramsey_orig_endo_nbr, bool
bool no_tmp_terms)
{
// Compute derivation IDs of Lagrange multipliers
set<int> mult_symb_ids { symbol_table.getLagrangeMultipliers() };
set<int> mult_symb_ids {symbol_table.getLagrangeMultipliers()};
vector<int> mult_deriv_ids;
for (int symb_id : mult_symb_ids)
mult_deriv_ids.push_back(getDerivID(symb_id, 0));
// Compute the list of aux vars for which to apply the chain rule derivation
map<int, BinaryOpNode *> recursive_variables;
map<int, BinaryOpNode*> recursive_variables;
for (auto aux_eq : aux_equations)
{
auto varexpr { dynamic_cast<VariableNode *>(aux_eq->arg1) };
auto varexpr {dynamic_cast<VariableNode*>(aux_eq->arg1)};
assert(varexpr && symbol_table.isAuxiliaryVariable(varexpr->symb_id));
/* Determine whether the auxiliary variable has been added after the last
Lagrange multiplier. We use the guarantee given by SymbolTable that
@ -851,64 +875,64 @@ StaticModel::computeRamseyMultipliersDerivatives(int ramsey_orig_endo_nbr, bool
unordered_map<expr_t, map<int, expr_t>> cache;
for (int eq {0}; eq < ramsey_orig_endo_nbr; eq++)
for (int mult {0}; mult < static_cast<int>(mult_deriv_ids.size()); mult++)
if (expr_t d { equations[eq]->getChainRuleDerivative(mult_deriv_ids[mult], recursive_variables,
non_null_chain_rule_derivatives, cache) };
if (expr_t d {equations[eq]->getChainRuleDerivative(mult_deriv_ids[mult], recursive_variables,
non_null_chain_rule_derivatives, cache)};
d != Zero)
ramsey_multipliers_derivatives.try_emplace({ eq, mult }, d);
ramsey_multipliers_derivatives.try_emplace({eq, mult}, d);
// Compute the temporary terms
map<pair<int, int>, unordered_set<expr_t>> temp_terms_map;
unordered_map<expr_t, pair<int, pair<int, int>>> reference_count;
for (const auto &[row_col, d] : ramsey_multipliers_derivatives)
d->computeTemporaryTerms({ 1, 0 }, temp_terms_map, reference_count, is_matlab);
for (const auto& [row_col, d] : ramsey_multipliers_derivatives)
d->computeTemporaryTerms({1, 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); });
for (auto& it : temp_terms_map)
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
StaticModel::writeDriverRamseyMultipliersDerivativesSparseIndices(ostream &output) const
StaticModel::writeDriverRamseyMultipliersDerivativesSparseIndices(ostream& output) const
{
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([";
for (auto &[row_col, d] : ramsey_multipliers_derivatives)
output << row_col.second+1 << ' ';
output << "]);" << endl
<< "M_.ramsey_multipliers_static_g1_sparse_colptr = int32([";
for (auto& [row_col, d] : ramsey_multipliers_derivatives)
output << row_col.first + 1 << ' ';
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([";
for (int it : ramsey_multipliers_derivatives_sparse_colptr)
output << it+1 << ' ';
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 };
constexpr auto output_type {ExprNodeOutputType::matlabStaticModel};
filesystem::path filename {packageDir(basename) / "ramsey_multipliers_static_g1.m"};
ofstream output_file{filename, ios::out | ios::binary};
ofstream output_file {filename, ios::out | ios::binary};
if (!output_file.is_open())
{
cerr << "ERROR: Can't open file " << filename.string() << " for writing" << endl;
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,36 +942,42 @@ 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"};
constexpr auto output_type {ExprNodeOutputType::CStaticModel};
const filesystem::path model_src_dir {filesystem::path {basename} / "model" / "src"};
const int xlen { symbol_table.exo_nbr()+symbol_table.exo_det_nbr() };
const int nzval { static_cast<int>(ramsey_multipliers_derivatives.size()) };
const int ncols { static_cast<int>(symbol_table.getLagrangeMultipliers().size()) };
const int xlen {symbol_table.exo_nbr() + symbol_table.exo_det_nbr()};
const int nzval {static_cast<int>(ramsey_multipliers_derivatives.size())};
const int ncols {static_cast<int>(symbol_table.getLagrangeMultipliers().size())};
const filesystem::path p {model_src_dir / "ramsey_multipliers_static_g1.c"};
ofstream output{p, ios::out | ios::binary};
ofstream output {p, ios::out | ios::binary};
if (!output.is_open())
{
cerr << "ERROR: Can't open file " << p.string() << " for writing" << endl;
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,18 +1021,20 @@ 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
<< " 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;
output.close();
compileMEX(packageDir(basename), "ramsey_multipliers_static_g1", mexext, { p }, matlabroot);
compileMEX(packageDir(basename), "ramsey_multipliers_static_g1", mexext, {p}, matlabroot);
}

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;
@ -58,23 +58,24 @@ private:
NB: the default value defined here is not used when converting from
DynamicModel class, and in particular it does not affect the main model
block. See the DynamicModel class for the default value in that case. */
int static_mfs{0};
int static_mfs {0};
// Writes static model file (MATLAB/Octave version, legacy representation)
void writeStaticMFile(const string &basename) const;
void writeStaticMFile(const string& basename) const;
//! Writes the code of the block-decomposed model in virtual machine bytecode
void writeStaticBlockBytecode(const string &basename) const;
void writeStaticBlockBytecode(const string& basename) const;
//! Writes the code of the model in virtual machine bytecode
void writeStaticBytecode(const string &basename) const;
void writeStaticBytecode(const string& basename) const;
//! Computes jacobian and prepares for equation normalization
/*! Using values from initval/endval blocks and parameter initializations:
- computes the jacobian for the model w.r. to contemporaneous variables
- removes edges of the incidence matrix when derivative w.r. to the corresponding variable is too close to zero (below the cutoff)
- 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);
void evaluateJacobian(const eval_context_t& eval_context, jacob_map_t* j_m, bool dynamic);
SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override;
int getLagByDerivID(int deriv_id) const noexcept(false) override;
@ -96,38 +97,37 @@ 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,
const ostringstream &init_s, const ostringstream &end_s,
const ostringstream &s, const ostringstream &s_tt) const;
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
derivatives at the same time (legacy representation) */
void writeStaticMWrapperFunction(const string &basename, const string &ending) const;
void writeStaticMWrapperFunction(const string& basename, const string& ending) const;
/* Create the compatibility static.m file for MATLAB/Octave not yet using the
temporary terms array interface (legacy representation) */
void writeStaticMCompatFile(const string &name) const;
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();
}
// Write the block structure of the model in the driver file
void writeBlockDriverOutput(ostream &output) const;
void writeBlockDriverOutput(ostream& output) const;
// Helper for writing ramsey_multipliers_derivatives
template<ExprNodeOutputType output_type>
void writeRamseyMultipliersDerivativesHelper(ostream &output) const;
void writeRamseyMultipliersDerivativesHelper(ostream& output) const;
//! Internal helper for the copy constructor and assignment operator
/*! Copies all the structures that contain ExprNode*, by the converting the
pointers into their equivalent in the new tree */
void copyHelper(const StaticModel &m);
void copyHelper(const StaticModel& m);
protected:
string
@ -137,71 +137,77 @@ protected:
}
public:
StaticModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants,
ExternalFunctionsTable &external_functions_table_arg);
StaticModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants,
ExternalFunctionsTable& external_functions_table_arg);
StaticModel(const StaticModel &m);
StaticModel &operator=(const StaticModel &m);
StaticModel(const StaticModel& m);
StaticModel& operator=(const StaticModel& m);
//! Creates the static version of a dynamic model
explicit StaticModel(const DynamicModel &m);
explicit StaticModel(const DynamicModel& m);
//! Writes information about the static model to the driver file
void writeDriverOutput(ostream &output) const;
void writeDriverOutput(ostream& output) const;
//! Execute computations (variable sorting + derivation + block decomposition)
/*!
\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;
void writeJsonOutput(ostream& output) const;
//! Write JSON representation of static model
void writeJsonComputingPassOutput(ostream &output, bool writeDetails) const;
void writeJsonComputingPassOutput(ostream& output, bool writeDetails) const;
//! Write JSON params derivatives
void writeJsonParamsDerivatives(ostream &output, bool writeDetails) const;
void writeJsonParamsDerivatives(ostream& output, bool writeDetails) const;
//! Writes file containing static parameters derivatives
template<bool julia>
void writeParamsDerivativesFile(const string &basename) const;
void writeParamsDerivativesFile(const string& basename) const;
//! Writes LaTeX file with the equations of the static model
void writeLatexFile(const string &basename, bool write_equation_tags) const;
void writeLatexFile(const string& basename, bool write_equation_tags) const;
//! Writes initializations in oo_.steady_state or steady state file for the auxiliary variables
void writeAuxVarInitval(ostream &output, ExprNodeOutputType output_type) const;
void writeAuxVarInitval(ostream& output, ExprNodeOutputType output_type) const;
void writeLatexAuxVarRecursiveDefinitions(ostream &output) const;
void writeJsonAuxVarRecursiveDefinitions(ostream &output) const;
void writeLatexAuxVarRecursiveDefinitions(ostream& output) const;
void writeJsonAuxVarRecursiveDefinitions(ostream& output) const;
//! To ensure that no exogenous is present in the planner objective
//! See #1264
bool exoPresentInEqs() const;
int getDerivID(int symb_id, int lag) const noexcept(false) override;
void addAllParamDerivId(set<int> &deriv_id_set) override;
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;
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
@ -212,18 +218,19 @@ public:
template<bool julia>
void
StaticModel::writeParamsDerivativesFile(const string &basename) const
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)
if constexpr (!julia)
{
filesystem::path filename {packageDir(basename) / "static_params_derivs.m"};
ofstream paramsDerivsFile {filename, ios::out | ios::binary};
@ -232,57 +239,97 @@ 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
<< "%" << 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
<< "%" << 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
<< "%" << endl
<< "%" << endl
<< "% Warning : this file is generated automatically by Dynare" << endl
<< "% from model file (.mod)" << endl << endl
<< "T = NaN(" << params_derivs_temporary_terms_idxs.size() << ",1);" << endl
<< 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
<< "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
<< "if nargout >= 5" << endl
<< "hp = zeros(" << params_derivatives.at({ 2, 1 }).size() << ",5);" << endl
<< hp_output.str()
<< "end" << endl
<< "end" << 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
<< "%" << 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
<< "%" << 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
<< "%" << endl
<< "%" << endl
<< "% Warning : this file is generated automatically by Dynare" << endl
<< "% from model file (.mod)" << endl
<< endl
<< "T = NaN(" << params_derivs_temporary_terms_idxs.size() << ",1);" << endl
<< 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
<< "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
<< "if nargout >= 5" << endl
<< "hp = zeros(" << params_derivatives.at({2, 1}).size() << ",5);" << endl
<< hp_output.str() << "end" << endl
<< "end" << endl;
paramsDerivsFile.close();
}
else
@ -293,46 +340,42 @@ 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");
}
}
template<ExprNodeOutputType output_type>
void
StaticModel::writeRamseyMultipliersDerivativesHelper(ostream &output) const
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;
@ -43,10 +43,11 @@ using namespace std;
class TrendComponentModelTable
{
private:
SymbolTable &symbol_table;
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;
@ -57,35 +58,34 @@ private:
in the structural VAR context. */
map<string, map<tuple<int, int>, expr_t>> A0, A0star; // name -> (eqn, col) -> expr_t
public:
explicit TrendComponentModelTable(SymbolTable &symbol_table_arg);
explicit TrendComponentModelTable(SymbolTable& symbol_table_arg);
//! Add a trend component model
void addTrendComponentModel(string name_arg, vector<string> eqtags_arg,
vector<string> target_eqtags_arg);
inline bool isExistingTrendComponentModelName(const string &name_arg) const;
inline bool isExistingTrendComponentModelName(const string& name_arg) const;
inline bool empty() const;
const map<string, vector<string>> &getEqTags() const;
const vector<string> &getEqTags(const string &name_arg) const;
const map<string, vector<string>> &getTargetEqTags() const;
const map<string, vector<int>> &getEqNums() const;
const map<string, vector<int>> &getTargetEqNums() const;
const vector<int> &getTargetEqNums(const string &name_arg) const;
const vector<int> &getEqNums(const string &name_arg) const;
const vector<int> &getMaxLags(const string &name_arg) const;
int getMaxLag(const string &name_arg) const;
const vector<int> &getLhs(const string &name_arg) const;
const vector<expr_t> &getLhsExprT(const string &name_arg) const;
const vector<bool> &getDiff(const string &name_arg) const;
const map<string, vector<int>> &getNonTargetEqNums() const;
const vector<int> &getNonTargetEqNums(const string &name_arg) const;
const vector<int> &getNonTargetLhs(const string &name_arg) const;
const vector<int> &getTargetLhs(const string &name_arg) const;
const map<string, vector<string>>& getEqTags() const;
const vector<string>& getEqTags(const string& name_arg) const;
const map<string, vector<string>>& getTargetEqTags() const;
const map<string, vector<int>>& getEqNums() const;
const map<string, vector<int>>& getTargetEqNums() const;
const vector<int>& getTargetEqNums(const string& name_arg) const;
const vector<int>& getEqNums(const string& name_arg) const;
const vector<int>& getMaxLags(const string& name_arg) const;
int getMaxLag(const string& name_arg) const;
const vector<int>& getLhs(const string& name_arg) const;
const vector<expr_t>& getLhsExprT(const string& name_arg) const;
const vector<bool>& getDiff(const string& name_arg) const;
const map<string, vector<int>>& getNonTargetEqNums() const;
const vector<int>& getNonTargetEqNums(const string& name_arg) const;
const vector<int>& getNonTargetLhs(const string& name_arg) const;
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);
@ -96,18 +96,18 @@ public:
map<string, map<tuple<int, int>, expr_t>> A0star_arg);
//! Write output of this class
void writeOutput(const string &basename, ostream &output) const;
void writeOutput(const string& basename, ostream& output) const;
//! Write JSON Output
void writeJsonOutput(ostream &output) const;
void writeJsonOutput(ostream& output) const;
private:
void checkModelName(const string &name_arg) const;
void checkModelName(const string& name_arg) const;
void setNonTargetEqnums();
};
inline bool
TrendComponentModelTable::isExistingTrendComponentModelName(const string &name_arg) const
TrendComponentModelTable::isExistingTrendComponentModelName(const string& name_arg) const
{
return names.contains(name_arg);
}
@ -121,43 +121,45 @@ TrendComponentModelTable::empty() const
class VarModelTable
{
private:
SymbolTable &symbol_table;
SymbolTable& symbol_table;
set<string> names;
map<string, bool> structural; // Whether VARs are structural or reduced-form
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
context. */
map<string, map<tuple<int, int>, expr_t>> A0; // name -> (eqn, lhs_symb_id) -> param_expr_t
map<string, map<int, expr_t>> constants; // name -> eqn -> constant
map<string, map<int, expr_t>> constants; // name -> eqn -> constant
public:
explicit VarModelTable(SymbolTable &symbol_table_arg);
explicit VarModelTable(SymbolTable& symbol_table_arg);
//! Add a VAR model
void addVarModel(string name, bool structural_arg, vector<string> eqtags);
inline bool isExistingVarModelName(const string &name_arg) const;
inline bool isExistingVarModelName(const string& name_arg) const;
inline bool empty() const;
const map<string, bool> &getStructural() const;
const map<string, vector<string>> &getEqTags() const;
const vector<string> &getEqTags(const string &name_arg) const;
const map<string, vector<int>> &getEqNums() const;
const vector<bool> &getDiff(const string &name_arg) const;
const vector<int> &getEqNums(const string &name_arg) const;
const vector<int> &getMaxLags(const string &name_arg) const;
int getMaxLag(const string &name_arg) const;
const vector<int> &getLhs(const string &name_arg) const;
const vector<int> &getLhsOrigIds(const string &name_arg) const;
const vector<set<pair<int, int>>> &getRhs(const string &name_arg) const;
const vector<expr_t> &getLhsExprT(const string &name_arg) const;
const map<string, bool>& getStructural() const;
const map<string, vector<string>>& getEqTags() const;
const vector<string>& getEqTags(const string& name_arg) const;
const map<string, vector<int>>& getEqNums() const;
const vector<bool>& getDiff(const string& name_arg) const;
const vector<int>& getEqNums(const string& name_arg) const;
const vector<int>& getMaxLags(const string& name_arg) const;
int getMaxLag(const string& name_arg) const;
const vector<int>& getLhs(const string& name_arg) const;
const vector<int>& getLhsOrigIds(const string& name_arg) const;
const vector<set<pair<int, int>>>& getRhs(const string& name_arg) const;
const vector<expr_t>& getLhsExprT(const string& name_arg) const;
void setEqNums(map<string, vector<int>> eqnums_arg);
void setLhs(map<string, vector<int>> lhs_arg);
@ -171,17 +173,17 @@ public:
void setConstants(map<string, map<int, expr_t>> constants_arg);
//! Write output of this class
void writeOutput(const string &basename, ostream &output) const;
void writeOutput(const string& basename, ostream& output) const;
//! Write JSON Output
void writeJsonOutput(ostream &output) const;
void writeJsonOutput(ostream& output) const;
private:
void checkModelName(const string &name_arg) const;
void checkModelName(const string& name_arg) const;
};
inline bool
VarModelTable::isExistingVarModelName(const string &name_arg) const
VarModelTable::isExistingVarModelName(const string& name_arg) const
{
return names.contains(name_arg);
}
@ -195,7 +197,7 @@ VarModelTable::empty() const
class VarExpectationModelTable
{
private:
SymbolTable &symbol_table;
SymbolTable& symbol_table;
set<string> names;
map<string, expr_t> expression;
map<string, string> aux_model_name;
@ -206,26 +208,31 @@ 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);
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 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,
const TrendComponentModelTable &trend_component_model_table);
void writeOutput(ostream &output) const;
void writeJsonOutput(ostream &output) const;
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;
};
class PacModelTable
{
private:
SymbolTable &symbol_table;
SymbolTable& symbol_table;
set<string> names;
map<string, string> aux_model_name;
map<string, string> discount;
@ -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,44 +306,49 @@ 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)
map<string, tuple<expr_t, string, vector<target_component_t>>> target_info;
int pacEquationMaxLag(const string &name_arg) const;
int pacEquationMaxLag(const string& name_arg) const;
// Return a text representation of a kind (but fails on “unspecified” kind value)
static string kindToString(PacTargetKind kind);
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);
bool isExistingPacModelName(const string &name_arg) const;
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);
bool isExistingPacModelName(const string& name_arg) const;
bool empty() const;
void checkPass(ModFileStructure &mod_file_struct);
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 findDiffNodesInGrowth(lag_equivalence_table_t &diff_nodes) const;
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,
const TrendComponentModelTable &trend_component_model_table);
void writeOutput(ostream &output) const;
void writeJsonOutput(ostream &output) const;
void setTargetExpr(const string &name_arg, expr_t target);
void setTargetAuxnameNonstationary(const string &name_arg, string auxname);
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,
const TrendComponentModelTable& trend_component_model_table);
void writeOutput(ostream& output) const;
void writeJsonOutput(ostream& output) const;
void setTargetExpr(const string& name_arg, expr_t target);
void setTargetAuxnameNonstationary(const string& name_arg, string auxname);
/* Only the first four elements of the tuple are expected to be set by the
caller. The other ones will be filled by this class. */
void addTargetComponent(const string &name_arg, target_component_t component);
void writeTargetCoefficientsFile(const string &basename) const;
void addTargetComponent(const string& name_arg, target_component_t component);
void writeTargetCoefficientsFile(const string& basename) const;
};
#endif

View File

@ -21,14 +21,13 @@
#include "SymbolList.hh"
SymbolList::SymbolList(vector<string> symbols_arg) :
symbols{move(symbols_arg)}
SymbolList::SymbolList(vector<string> symbols_arg) : symbols {move(symbols_arg)}
{
}
void
SymbolList::checkPass(WarningConsolidation &warnings, const vector<SymbolType> &types,
const SymbolTable &symbol_table) const noexcept(false)
SymbolList::checkPass(WarningConsolidation& warnings, const vector<SymbolType>& types,
const SymbolTable& symbol_table) const noexcept(false)
{
if (types.empty())
return;
@ -41,20 +40,21 @@ SymbolList::checkPass(WarningConsolidation &warnings, const vector<SymbolType> &
regex_str += "|AUX_ENDO_|LOG_";
break;
}
regex re("^(" + regex_str +")");
for (const auto &symbol : symbols)
regex re("^(" + regex_str + ")");
for (const auto& symbol : symbols)
{
if (!symbol_table.exists(symbol))
{
if (regex_search(symbol, m, re))
{
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;
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;
}
else
throw SymbolListException{"Variable " + symbol + " was not declared."};
throw SymbolListException {"Variable " + symbol + " was not declared."};
}
if (none_of(types.begin(), types.end(),
@ -62,7 +62,7 @@ SymbolList::checkPass(WarningConsolidation &warnings, const vector<SymbolType> &
{
string valid_types;
for (auto type : types)
switch(type)
switch (type)
{
case SymbolType::endogenous:
valid_types += "endogenous, ";
@ -104,18 +104,17 @@ SymbolList::checkPass(WarningConsolidation &warnings, const vector<SymbolType> &
valid_types += "excludedVariable, ";
break;
}
valid_types = valid_types.erase(valid_types.size()-2, 2);
throw SymbolListException{"Variable " + symbol + " is not one of {" + valid_types + "}"};
valid_types = valid_types.erase(valid_types.size() - 2, 2);
throw SymbolListException {"Variable " + symbol + " is not one of {" + valid_types + "}"};
}
}
}
void
SymbolList::writeOutput(const string &varname, ostream &output) const
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 << ";";
@ -125,11 +124,10 @@ SymbolList::writeOutput(const string &varname, ostream &output) const
}
void
SymbolList::writeJsonOutput(ostream &output) const
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 << ",";
@ -145,14 +143,15 @@ SymbolList::getSymbols() const
}
void
SymbolList::removeDuplicates(const string &dynare_command, WarningConsolidation &warnings)
SymbolList::removeDuplicates(const string& dynare_command, WarningConsolidation& warnings)
{
vector<string> unique_symbols;
for (const auto &it : symbols)
for (const auto& it : symbols)
if (find(unique_symbols.begin(), unique_symbols.end(), it) == unique_symbols.end())
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
@ -46,16 +47,17 @@ public:
const string message;
};
//! Remove duplicate symbols
void removeDuplicates(const string &dynare_command, WarningConsolidation &warnings);
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;
void writeOutput(const string& varname, ostream& output) const;
//! Output content in Matlab format without preceding varname of writeOutput
void write(ostream &output) const;
void write(ostream& output) const;
//! Write JSON output
void writeJsonOutput(ostream &output) const;
void writeJsonOutput(ostream& output) const;
//! Is Empty
bool
empty() 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();
@ -38,9 +39,9 @@ SymbolTable::addSymbol(const string &name, SymbolType type, const string &tex_na
if (exists(name))
{
if (type_table[getID(name)] == type)
throw AlreadyDeclaredException{name, true};
throw AlreadyDeclaredException {name, true};
else
throw AlreadyDeclaredException{name, false};
throw AlreadyDeclaredException {name, false};
}
string final_tex_name = tex_name;
@ -57,7 +58,7 @@ SymbolTable::addSymbol(const string &name, SymbolType type, const string &tex_na
string final_long_name = name;
bool non_long_name_partition_exists = false;
for (const auto &it : partition_value)
for (const auto& it : partition_value)
if (it.first == "long_name")
final_long_name = it.second;
else
@ -73,7 +74,7 @@ SymbolTable::addSymbol(const string &name, SymbolType type, const string &tex_na
if (non_long_name_partition_exists)
{
map<string, string> pmv;
for (const auto &it : partition_value)
for (const auto& it : partition_value)
pmv[it.first] = it.second;
partition_value_map[id] = pmv;
}
@ -81,7 +82,7 @@ SymbolTable::addSymbol(const string &name, SymbolType type, const string &tex_na
}
int
SymbolTable::addSymbol(const string &name, SymbolType type) noexcept(false)
SymbolTable::addSymbol(const string& name, SymbolType type) noexcept(false)
{
return addSymbol(name, type, "", {});
}
@ -154,26 +155,26 @@ SymbolTable::getID(SymbolType type, int tsid) const noexcept(false)
{
case SymbolType::endogenous:
if (tsid < 0 || tsid >= static_cast<int>(endo_ids.size()))
throw UnknownTypeSpecificIDException{tsid, type};
throw UnknownTypeSpecificIDException {tsid, type};
else
return endo_ids[tsid];
case SymbolType::exogenous:
if (tsid < 0 || tsid >= static_cast<int>(exo_ids.size()))
throw UnknownTypeSpecificIDException{tsid, type};
throw UnknownTypeSpecificIDException {tsid, type};
else
return exo_ids[tsid];
case SymbolType::exogenousDet:
if (tsid < 0 || tsid >= static_cast<int>(exo_det_ids.size()))
throw UnknownTypeSpecificIDException{tsid, type};
throw UnknownTypeSpecificIDException {tsid, type};
else
return exo_det_ids[tsid];
case SymbolType::parameter:
if (tsid < 0 || tsid >= static_cast<int>(param_ids.size()))
throw UnknownTypeSpecificIDException{tsid, type};
throw UnknownTypeSpecificIDException {tsid, type};
else
return param_ids[tsid];
default:
throw UnknownTypeSpecificIDException{tsid, type};
throw UnknownTypeSpecificIDException {tsid, type};
}
}
@ -181,15 +182,15 @@ map<string, map<int, string>>
SymbolTable::getPartitionsForType(SymbolType st) const noexcept(false)
{
map<string, map<int, string>> partitions;
for (const auto &it : partition_value_map)
for (const auto& it : partition_value_map)
if (getType(it.first) == st)
for (const auto &it1 : it.second)
for (const auto& it1 : it.second)
partitions[it1.first][it.first] = it1.second;
return partitions;
}
void
SymbolTable::writeOutput(ostream &output) const noexcept(false)
SymbolTable::writeOutput(ostream& output) const noexcept(false)
{
if (!frozen)
throw NotYetFrozenException();
@ -200,18 +201,19 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
output << "M_.exo_names_tex = cell(" << exo_nbr() << ",1);" << endl;
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;
for (auto &partition : getPartitionsForType(SymbolType::exogenous))
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;
for (auto& partition : getPartitionsForType(SymbolType::exogenous))
if (partition.first != "long_name")
{
output << "M_.exo_partitions." << partition.first << " = { ";
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,11 +237,14 @@ 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))
for (auto& partition : getPartitionsForType(SymbolType::exogenousDet))
if (partition.first != "long_name")
{
output << "M_.exo_det_partitions." << partition.first << " = { ";
@ -261,19 +266,20 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
output << "M_.endo_names_tex = cell(" << endo_nbr() << ",1);" << endl;
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;
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;
output << "M_.endo_partitions = struct();" << endl;
for (auto &partition : getPartitionsForType(SymbolType::endogenous))
for (auto& partition : getPartitionsForType(SymbolType::endogenous))
if (partition.first != "long_name")
{
output << "M_.endo_partitions." << partition.first << " = { ";
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,22 +294,24 @@ 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;
}
output << "M_.param_partitions = struct();" << endl;
for (auto &partition : getPartitionsForType(SymbolType::parameter))
for (auto& partition : getPartitionsForType(SymbolType::parameter))
if (partition.first != "long_name")
{
output << "M_.param_partitions." << partition.first << " = { ";
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,26 +355,34 @@ 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 = '";
output << "M_.aux_vars(" << i + 1 << ").orig_expr = '";
orig_expr->writeJsonOutput(output, {}, {});
output << "';" << endl;
}
@ -374,73 +392,77 @@ SymbolTable::writeOutput(ostream &output) const noexcept(false)
{
output << "M_.predetermined_variables = [ ";
for (int predetermined_variable : predetermined_variables)
output << getTypeSpecificID(predetermined_variable)+1 << " ";
output << getTypeSpecificID(predetermined_variable) + 1 << " ";
output << "];" << endl;
}
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 = [ ";
for (int varob : varobs)
output << getTypeSpecificID(varob)+1 << " ";
output << " ];" << endl;
output << getTypeSpecificID(varob) + 1 << " ";
output << " ];" << endl;
}
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 = [ ";
for (int varexob : varexobs)
output << getTypeSpecificID(varexob)+1 << " ";
output << " ];" << endl;
output << getTypeSpecificID(varexob) + 1 << " ";
output << " ];" << endl;
}
}
int
SymbolTable::addLeadAuxiliaryVarInternal(bool endo, int index, expr_t expr_arg) noexcept(false)
{
string varname{(endo ? "AUX_ENDO_LEAD_" : "AUX_EXO_LEAD_") + to_string(index)};
string varname {(endo ? "AUX_ENDO_LEAD_" : "AUX_EXO_LEAD_") + to_string(index)};
int symb_id;
try
{
symb_id = addSymbol(varname, SymbolType::endogenous);
}
catch (AlreadyDeclaredException &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);
}
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
{
symb_id = addSymbol(varname, SymbolType::endogenous);
}
catch (AlreadyDeclaredException &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);
}
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,24 +487,27 @@ 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)};
string varname {"AUX_EXPECT_"s + (information_set < 0 ? "LAG" : "LEAD") + "_"
+ to_string(abs(information_set)) + "_" + to_string(index)};
int symb_id;
try
{
symb_id = addSymbol(varname, SymbolType::endogenous);
}
catch (AlreadyDeclaredException &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;
@ -499,29 +526,34 @@ SymbolTable::addLogTransformAuxiliaryVar(int orig_symb_id, int orig_lead_lag, ex
{
symb_id = addSymbol(varname, SymbolType::endogenous);
}
catch (AlreadyDeclaredException &e)
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)};
string varname {"AUX_DIFF_LAG_" + to_string(index)};
int symb_id;
try
{
symb_id = addSymbol(varname, SymbolType::endogenous);
}
catch (AlreadyDeclaredException &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);
}
@ -531,17 +563,19 @@ 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)};
string varname {"AUX_DIFF_LEAD_" + to_string(index)};
int symb_id;
try
{
symb_id = addSymbol(varname, SymbolType::endogenous);
}
catch (AlreadyDeclaredException &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);
}
@ -551,41 +585,48 @@ 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)};
string varname {"AUX_DIFF_" + to_string(index)};
int symb_id;
try
{
symb_id = addSymbol(varname, SymbolType::endogenous);
}
catch (AlreadyDeclaredException &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);
}
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)};
string varname {"AUX_UOP_" + to_string(index)};
int symb_id;
try
{
symb_id = addSymbol(varname, SymbolType::endogenous);
}
catch (AlreadyDeclaredException &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);
}
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;
}
@ -593,15 +634,16 @@ SymbolTable::addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op,
int
SymbolTable::addMultiplierAuxiliaryVar(int index) noexcept(false)
{
string varname{"MULT_" + to_string(index+1)};
string varname {"MULT_" + to_string(index + 1)};
int symb_id;
try
{
symb_id = addSymbol(varname, SymbolType::endogenous);
}
catch (AlreadyDeclaredException &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);
}
@ -610,35 +652,41 @@ 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)};
string varname {"AUX_DIFF_FWRD_" + to_string(orig_symb_id + 1)};
int symb_id;
try
{
symb_id = addSymbol(varname, SymbolType::endogenous);
}
catch (AlreadyDeclaredException &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);
}
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;
}
int
SymbolTable::addPacExpectationAuxiliaryVar(const string &name, expr_t expr_arg)
SymbolTable::addPacExpectationAuxiliaryVar(const string& name, expr_t expr_arg)
{
int symb_id;
try
{
symb_id = addSymbol(name, SymbolType::endogenous);
}
catch (AlreadyDeclaredException &e)
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);
}
@ -647,16 +695,19 @@ SymbolTable::addPacExpectationAuxiliaryVar(const string &name, expr_t expr_arg)
}
int
SymbolTable::addPacTargetNonstationaryAuxiliaryVar(const string &name, expr_t expr_arg)
SymbolTable::addPacTargetNonstationaryAuxiliaryVar(const string& name, expr_t expr_arg)
{
int symb_id;
try
{
symb_id = addSymbol(name, SymbolType::endogenous);
}
catch (AlreadyDeclaredException &e)
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);
}
@ -667,45 +718,43 @@ SymbolTable::addPacTargetNonstationaryAuxiliaryVar(const string &name, expr_t ex
int
SymbolTable::searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const noexcept(false)
{
for (const auto &aux_var : aux_vars)
for (const auto& aux_var : aux_vars)
if ((aux_var.type == AuxVarType::endoLag || aux_var.type == AuxVarType::exoLag)
&& aux_var.orig_symb_id == orig_symb_id && aux_var.orig_lead_lag == orig_lead_lag)
return aux_var.symb_id;
throw SearchFailedException{orig_symb_id, orig_lead_lag};
throw SearchFailedException {orig_symb_id, orig_lead_lag};
}
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
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
|| 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};
throw UnknownSymbolIDException {aux_var_symb_id_arg};
}
pair<int, int>
SymbolTable::unrollDiffLeadLagChain(int symb_id, int lag) const noexcept(false)
{
for (const auto &aux_var : aux_vars)
for (const auto& aux_var : aux_vars)
if (aux_var.symb_id == symb_id)
if (aux_var.type == AuxVarType::diffLag || aux_var.type == AuxVarType::diffLead)
{
auto [orig_symb_id, orig_lag] = unrollDiffLeadLagChain(aux_var.orig_symb_id.value(), lag);
return { orig_symb_id, orig_lag + aux_var.orig_lead_lag.value() };
return {orig_symb_id, orig_lag + aux_var.orig_lead_lag.value()};
}
return { symb_id, lag };
return {symb_id, lag};
}
void
@ -803,11 +852,11 @@ SymbolTable::getObservedExogenousVariableIndex(int symb_id) const
return static_cast<int>(it - varexobs.begin());
}
vector <int>
vector<int>
SymbolTable::getTrendVarIds() const
{
vector <int> trendVars;
for (const auto &it : symbol_table)
vector<int> trendVars;
for (const auto& it : symbol_table)
if (getType(it.second) == SymbolType::trend || getType(it.second) == SymbolType::logTrend)
trendVars.push_back(it.second);
return trendVars;
@ -816,8 +865,8 @@ SymbolTable::getTrendVarIds() const
set<int>
SymbolTable::getExogenous() const
{
set <int> exogs;
for (const auto &it : symbol_table)
set<int> exogs;
for (const auto& it : symbol_table)
if (getType(it.second) == SymbolType::exogenous)
exogs.insert(it.second);
return exogs;
@ -826,8 +875,8 @@ SymbolTable::getExogenous() const
set<int>
SymbolTable::getObservedExogenous() const
{
set <int> oexogs;
for (const auto &it : symbol_table)
set<int> oexogs;
for (const auto& it : symbol_table)
if (getType(it.second) == SymbolType::exogenous)
if (isObservedExogenousVariable(it.second))
oexogs.insert(it.second);
@ -837,8 +886,8 @@ SymbolTable::getObservedExogenous() const
set<int>
SymbolTable::getEndogenous() const
{
set <int> endogs;
for (const auto &it : symbol_table)
set<int> endogs;
for (const auto& it : symbol_table)
if (getType(it.second) == SymbolType::endogenous)
endogs.insert(it.second);
return endogs;
@ -847,31 +896,32 @@ 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>
SymbolTable::getOrigEndogenous() const
{
set <int> origendogs;
for (const auto &it : symbol_table)
set<int> origendogs;
for (const auto& it : symbol_table)
if (getType(it.second) == SymbolType::endogenous && !isAuxiliaryVariable(it.second))
origendogs.insert(it.second);
return origendogs;
}
void
SymbolTable::writeJsonOutput(ostream &output) const
SymbolTable::writeJsonOutput(ostream& output) const
{
output << R"("endogenous": )";
writeJsonVarVector(output, endo_ids);
@ -889,20 +939,20 @@ SymbolTable::writeJsonOutput(ostream &output) const
{
output << R"(, "varobs": [)";
for (size_t i = 0; i < varobs.size(); i++)
{
if (i != 0)
output << ", ";
output << R"(")" << getName(varobs[i]) << R"(")";
}
{
if (i != 0)
output << ", ";
output << R"(")" << getName(varobs[i]) << R"(")";
}
output << "]" << endl;
output << R"(, "varobs_ids": [)";
for (size_t i = 0; i < varobs.size(); i++)
{
if (i != 0)
output << ", ";
output << getTypeSpecificID(varobs[i])+1;
}
{
if (i != 0)
output << ", ";
output << getTypeSpecificID(varobs[i]) + 1;
}
output << "]" << endl;
}
@ -910,20 +960,20 @@ SymbolTable::writeJsonOutput(ostream &output) const
{
output << R"(, "varexobs": [)";
for (size_t i = 0; i < varexobs.size(); i++)
{
if (i != 0)
output << ", ";
output << R"(")" << getName(varexobs[i]) << R"(")";
}
{
if (i != 0)
output << ", ";
output << R"(")" << getName(varexobs[i]) << R"(")";
}
output << "]" << endl;
output << R"(, "varexobs_ids": [)";
for (size_t i = 0; i < varexobs.size(); i++)
{
if (i != 0)
output << ", ";
output << getTypeSpecificID(varexobs[i])+1;
}
{
if (i != 0)
output << ", ";
output << getTypeSpecificID(varexobs[i]) + 1;
}
output << "]" << endl;
}
// Write the auxiliary variable table
@ -934,56 +984,56 @@ SymbolTable::writeJsonOutput(ostream &output) const
{
output << R"(, "aux_vars": [)" << endl;
for (int i = 0; i < static_cast<int>(aux_vars.size()); i++)
{
if (i != 0)
output << ", ";
output << R"({"endo_index": )" << getTypeSpecificID(aux_vars[i].symb_id)+1
<< R"(, "type": )" << aux_vars[i].get_type_id();
switch (aux_vars[i].type)
{
case AuxVarType::endoLead:
case AuxVarType::exoLead:
case AuxVarType::expectation:
case AuxVarType::pacExpectation:
{
if (i != 0)
output << ", ";
output << R"({"endo_index": )" << getTypeSpecificID(aux_vars[i].symb_id) + 1
<< R"(, "type": )" << aux_vars[i].get_type_id();
switch (aux_vars[i].type)
{
case AuxVarType::endoLead:
case AuxVarType::exoLead:
case AuxVarType::expectation:
case AuxVarType::pacExpectation:
case AuxVarType::pacTargetNonstationary:
break;
case AuxVarType::endoLag:
case AuxVarType::exoLag:
break;
case AuxVarType::endoLag:
case AuxVarType::exoLag:
case AuxVarType::logTransform:
case AuxVarType::diffLag:
case AuxVarType::diffLead:
case AuxVarType::diffForward:
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:
case AuxVarType::diffLag:
case AuxVarType::diffLead:
case AuxVarType::diffForward:
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:
output << R"(, "unary_op": ")" << aux_vars[i].unary_op << R"(")";
[[fallthrough]];
case AuxVarType::diff:
if (aux_vars[i].orig_symb_id)
output << R"(, "orig_index": )" << getTypeSpecificID(*aux_vars[i].orig_symb_id)+1
<< R"(, "orig_lead_lag": )" << aux_vars[i].orig_lead_lag.value();
break;
case AuxVarType::multiplier:
output << R"(, "eq_nbr": )" << aux_vars[i].equation_number_for_multiplier + 1;
break;
}
if (aux_vars[i].orig_symb_id)
output << R"(, "orig_index": )" << getTypeSpecificID(*aux_vars[i].orig_symb_id) + 1
<< R"(, "orig_lead_lag": )" << aux_vars[i].orig_lead_lag.value();
break;
case AuxVarType::multiplier:
output << R"(, "eq_nbr": )" << aux_vars[i].equation_number_for_multiplier + 1;
break;
}
if (expr_t orig_expr = aux_vars[i].expr_node;
orig_expr)
{
output << R"(, "orig_expr": ")";
orig_expr->writeJsonOutput(output, {}, {});
output << R"(")";
}
output << '}' << endl;
}
if (expr_t orig_expr = aux_vars[i].expr_node; orig_expr)
{
output << R"(, "orig_expr": ")";
orig_expr->writeJsonOutput(output, {}, {});
output << R"(")";
}
output << '}' << endl;
}
output << "]" << endl;
}
}
void
SymbolTable::writeJsonVarVector(ostream &output, const vector<int> &varvec) const
SymbolTable::writeJsonVarVector(ostream& output, const vector<int>& varvec) const
{
output << "[";
for (size_t i = 0; i < varvec.size(); i++)
@ -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;
}
@ -1007,7 +1058,7 @@ SymbolTable::getUltimateOrigSymbID(int symb_id) const
{
symb_id = getOrigSymbIdForAuxVar(symb_id);
}
catch (UnknownSymbolIDException &)
catch (UnknownSymbolIDException&)
{
break;
}
@ -1017,13 +1068,13 @@ SymbolTable::getUltimateOrigSymbID(int symb_id) const
optional<int>
SymbolTable::getEquationNumberForMultiplier(int symb_id) const
{
for (const auto &aux_var : aux_vars)
for (const auto& aux_var : aux_vars)
if (aux_var.symb_id == symb_id && aux_var.type == AuxVarType::multiplier)
return aux_var.equation_number_for_multiplier;
return nullopt;
}
const set<int> &
const set<int>&
SymbolTable::getVariablesWithLogTransform() const
{
return with_log_transform;
@ -1033,7 +1084,7 @@ set<int>
SymbolTable::getLagrangeMultipliers() const
{
set<int> r;
for (const auto &aux_var : aux_vars)
for (const auto& aux_var : aux_vars)
if (aux_var.type == AuxVarType::multiplier)
r.insert(aux_var.symb_id);
return r;

View File

@ -21,53 +21,55 @@
#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"
using namespace std;
using expr_t = class ExprNode *;
using expr_t = class ExprNode*;
//! Types of auxiliary variables
enum class AuxVarType
{
endoLead = 0, //!< Substitute for endo leads >= 2
endoLag = 1, //!< Substitute for endo lags >= 2
exoLead = 2, //!< Substitute for exo leads >= 1
exoLag = 3, //!< Substitute for exo lags >= 1
expectation = 4, //!< Substitute for Expectation Operator
diffForward = 5, /* Substitute for the differentiate of a forward variable,
{
endoLead = 0, //!< Substitute for endo leads >= 2
endoLag = 1, //!< Substitute for endo lags >= 2
exoLead = 2, //!< Substitute for exo leads >= 1
exoLag = 3, //!< Substitute for exo lags >= 1
expectation = 4, //!< Substitute for Expectation Operator
diffForward = 5, /* Substitute for the differentiate of a forward variable,
for the differentiate_forward_vars option.
N.B.: nothing to do with the diff() operator! */
multiplier = 6, //!< Multipliers for FOC of Ramsey Problem
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))
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
};
multiplier = 6, //!< Multipliers for FOC of Ramsey Problem
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))
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
};
//! Information on some auxiliary variables
struct AuxVarInfo
{
const int symb_id; // Symbol ID of the auxiliary variable
const AuxVarType type; // Its type
const optional<int> orig_symb_id; /* Symbol ID of the (only) endo that appears on the RHS of
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
(hence the need for std::optional). */
const int symb_id; // Symbol ID of the auxiliary variable
const AuxVarType type; // Its type
const optional<int> orig_symb_id; /* Symbol ID of the (only) endo that appears on the RHS of
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
(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
(in particular, for diff and unaryOp, unset
@ -79,8 +81,8 @@ struct AuxVarInfo
associated with this aux var. Only used for
avMultiplier. */
const int information_set; // Argument of expectation operator. Only used for avExpectation.
const expr_t expr_node; // Auxiliary variable definition
const string unary_op; // Used with AuxUnaryOp
const expr_t expr_node; // Auxiliary variable definition
const string unary_op; // Used with AuxUnaryOp
int
get_type_id() const
@ -107,7 +109,7 @@ class SymbolTable
{
private:
//! Has method freeze() been called?
bool frozen{false};
bool frozen {false};
using symbol_table_type = map<string, int>;
//! Maps strings to symbol IDs
@ -196,31 +198,34 @@ 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}
explicit SearchFailedException(int symb_id_arg) : symb_id {symb_id_arg}
{
}
};
private:
//! Factorized code for adding aux lag variables
int addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag, expr_t arg) 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;
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);
int addSymbol(const string& name, SymbolType type) noexcept(false);
//! Adds an auxiliary variable for endogenous with lead >= 2
/*!
\param[in] index Used to construct the variable name
@ -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,17 +302,22 @@ 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);
int addPacExpectationAuxiliaryVar(const string& name, expr_t expr_arg);
//! An auxiliary variable for a pac_target_nonstationary operator
int addPacTargetNonstationaryAuxiliaryVar(const string &name, expr_t expr_arg);
int addPacTargetNonstationaryAuxiliaryVar(const string& name, expr_t expr_arg);
//! Returns the number of auxiliary variables
int
AuxVarsSize() const
@ -314,23 +325,24 @@ public:
return aux_vars.size();
};
//! Tests if symbol already exists
inline bool exists(const string &name) const;
inline bool exists(const string& name) const;
//! Get symbol name (by ID)
inline string getName(int id) const noexcept(false);
//! Get TeX name
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);
//! Get type (by ID)
inline SymbolType getType(int id) const noexcept(false);
//! Get type (by name)
inline SymbolType getType(const string &name) const noexcept(false);
inline SymbolType getType(const string& name) const noexcept(false);
//! Get ID (by name)
inline int getID(const string &name) const noexcept(false);
inline int getID(const string& name) const noexcept(false);
//! Get ID (by type specific ID)
int getID(SymbolType type, int tsid) const noexcept(false);
//! Freeze symbol table
@ -343,7 +355,7 @@ public:
//! Get type specific ID (by symbol ID)
inline int getTypeSpecificID(int id) const noexcept(false);
//! Get type specific ID (by symbol name)
inline int getTypeSpecificID(const string &name) const noexcept(false);
inline int getTypeSpecificID(const string& name) const noexcept(false);
//! Get number of endogenous variables
inline int endo_nbr() const noexcept(false);
//! Get number of exogenous variables
@ -357,9 +369,9 @@ public:
//! Get number of user-declared endogenous variables (without the auxiliary variables)
inline int orig_endo_nbr() const noexcept(false);
//! Write output of this class
void writeOutput(ostream &output) const noexcept(false);
void writeOutput(ostream& output) const noexcept(false);
//! Write JSON Output
void writeJsonOutput(ostream &output) const;
void writeJsonOutput(ostream& output) const;
//! Mark a symbol as predetermined variable
void markPredetermined(int symb_id) noexcept(false);
//! Mark an endogenous as having been declared with “var(log)”
@ -382,21 +394,22 @@ 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;
vector<int> getTrendVarIds() const;
//! Get list of exogenous variables
set <int> getExogenous() const;
set<int> getExogenous() const;
//! Get list of exogenous variables
set <int> getObservedExogenous() const;
set<int> getObservedExogenous() const;
//! Get list of endogenous variables
set <int> getEndogenous() const;
set<int> getEndogenous() const;
//! Is a given symbol an auxiliary variable
bool isAuxiliaryVariable(int symb_id) const;
//! Is a given symbol a diff, diff lead, or diff lag auxiliary variable
bool isDiffAuxiliaryVariable(int symb_id) const;
//! Get list of endogenous variables without aux vars
set <int> getOrigEndogenous() const;
set<int> getOrigEndogenous() const;
//! Returns the original symbol corresponding to this variable
/* If symb_id has no original variable, returns symb_id. Otherwise,
repeatedly call getOrigSymbIDForAuxVar() until an original variable is
@ -404,13 +417,14 @@ 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 */
const AuxVarInfo &getAuxVarInfo(int symb_id) const;
const AuxVarInfo& getAuxVarInfo(int symb_id) const;
// Returns the set of all endogenous declared with “var(log)”
const set<int> &getVariablesWithLogTransform() const;
const set<int>& getVariablesWithLogTransform() const;
// Returns all Lagrange multipliers
set<int> getLagrangeMultipliers() const;
};
@ -419,11 +433,11 @@ inline void
SymbolTable::validateSymbID(int symb_id) const noexcept(false)
{
if (symb_id < 0 || symb_id > static_cast<int>(symbol_table.size()))
throw UnknownSymbolIDException{symb_id};
throw UnknownSymbolIDException {symb_id};
}
inline bool
SymbolTable::exists(const string &name) const
SymbolTable::exists(const string& name) const
{
return symbol_table.contains(name);
}
@ -457,19 +471,18 @@ SymbolTable::getType(int id) const noexcept(false)
}
inline SymbolType
SymbolTable::getType(const string &name) const noexcept(false)
SymbolTable::getType(const string& name) const noexcept(false)
{
return getType(getID(name));
}
inline int
SymbolTable::getID(const string &name) const noexcept(false)
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};
throw UnknownSymbolNameException {name};
}
inline int
@ -480,15 +493,14 @@ 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};
throw NoTypeSpecificIDException {id};
}
inline int
SymbolTable::getTypeSpecificID(const string &name) const noexcept(false)
SymbolTable::getTypeSpecificID(const string& name) const noexcept(false)
{
return getTypeSpecificID(getID(name));
}
@ -541,13 +553,13 @@ SymbolTable::orig_endo_nbr() const noexcept(false)
return endo_nbr() - aux_vars.size();
}
inline const AuxVarInfo &
inline const AuxVarInfo&
SymbolTable::getAuxVarInfo(int symb_id) const
{
for (const auto &aux_var : aux_vars)
for (const auto& aux_var : aux_vars)
if (aux_var.symb_id == symb_id)
return aux_var;
throw UnknownSymbolIDException{symb_id};
throw UnknownSymbolIDException {symb_id};
}
#endif

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;
@ -126,13 +127,13 @@ VariableDependencyGraph::print() const
}
VariableDependencyGraph
VariableDependencyGraph::extractSubgraph(const vector<int> &select_index) const
VariableDependencyGraph::extractSubgraph(const vector<int>& select_index) const
{
int n = select_index.size();
VariableDependencyGraph G(n);
auto v_index = get(vertex_index, *this);
auto v_index1_G = get(vertex_index1, G); // Maps new vertices to original indices
map<int, int> reverse_index; // Maps orig indices to new ones
map<int, int> reverse_index; // Maps orig indices to new ones
for (int i = 0; i < n; i++)
{
reverse_index[select_index[i]] = i;
@ -159,7 +160,7 @@ VariableDependencyGraph::vertexBelongsToAClique(vertex_descriptor vertex) const
while (it_in != in_end && it_out != out_end && agree)
{
agree = (source(*it_in, *this) == target(*it_out, *this)
&& source(*it_in, *this) != target(*it_in, *this)); //not a loop
&& source(*it_in, *this) != target(*it_in, *this)); // not a loop
liste.push_back(source(*it_in, *this));
++it_in;
++it_out;
@ -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;
@ -247,7 +249,7 @@ VariableDependencyGraph::eliminationOfVerticesBelongingToAClique()
}
bool
VariableDependencyGraph::suppressionOfVerticesWithLoop(set<int> &feed_back_vertices)
VariableDependencyGraph::suppressionOfVerticesWithLoop(set<int>& feed_back_vertices)
{
bool something_has_been_done = false;
vertex_iterator ita;
@ -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())
@ -314,7 +318,7 @@ VariableDependencyGraph::minimalSetOfFeedbackVertices() const
}
vector<int>
VariableDependencyGraph::reorderRecursiveVariables(const set<int> &feedback_vertices) const
VariableDependencyGraph::reorderRecursiveVariables(const set<int>& feedback_vertices) const
{
vector<int> reordered_vertices;
VariableDependencyGraph G(*this);
@ -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);
@ -384,11 +389,11 @@ VariableDependencyGraph::sortedStronglyConnectedComponents() const
// Construct mapping from unordered SCC to ordered SCC
vector<int> unordered2ordered(num_scc);
for (int j = 0; j < num_scc; j++)
unordered2ordered[reverseOrdered2unordered[num_scc-j-1]] = j;
unordered2ordered[reverseOrdered2unordered[num_scc - j - 1]] = j;
// Update the mapping of vertices to (now sorted) SCCs
for (int i = 0; i < static_cast<int>(num_vertices(*this)); i++)
vertex2scc[i] = unordered2ordered[vertex2scc[i]];
return { num_scc, vertex2scc };
return {num_scc, vertex2scc};
}

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,
boost::property<boost::vertex_degree_t, int,
boost::property<boost::vertex_in_degree_t, int,
boost::property<boost::vertex_out_degree_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
@ -54,12 +59,13 @@ public:
The property vertex_index1 of the subgraph contains indices of the original
graph.
*/
VariableDependencyGraph extractSubgraph(const vector<int> &select_index) const;
VariableDependencyGraph extractSubgraph(const vector<int>& select_index) const;
//! 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 */
vector<int> reorderRecursiveVariables(const set<int> &feedback_vertices) const;
/*! 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.
Returns the number of SCCs, and a mapping of vertex indices to sorted SCC
@ -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);
@ -77,14 +84,14 @@ private:
through the vertex to be removed) */
void eliminate(vertex_descriptor vertex_to_eliminate);
// Internal helper for hasCycle()
bool hasCycleDFS(vertex_descriptor u, color_t &color, vector<int> &circuit_stack) const;
bool hasCycleDFS(vertex_descriptor u, color_t& color, vector<int>& circuit_stack) const;
// Determine whether the graph has a cycle
bool hasCycle() const;
bool vertexBelongsToAClique(vertex_descriptor vertex) const;
bool eliminationOfVerticesWithOneOrLessIndegreeOrOutdegree();
bool eliminationOfVerticesBelongingToAClique();
// The suppressed vertices are stored in feedback set
bool suppressionOfVerticesWithLoop(set<int> &feed_back_vertices);
bool suppressionOfVerticesWithLoop(set<int>& feed_back_vertices);
};
#endif // _VARIABLEDEPENDENCYGRAPH_HH

View File

@ -20,8 +20,8 @@
#include "WarningConsolidation.hh"
#include <ostream>
WarningConsolidation &
operator<<(WarningConsolidation &wcc, const string &warning)
WarningConsolidation&
operator<<(WarningConsolidation& wcc, const string& warning)
{
if (wcc.no_warn)
return wcc;
@ -31,8 +31,8 @@ operator<<(WarningConsolidation &wcc, const string &warning)
return wcc;
};
WarningConsolidation &
operator<<(WarningConsolidation &wcc, const Dynare::location &loc)
WarningConsolidation&
operator<<(WarningConsolidation& wcc, const Dynare::location& loc)
{
if (wcc.no_warn)
return wcc;
@ -40,12 +40,10 @@ 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;
ostr << '-' << last.line << '.' << last.column;
else if (loc.begin.column != last.column)
ostr << '-' << last.column;
@ -54,8 +52,8 @@ operator<<(WarningConsolidation &wcc, const Dynare::location &loc)
return wcc;
};
WarningConsolidation &
operator<<(WarningConsolidation &wcc, ostream &(*pf)(ostream &))
WarningConsolidation&
operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&))
{
if (wcc.no_warn)
return wcc;
@ -66,7 +64,7 @@ operator<<(WarningConsolidation &wcc, ostream &(*pf)(ostream &))
}
void
WarningConsolidation::writeOutput(ostream &output) const
WarningConsolidation::writeOutput(ostream& output) const
{
if (warnings.str().empty())
return;
@ -88,7 +86,7 @@ WarningConsolidation::writeOutput(ostream &output) const
else
{
output << "');" << endl;
if (i+1 < warningsstr.length())
if (i + 1 < warningsstr.length())
writedisp = true;
}
}

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;
@ -34,28 +34,28 @@ private:
bool no_warn;
public:
explicit WarningConsolidation(bool no_warn_arg) : no_warn{no_warn_arg}
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);
friend WarningConsolidation &operator<<(WarningConsolidation &wcc, const Dynare::location &loc);
friend WarningConsolidation &operator<<(WarningConsolidation &wcc, ostream &(*pf)(ostream &));
friend WarningConsolidation& operator<<(WarningConsolidation& wcc, const string& warning);
friend WarningConsolidation& operator<<(WarningConsolidation& wcc, const Dynare::location& loc);
friend WarningConsolidation& operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&));
void
addWarning(const string &w)
addWarning(const string& w)
{
warnings << w;
};
void
addWarning(ostream &(*pf)(ostream &))
addWarning(ostream& (*pf)(ostream&))
{
warnings << pf;
};
//! Write Warnings to m file
void writeOutput(ostream &output) const;
void writeOutput(ostream& output) const;
//! Count warnings
/*! This is done in a very lousy way, by counting newlines in the
stringstream... */

View File

@ -26,25 +26,25 @@
using namespace macro;
void
Eval::interpret(ostream &output, Environment &env, [[maybe_unused]] vector<filesystem::path> &paths)
Eval::interpret(ostream& output, Environment& env, [[maybe_unused]] vector<filesystem::path>& paths)
{
try
{
output << expr->eval(env)->to_string();
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("Evaluation", location);
error(ex);
}
catch (exception &e)
catch (exception& e)
{
error(StackTrace("Evaluation", e.what(), location));
}
}
void
Include::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths)
Include::interpret(ostream& output, Environment& env, vector<filesystem::path>& paths)
{
using namespace filesystem;
try
@ -56,7 +56,7 @@ Include::interpret(ostream &output, Environment &env, vector<filesystem::path> &
ifstream incfile(filename, ios::binary);
if (incfile.fail())
{
for (const auto &dir : paths)
for (const auto& dir : paths)
{
incfile = ifstream(dir / filename, ios::binary);
if (incfile.good())
@ -66,10 +66,12 @@ Include::interpret(ostream &output, Environment &env, vector<filesystem::path> &
{
ostringstream errmsg;
errmsg << " * " << current_path().string() << endl;
for (const auto &dir : paths)
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;
@ -79,12 +81,12 @@ Include::interpret(ostream &output, Environment &env, vector<filesystem::path> &
https://en.cppreference.com/w/cpp/filesystem/path/native. */
m.parse(filename.string(), incfile, false, {}, env, paths, output);
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("@#include", location);
error(ex);
}
catch (exception &e)
catch (exception& e)
{
error(StackTrace("@#include", e.what(), location));
}
@ -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
@ -110,7 +113,7 @@ IncludePath::interpret([[maybe_unused]] ostream &output, Environment &env, vecto
string ipstr = static_cast<string>(*msp);
while (ipstr.size() > 1 && (ipstr.back() == '/' || ipstr.back() == '\\'))
ipstr.pop_back();
path ip{ipstr};
path ip {ipstr};
#else
path ip = static_cast<string>(*msp);
#endif
@ -120,12 +123,12 @@ IncludePath::interpret([[maybe_unused]] ostream &output, Environment &env, vecto
warning(StackTrace("@#includepath", ip.string() + " does not exist", location));
paths.emplace_back(ip);
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("@#includepath", location);
error(ex);
}
catch (exception &e)
catch (exception& e)
{
error(StackTrace("@#includepath", e.what(), location));
}
@ -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
{
@ -144,12 +148,12 @@ Define::interpret([[maybe_unused]] ostream &output, Environment &env, [[maybe_un
else
throw StackTrace("LHS of can be either a variable or a function");
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("@#define", location);
error(ex);
}
catch (exception &e)
catch (exception& e)
{
error(StackTrace("@#define", e.what(), location));
}
@ -157,18 +161,18 @@ Define::interpret([[maybe_unused]] ostream &output, Environment &env, [[maybe_un
}
void
Echo::interpret(ostream &output, Environment &env, [[maybe_unused]] vector<filesystem::path> &paths)
Echo::interpret(ostream& output, Environment& env, [[maybe_unused]] vector<filesystem::path>& paths)
{
try
{
cout << "@#echo (" << getLocation() << "): " << expr->eval(env)->to_string() << endl;
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("@#echo", location);
error(ex);
}
catch (exception &e)
catch (exception& e)
{
error(StackTrace("@#echo", e.what(), location));
}
@ -176,25 +180,27 @@ 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
{
throw StackTrace(expr->eval(env)->to_string());
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("@#error", location);
error(ex);
}
catch (exception &e)
catch (exception& e)
{
error(StackTrace("@#error", e.what(), location));
}
}
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);
@ -204,7 +210,7 @@ EchoMacroVars::interpret(ostream &output, Environment &env, [[maybe_unused]] vec
}
void
For::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths)
For::interpret(ostream& output, Environment& env, vector<filesystem::path>& paths)
{
ArrayPtr ap;
try
@ -213,12 +219,12 @@ For::interpret(ostream &output, Environment &env, vector<filesystem::path> &path
if (!ap)
throw StackTrace("The index must loop through an array");
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("@#for", location);
error(ex);
}
catch (exception &e)
catch (exception& e)
{
error(StackTrace("@#for", e.what(), location));
}
@ -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));
@ -246,7 +255,7 @@ For::interpret(ostream &output, Environment &env, vector<filesystem::path> &path
}
bool printLine = true;
for (const auto &statement : statements)
for (const auto& statement : statements)
{
if (printLine)
{
@ -260,10 +269,9 @@ For::interpret(ostream &output, Environment &env, vector<filesystem::path> &path
}
void
If::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths)
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);
@ -294,12 +302,12 @@ If::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths
}
}
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("@#if", location);
error(ex);
}
catch (exception &e)
catch (exception& e)
{
error(StackTrace("@#if", e.what(), location));
}
@ -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

@ -26,187 +26,210 @@
namespace macro
{
class Directive : public Node
class Directive : public Node
{
// A Parent class just for clarity
public:
explicit Directive(Tokenizer::location location_arg) : Node(move(location_arg))
{
// A Parent class just for clarity
public:
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;
};
}
// 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
// Not a real directive node
// Treated as such as the output is only to be interpreted
private:
const string text;
class TextNode : public Directive
public:
TextNode(string text_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), text {move(text_arg)}
{
// Class for text not interpreted by macroprocessor
// Not a real directive node
// 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)} { }
void
interpret(ostream &output, [[maybe_unused]] Environment &env, [[maybe_unused]] vector<filesystem::path> &paths) override
{
output << text;
}
};
class Eval : public Directive
}
void
interpret(ostream& output, [[maybe_unused]] Environment& env,
[[maybe_unused]] vector<filesystem::path>& paths) override
{
// Class for @{} statements
// Not a real directive node
// 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)} { }
void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override;
};
output << text;
}
};
class Eval : public Directive
{
// Class for @{} statements
// Not a real directive node
// Treated as such as the output is only to be interpreted
private:
const ExpressionPtr expr;
class Include : public Directive
public:
Eval(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr {move(expr_arg)}
{
private:
const ExpressionPtr expr;
public:
Include(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;
};
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class Include : public Directive
{
private:
const ExpressionPtr expr;
class IncludePath : public Directive
public:
Include(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr {move(expr_arg)}
{
private:
const ExpressionPtr expr;
public:
IncludePath(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;
};
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class IncludePath : public Directive
{
private:
const ExpressionPtr expr;
class Define : public Directive
public:
IncludePath(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr {move(expr_arg)}
{
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)} { }
void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override;
};
}
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;
class Echo : public Directive
public:
Define(VariablePtr var_arg, ExpressionPtr value_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), var {move(var_arg)}, value {move(value_arg)}
{
private:
const ExpressionPtr expr;
public:
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
}
Define(FunctionPtr func_arg, ExpressionPtr value_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), func {move(func_arg)}, value {move(value_arg)}
{
private:
const ExpressionPtr expr;
public:
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;
};
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class Echo : public Directive
{
private:
const ExpressionPtr expr;
class EchoMacroVars : public Directive
public:
Echo(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr {move(expr_arg)}
{
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)} { }
void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override;
};
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class Error : public Directive
{
private:
const ExpressionPtr expr;
class For : public Directive
public:
Error(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr {move(expr_arg)}
{
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,
}
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)}
{
}
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)}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class If : public Directive
{
protected:
/* Every if statement and the associated body to execute are stored in a
* pair<ExpressionPtr, vector<DirectivePtr>>, where the ExpressionPtr is the condition
* and vector<DirectivePtr> is the series of statements to execute if the condition evaluates
* to true.
* The `if` statement is the first element in the vector
* If there exist any `elseif` statements, they follow
* If there is an `else` statement it is the last element in the vector. Its condition is true.
*/
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}
{
}
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);
};
class Ifdef : public If
{
public:
Ifdef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_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
If(move(expr_and_body_arg), move(location_arg), true, false)
{
protected:
/* Every if statement and the associated body to execute are stored in a
* pair<ExpressionPtr, vector<DirectivePtr>>, where the ExpressionPtr is the condition
* and vector<DirectivePtr> is the series of statements to execute if the condition evaluates
* to true.
* The `if` statement is the first element in the vector
* If there exist any `elseif` statements, they follow
* If there is an `else` statement it is the last element in the vector. Its condition is true.
*/
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} { }
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);
};
}
};
class Ifdef : public If
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)
{
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) { }
};
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) { }
};
}
};
}
#endif

View File

@ -25,16 +25,16 @@
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;
if (!defines.empty())
{
stringstream command_line_defines_with_endl;
for (const auto & [var, val] : defines)
for (const auto& [var, val] : defines)
command_line_defines_with_endl << "@#define " << var << " = " << val << endl;
Driver m;
istream is(command_line_defines_with_endl.rdbuf());
@ -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);
@ -64,7 +63,7 @@ Driver::parse(const string &file_arg, const istream &modfile,
}
void
Driver::error(const Tokenizer::parser::location_type &location, const string &message) const
Driver::error(const Tokenizer::parser::location_type& location, const string& message) const
{
cerr << "ERROR in macro-processor: " << location << ": " << message << endl;
exit(EXIT_FAILURE);

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>
@ -39,87 +39,90 @@
namespace macro
{
/* The lexer class
* It was necessary to subclass the TokenizerFlexLexer class generated by Flex,
* since the prototype for TokenizerFlexLexer::yylex() was not convenient.
*/
class TokenizerFlex : public TokenizerFlexLexer
/* The lexer class
* It was necessary to subclass the TokenizerFlexLexer class generated by Flex,
* since the prototype for TokenizerFlexLexer::yylex() was not convenient.
*/
class TokenizerFlex : public TokenizerFlexLexer
{
public:
TokenizerFlex(istream* in) : TokenizerFlexLexer {in}
{
public:
TokenizerFlex(istream *in) : TokenizerFlexLexer{in} { }
TokenizerFlex(const TokenizerFlex &) = delete;
TokenizerFlex &operator=(const TokenizerFlex &) = delete;
}
TokenizerFlex(const TokenizerFlex&) = delete;
TokenizerFlex& operator=(const TokenizerFlex&) = delete;
//! The main lexing function
Tokenizer::parser::token_type lex(Tokenizer::parser::semantic_type *yylval,
Tokenizer::parser::location_type *yylloc,
macro::Driver &driver);
static void location_increment(Tokenizer::parser::location_type *yylloc, const char *yytext);
//! The main lexing function
Tokenizer::parser::token_type lex(Tokenizer::parser::semantic_type* yylval,
Tokenizer::parser::location_type* yylloc,
macro::Driver& driver);
static void location_increment(Tokenizer::parser::location_type* yylloc, const char* yytext);
};
//! Implements the macro expansion using a Flex scanner and a Bison parser
class Driver
{
private:
vector<DirectivePtr> statements;
stack<vector<DirectivePtr>> directive_stack;
public:
Driver() = default;
Driver(const Driver&) = delete;
Driver& operator=(const Driver&) = delete;
//! Exception thrown when value of an unknown variable is requested
struct UnknownVariable
{
const string name;
};
//! Implements the macro expansion using a Flex scanner and a Bison parser
class Driver
//! 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);
//! Name of main file being parsed (for error reporting purposes)
string file;
//! Reference to the lexer
unique_ptr<TokenizerFlex> lexer;
//! Error handler
void error(const Tokenizer::parser::location_type& location, const string& message) const;
bool
inContext() const
{
private:
vector<DirectivePtr> statements;
stack<vector<DirectivePtr>> directive_stack;
public:
Driver() = default;
Driver(const Driver &) = delete;
Driver &operator=(const Driver &) = delete;
return !directive_stack.empty();
}
//! Exception thrown when value of an unknown variable is requested
struct UnknownVariable
{
const string name;
};
void
pushContext()
{
directive_stack.emplace(vector<DirectivePtr>());
}
//! 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
pushContextTop(DirectivePtr statement)
{
directive_stack.top().emplace_back(move(statement));
}
//! Name of main file being parsed (for error reporting purposes)
string file;
void
pushStatements(DirectivePtr statement)
{
statements.emplace_back(move(statement));
}
//! Reference to the lexer
unique_ptr<TokenizerFlex> lexer;
//! Error handler
void error(const Tokenizer::parser::location_type &location, const string &message) const;
bool
inContext() const
{
return !directive_stack.empty();
}
void
pushContext()
{
directive_stack.emplace(vector<DirectivePtr>());
}
void
pushContextTop(DirectivePtr statement)
{
directive_stack.top().emplace_back(move(statement));
}
void
pushStatements(DirectivePtr statement)
{
statements.emplace_back(move(statement));
}
vector<DirectivePtr>
popContext()
{
auto top = move(directive_stack.top());
directive_stack.pop();
return top;
}
};
vector<DirectivePtr>
popContext()
{
auto top = move(directive_stack.top());
directive_stack.pop();
return top;
}
};
}
#endif

View File

@ -43,7 +43,7 @@ Environment::define(FunctionPtr func, ExpressionPtr value)
}
ExpressionPtr
Environment::getVariable(const string &name) const
Environment::getVariable(const string& name) const
{
if (auto it = variables.find(name); it != variables.end())
return it->second;
@ -55,7 +55,7 @@ Environment::getVariable(const string &name) const
}
tuple<FunctionPtr, ExpressionPtr>
Environment::getFunction(const string &name) const
Environment::getFunction(const string& name) const
{
if (auto it = functions.find(name); it != functions.end())
return it->second;
@ -67,50 +67,51 @@ Environment::getFunction(const string &name) const
}
codes::BaseType
Environment::getType(const string &name) const
Environment::getType(const string& name) const
{
return getVariable(name)->eval(const_cast<Environment &>(*this))->getType();
return getVariable(name)->eval(const_cast<Environment&>(*this))->getType();
}
bool
Environment::isVariableDefined(const string &name) const noexcept
Environment::isVariableDefined(const string& name) const noexcept
{
try
{
getVariable(name);
return true;
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
return false;
}
}
bool
Environment::isFunctionDefined(const string &name) const noexcept
Environment::isFunctionDefined(const string& name) const noexcept
{
try
{
getFunction(name);
return true;
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
return false;
}
}
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;
if (vars.empty())
for (const auto &it : variables)
for (const auto& it : variables)
printVariable(output, it.first, line, save);
else
for (const auto &it : vars)
for (const auto& it : vars)
if (isVariableDefined(it))
printVariable(output, it, line, save);
@ -118,10 +119,10 @@ Environment::print(ostream &output, const vector<string> &vars, const optional<i
output << "Macro Functions:" << endl;
if (vars.empty())
for (const auto &it : functions)
for (const auto& it : functions)
printFunction(output, it.second, line, save);
else
for (const auto &it : vars)
for (const auto& it : vars)
if (isFunctionDefined(it))
printFunction(output, functions.at(it), line, save);
@ -130,19 +131,20 @@ 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 << " = ";
getVariable(name)->eval(const_cast<Environment &>(*this))->print(output, save);
output << (save ? "options_.macrovars_line_" + to_string(*line) + "." : " ") << name << " = ";
getVariable(name)->eval(const_cast<Environment&>(*this))->print(output, save);
if (save)
output << ";";
output << endl;
}
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,44 +23,51 @@
#include "ForwardDeclarationsAndEnums.hh"
#include <map>
#include <vector>
#include <optional>
#include <vector>
namespace macro
{
class Environment
class Environment
{
private:
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}
{
private:
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} { }
void define(VariablePtr var, ExpressionPtr value);
void define(FunctionPtr func, ExpressionPtr value);
ExpressionPtr getVariable(const string &name) const;
tuple<FunctionPtr, ExpressionPtr> getFunction(const string &name) const;
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
{
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;
size_t
size() const noexcept
{
return variables.size() + functions.size();
}
const Environment *
getGlobalEnv() const noexcept
{
return parent == nullptr ? this : parent->getGlobalEnv();
}
};
}
void define(VariablePtr var, ExpressionPtr value);
void define(FunctionPtr func, ExpressionPtr value);
ExpressionPtr getVariable(const string& name) const;
tuple<FunctionPtr, ExpressionPtr> getFunction(const string& name) const;
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
{
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;
size_t
size() const noexcept
{
return variables.size() + functions.size();
}
const Environment*
getGlobalEnv() const noexcept
{
return parent == nullptr ? this : parent->getGlobalEnv();
}
};
}
#endif

View File

@ -17,15 +17,15 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <utility>
#include <numbers>
#include <utility>
#include "Expressions.hh"
using namespace macro;
BoolPtr
BaseType::is_different(const BaseTypePtr &btp) const
BaseType::is_different(const BaseTypePtr& btp) const
{
if (*(this->is_equal(btp)))
return make_shared<Bool>(false);
@ -33,7 +33,7 @@ BaseType::is_different(const BaseTypePtr &btp) const
}
BoolPtr
Bool::is_equal(const BaseTypePtr &btp) const
Bool::is_equal(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Bool>(btp);
if (!btp2)
@ -42,7 +42,7 @@ Bool::is_equal(const BaseTypePtr &btp) const
}
BoolPtr
Bool::logical_and(const ExpressionPtr &ep, Environment &env) const
Bool::logical_and(const ExpressionPtr& ep, Environment& env) const
{
if (!value)
return make_shared<Bool>(false);
@ -58,7 +58,7 @@ Bool::logical_and(const ExpressionPtr &ep, Environment &env) const
}
BoolPtr
Bool::logical_or(const ExpressionPtr &ep, Environment &env) const
Bool::logical_or(const ExpressionPtr& ep, Environment& env) const
{
if (value)
return make_shared<Bool>(true);
@ -80,7 +80,7 @@ Bool::logical_not() const
}
BaseTypePtr
Real::plus(const BaseTypePtr &btp) const
Real::plus(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -89,7 +89,7 @@ Real::plus(const BaseTypePtr &btp) const
}
BaseTypePtr
Real::minus(const BaseTypePtr &btp) const
Real::minus(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -98,7 +98,7 @@ Real::minus(const BaseTypePtr &btp) const
}
BaseTypePtr
Real::times(const BaseTypePtr &btp) const
Real::times(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -107,7 +107,7 @@ Real::times(const BaseTypePtr &btp) const
}
BaseTypePtr
Real::divide(const BaseTypePtr &btp) const
Real::divide(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -116,7 +116,7 @@ Real::divide(const BaseTypePtr &btp) const
}
BaseTypePtr
Real::power(const BaseTypePtr &btp) const
Real::power(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -125,7 +125,7 @@ Real::power(const BaseTypePtr &btp) const
}
BoolPtr
Real::is_less(const BaseTypePtr &btp) const
Real::is_less(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -134,7 +134,7 @@ Real::is_less(const BaseTypePtr &btp) const
}
BoolPtr
Real::is_greater(const BaseTypePtr &btp) const
Real::is_greater(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -143,7 +143,7 @@ Real::is_greater(const BaseTypePtr &btp) const
}
BoolPtr
Real::is_less_equal(const BaseTypePtr &btp) const
Real::is_less_equal(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -152,7 +152,7 @@ Real::is_less_equal(const BaseTypePtr &btp) const
}
BoolPtr
Real::is_greater_equal(const BaseTypePtr &btp) const
Real::is_greater_equal(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -161,7 +161,7 @@ Real::is_greater_equal(const BaseTypePtr &btp) const
}
BoolPtr
Real::is_equal(const BaseTypePtr &btp) const
Real::is_equal(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -170,7 +170,7 @@ Real::is_equal(const BaseTypePtr &btp) const
}
BoolPtr
Real::logical_and(const ExpressionPtr &ep, Environment &env) const
Real::logical_and(const ExpressionPtr& ep, Environment& env) const
{
if (!value)
return make_shared<Bool>(false);
@ -186,7 +186,7 @@ Real::logical_and(const ExpressionPtr &ep, Environment &env) const
}
BoolPtr
Real::logical_or(const ExpressionPtr &ep, Environment &env) const
Real::logical_or(const ExpressionPtr& ep, Environment& env) const
{
if (value)
return make_shared<Bool>(true);
@ -208,7 +208,7 @@ Real::logical_not() const
}
RealPtr
Real::max(const BaseTypePtr &btp) const
Real::max(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -217,7 +217,7 @@ Real::max(const BaseTypePtr &btp) const
}
RealPtr
Real::min(const BaseTypePtr &btp) const
Real::min(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -226,7 +226,7 @@ Real::min(const BaseTypePtr &btp) const
}
RealPtr
Real::mod(const BaseTypePtr &btp) const
Real::mod(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
@ -235,27 +235,30 @@ Real::mod(const BaseTypePtr &btp) const
}
RealPtr
Real::normpdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const
Real::normpdf(const BaseTypePtr& btp1, const BaseTypePtr& btp2) const
{
auto btp12 = dynamic_pointer_cast<Real>(btp1);
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
Real::normcdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const
Real::normcdf(const BaseTypePtr& btp1, const BaseTypePtr& btp2) const
{
auto btp12 = dynamic_pointer_cast<Real>(btp1);
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
String::plus(const BaseTypePtr &btp) const
String::plus(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<String>(btp);
if (!btp2)
@ -264,7 +267,7 @@ String::plus(const BaseTypePtr &btp) const
}
BoolPtr
String::is_less(const BaseTypePtr &btp) const
String::is_less(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<String>(btp);
if (!btp2)
@ -273,7 +276,7 @@ String::is_less(const BaseTypePtr &btp) const
}
BoolPtr
String::is_greater(const BaseTypePtr &btp) const
String::is_greater(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<String>(btp);
if (!btp2)
@ -282,7 +285,7 @@ String::is_greater(const BaseTypePtr &btp) const
}
BoolPtr
String::is_less_equal(const BaseTypePtr &btp) const
String::is_less_equal(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<String>(btp);
if (!btp2)
@ -291,7 +294,7 @@ String::is_less_equal(const BaseTypePtr &btp) const
}
BoolPtr
String::is_greater_equal(const BaseTypePtr &btp) const
String::is_greater_equal(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<String>(btp);
if (!btp2)
@ -300,7 +303,7 @@ String::is_greater_equal(const BaseTypePtr &btp) const
}
BoolPtr
String::is_equal(const BaseTypePtr &btp) const
String::is_equal(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<String>(btp);
if (!btp2)
@ -309,9 +312,9 @@ String::is_equal(const BaseTypePtr &btp) const
}
BoolPtr
String::cast_bool([[maybe_unused]] Environment &env) const
String::cast_bool([[maybe_unused]] Environment& env) const
{
auto f = [](const char &a, const char &b) { return (tolower(a) == tolower(b)); };
auto f = [](const char& a, const char& b) { return (tolower(a) == tolower(b)); };
if (string tf = "true"; equal(value.begin(), value.end(), tf.begin(), tf.end(), f))
return make_shared<Bool>(true);
@ -334,7 +337,7 @@ String::cast_bool([[maybe_unused]] Environment &env) const
}
RealPtr
String::cast_real([[maybe_unused]] Environment &env) const
String::cast_real([[maybe_unused]] Environment& env) const
{
try
{
@ -351,19 +354,19 @@ String::cast_real([[maybe_unused]] Environment &env) const
}
BaseTypePtr
Array::plus(const BaseTypePtr &btp) const
Array::plus(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Array>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of + operator");
vector<ExpressionPtr> arr_copy{arr};
vector<ExpressionPtr> arr_copy {arr};
arr_copy.insert(arr_copy.end(), btp2->arr.begin(), btp2->arr.end());
return make_shared<Array>(arr_copy);
}
BaseTypePtr
Array::minus(const BaseTypePtr &btp) const
Array::minus(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Array>(btp);
if (!btp2)
@ -372,7 +375,7 @@ Array::minus(const BaseTypePtr &btp) const
/* Highly inefficient algorithm for computing set difference
(but vector<T> is not suited for that...) */
vector<ExpressionPtr> arr_copy;
for (const auto &it : arr)
for (const auto& it : arr)
{
auto itbtp = dynamic_pointer_cast<BaseType>(it);
auto it2 = btp2->arr.cbegin();
@ -386,15 +389,15 @@ Array::minus(const BaseTypePtr &btp) const
}
BaseTypePtr
Array::times(const BaseTypePtr &btp) const
Array::times(const BaseTypePtr& btp) const
{
vector<ExpressionPtr> values;
auto btp2 = dynamic_pointer_cast<Array>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of * operator");
for (const auto &itl : arr)
for (const auto &itr : btp2->getValue())
for (const auto& itl : arr)
for (const auto& itr : btp2->getValue())
{
vector<ExpressionPtr> new_tuple;
if (dynamic_pointer_cast<Real>(itl) || dynamic_pointer_cast<String>(itl))
@ -407,7 +410,7 @@ Array::times(const BaseTypePtr &btp) const
if (dynamic_pointer_cast<Real>(itr) || dynamic_pointer_cast<String>(itr))
new_tuple.push_back(itr);
else if (dynamic_pointer_cast<Tuple>(itr))
for (const auto &tit : dynamic_pointer_cast<Tuple>(itr)->getValue())
for (const auto& tit : dynamic_pointer_cast<Tuple>(itr)->getValue())
new_tuple.push_back(tit);
else
throw StackTrace("Array::times: unsupported type on rhs");
@ -419,7 +422,7 @@ Array::times(const BaseTypePtr &btp) const
}
BaseTypePtr
Array::power(const BaseTypePtr &btp) const
Array::power(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2 || !*(btp2->isinteger()))
@ -435,7 +438,7 @@ Array::power(const BaseTypePtr &btp) const
}
BoolPtr
Array::is_equal(const BaseTypePtr &btp) const
Array::is_equal(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Array>(btp);
if (!btp2)
@ -455,20 +458,20 @@ Array::is_equal(const BaseTypePtr &btp) const
}
ArrayPtr
Array::set_union(const BaseTypePtr &btp) const
Array::set_union(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Array>(btp);
if (!btp2)
throw StackTrace("Arguments of the union operator (|) must be sets");
vector<ExpressionPtr> new_values = arr;
for (const auto &it : btp2->arr)
for (const auto& it : btp2->arr)
{
bool found = false;
auto it2 = dynamic_pointer_cast<BaseType>(it);
if (!it2)
throw StackTrace("Type mismatch for operands of in operator");
for (const auto &nvit : new_values)
for (const auto& nvit : new_values)
{
auto v2 = dynamic_pointer_cast<BaseType>(nvit);
if (!v2)
@ -486,19 +489,19 @@ Array::set_union(const BaseTypePtr &btp) const
}
ArrayPtr
Array::set_intersection(const BaseTypePtr &btp) const
Array::set_intersection(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Array>(btp);
if (!btp2)
throw StackTrace("Arguments of the intersection operator (|) must be sets");
vector<ExpressionPtr> new_values;
for (const auto &it : btp2->arr)
for (const auto& it : btp2->arr)
{
auto it2 = dynamic_pointer_cast<BaseType>(it);
if (!it2)
throw StackTrace("Type mismatch for operands of in operator");
for (const auto &nvit : arr)
for (const auto& nvit : arr)
{
auto v2 = dynamic_pointer_cast<BaseType>(nvit);
if (!v2)
@ -514,9 +517,9 @@ Array::set_intersection(const BaseTypePtr &btp) const
}
BoolPtr
Array::contains(const BaseTypePtr &btp) const
Array::contains(const BaseTypePtr& btp) const
{
for (const auto &v : arr)
for (const auto& v : arr)
{
auto v2 = dynamic_pointer_cast<BaseType>(v);
if (!v2)
@ -531,7 +534,7 @@ RealPtr
Array::sum() const
{
double retval = 0;
for (const auto &v : arr)
for (const auto& v : arr)
{
auto v2 = dynamic_pointer_cast<Real>(v);
if (!v2)
@ -542,7 +545,7 @@ Array::sum() const
}
BoolPtr
Array::cast_bool(Environment &env) const
Array::cast_bool(Environment& env) const
{
if (arr.size() != 1)
throw StackTrace("Array must be of size 1 to be cast to a boolean");
@ -550,7 +553,7 @@ Array::cast_bool(Environment &env) const
}
RealPtr
Array::cast_real(Environment &env) const
Array::cast_real(Environment& env) const
{
if (arr.size() != 1)
throw StackTrace("Array must be of size 1 to be cast to a real");
@ -558,7 +561,7 @@ Array::cast_real(Environment &env) const
}
BoolPtr
Tuple::is_equal(const BaseTypePtr &btp) const
Tuple::is_equal(const BaseTypePtr& btp) const
{
auto btp2 = dynamic_pointer_cast<Tuple>(btp);
if (!btp2)
@ -578,9 +581,9 @@ Tuple::is_equal(const BaseTypePtr &btp) const
}
BoolPtr
Tuple::contains(const BaseTypePtr &btp) const
Tuple::contains(const BaseTypePtr& btp) const
{
for (const auto &v : tup)
for (const auto& v : tup)
{
auto v2 = dynamic_pointer_cast<BaseType>(v);
if (!v2)
@ -592,7 +595,7 @@ Tuple::contains(const BaseTypePtr &btp) const
}
BoolPtr
Tuple::cast_bool(Environment &env) const
Tuple::cast_bool(Environment& env) const
{
if (tup.size() != 1)
throw StackTrace("Tuple must be of size 1 to be cast to a boolean");
@ -600,7 +603,7 @@ Tuple::cast_bool(Environment &env) const
}
RealPtr
Tuple::cast_real(Environment &env) const
Tuple::cast_real(Environment& env) const
{
if (tup.size() != 1)
throw StackTrace("Tuple must be of size 1 to be cast to a real");
@ -608,7 +611,7 @@ Tuple::cast_real(Environment &env) const
}
BaseTypePtr
Range::eval(Environment &env) const
Range::eval(Environment& env) const
{
RealPtr incdbl = make_shared<Real>(1);
if (inc)
@ -631,55 +634,64 @@ Range::eval(Environment &env) const
}
BaseTypePtr
Array::eval(Environment &env) const
Array::eval(Environment& env) const
{
vector<ExpressionPtr> retval;
for (const auto &it : arr)
for (const auto& it : arr)
retval.emplace_back(it->eval(env));
return make_shared<Array>(retval);
}
BaseTypePtr
Tuple::eval(Environment &env) const
Tuple::eval(Environment& env) const
{
vector<ExpressionPtr> retval;
for (const auto &it : tup)
for (const auto& it : tup)
retval.emplace_back(it->eval(env));
return make_shared<Tuple>(retval);
}
BaseTypePtr
Variable::eval(Environment &env) const
Variable::eval(Environment& env) const
{
if (indices && !indices->empty())
{
ArrayPtr map = dynamic_pointer_cast<Array>(indices->eval(env));
vector<int> ind;
for (const auto &it : map->getValue())
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))
for (const auto &it1 : dynamic_pointer_cast<Array>(it)->getValue())
for (const auto& it1 : dynamic_pointer_cast<Array>(it)->getValue())
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,15 +705,14 @@ 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
{
retvals += orig_string.substr(it - 1, 1);
}
catch (const out_of_range &ex)
catch (const out_of_range& ex)
{
throw StackTrace("variable", "Index out of range", location);
}
@ -716,7 +727,7 @@ Variable::eval(Environment &env) const
{
retval.emplace_back(ap->at(it - 1)->eval(env));
}
catch (const out_of_range &ex)
catch (const out_of_range& ex)
{
throw StackTrace("variable", "Index out of range", location);
}
@ -732,7 +743,7 @@ Variable::eval(Environment &env) const
}
BaseTypePtr
Function::eval(Environment &env) const
Function::eval(Environment& env) const
{
FunctionPtr func;
ExpressionPtr body;
@ -742,15 +753,17 @@ Function::eval(Environment &env) const
{
tie(func, body) = env.getFunction(name);
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("Function", location);
throw;
}
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
{
@ -763,7 +776,7 @@ Function::eval(Environment &env) const
env = env_orig;
return retval;
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("Function", location);
throw;
@ -771,7 +784,7 @@ Function::eval(Environment &env) const
}
BaseTypePtr
UnaryOp::eval(Environment &env) const
UnaryOp::eval(Environment& env) const
{
try
{
@ -857,12 +870,12 @@ UnaryOp::eval(Environment &env) const
return arg->eval(env)->defined(env);
}
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("unary operation", location);
throw;
}
catch (exception &e)
catch (exception& e)
{
throw StackTrace("unary operation", e.what(), location);
}
@ -871,7 +884,7 @@ UnaryOp::eval(Environment &env) const
}
BaseTypePtr
BinaryOp::eval(Environment &env) const
BinaryOp::eval(Environment& env) const
{
try
{
@ -917,12 +930,12 @@ BinaryOp::eval(Environment &env) const
return arg1->eval(env)->mod(arg2->eval(env));
}
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("binary operation", location);
throw;
}
catch (exception &e)
catch (exception& e)
{
throw StackTrace("binary operation", e.what(), location);
}
@ -931,7 +944,7 @@ BinaryOp::eval(Environment &env) const
}
BaseTypePtr
TrinaryOp::eval(Environment &env) const
TrinaryOp::eval(Environment& env) const
{
try
{
@ -943,12 +956,12 @@ TrinaryOp::eval(Environment &env) const
return arg1->eval(env)->normcdf(arg2->eval(env), arg3->eval(env));
}
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("trinary operation", location);
throw;
}
catch (exception &e)
catch (exception& e)
{
throw StackTrace("trinary operation", e.what(), location);
}
@ -957,7 +970,7 @@ TrinaryOp::eval(Environment &env) const
}
BaseTypePtr
Comprehension::eval(Environment &env) const
Comprehension::eval(Environment& env) const
{
ArrayPtr input_set;
VariablePtr vp;
@ -970,10 +983,12 @@ 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)
catch (StackTrace& ex)
{
ex.push("Comprehension: ", location);
throw;
@ -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)
{
auto mt2 = dynamic_pointer_cast<Tuple>(btp);
if (mt->size() != mt2->size())
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);
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 "
" set tuple are not the same as the number of elements in "
"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);
env.define(vp2, mt2->at(j));
}
}
else
throw StackTrace("Comprehension", "assigning to tuple in output expression "
"but input expression does not contain tuples", 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);
env.define(vp2, mt2->at(j));
}
}
else
throw StackTrace("Comprehension",
"assigning to tuple in output expression "
"but input expression does not contain tuples",
location);
if (!c_when)
if (!c_expr)
@ -1024,7 +1044,7 @@ Comprehension::eval(Environment &env) const
if (!bp && !dp)
throw StackTrace("The condition must evaluate to a boolean or a real");
}
catch (StackTrace &ex)
catch (StackTrace& ex)
{
ex.push("Comprehension", location);
throw;
@ -1047,27 +1067,27 @@ Array::to_string() const noexcept
if (arr.empty())
return "[]";
string retval = "[";
for (const auto &it : arr)
for (const auto& it : arr)
retval += it->to_string() + ", ";
return retval.substr(0, retval.size()-2) + "]";
return retval.substr(0, retval.size() - 2) + "]";
}
string
Tuple::to_string() const noexcept
{
string retval = "(";
for (const auto &it : tup)
for (const auto& it : tup)
retval += it->to_string() + ", ";
return retval.substr(0, retval.size()-2) + ")";
return retval.substr(0, retval.size() - 2) + ")";
}
string
Function::to_string() const noexcept
{
string retval = name + "(";
for (const auto &it : args)
for (const auto& it : args)
retval += it->to_string() + ", ";
return retval.substr(0, retval.size()-2) + ")";
return retval.substr(0, retval.size() - 2) + ")";
}
string
@ -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);
@ -1248,19 +1270,16 @@ Comprehension::to_string() const noexcept
}
void
String::print(ostream &output, bool matlab_output) const noexcept
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
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 << ", ";
@ -1270,11 +1289,10 @@ Array::print(ostream &output, bool matlab_output) const noexcept
}
void
Tuple::print(ostream &output, bool matlab_output) const noexcept
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 << ", ";
@ -1284,11 +1302,10 @@ Tuple::print(ostream &output, bool matlab_output) const noexcept
}
void
Function::printArgs(ostream &output) const noexcept
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 << ", ";
@ -1298,7 +1315,7 @@ Function::printArgs(ostream &output) const noexcept
}
void
UnaryOp::print(ostream &output, bool matlab_output) const noexcept
UnaryOp::print(ostream& output, bool matlab_output) const noexcept
{
switch (op_code)
{
@ -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
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)
@ -1529,7 +1540,7 @@ BinaryOp::print(ostream &output, bool matlab_output) const noexcept
}
void
TrinaryOp::print(ostream &output, bool matlab_output) const noexcept
TrinaryOp::print(ostream& output, bool matlab_output) const noexcept
{
switch (op_code)
{
@ -1549,7 +1560,7 @@ TrinaryOp::print(ostream &output, bool matlab_output) const noexcept
}
void
Comprehension::print(ostream &output, bool matlab_output) const noexcept
Comprehension::print(ostream& output, bool matlab_output) const noexcept
{
output << "[";
if (c_expr)

File diff suppressed because it is too large Load Diff

View File

@ -26,123 +26,123 @@ using namespace std;
namespace macro
{
// For Expressions.hh
class BaseType;
using BaseTypePtr = shared_ptr<BaseType>;
class Bool;
using BoolPtr = shared_ptr<Bool>;
class Real;
using RealPtr = shared_ptr<Real>;
class String;
using StringPtr = shared_ptr<String>;
class Tuple;
using TuplePtr = shared_ptr<Tuple>;
class Array;
using ArrayPtr = shared_ptr<Array>;
class Range;
using RangePtr = shared_ptr<Range>;
// For Expressions.hh
class BaseType;
using BaseTypePtr = shared_ptr<BaseType>;
class Bool;
using BoolPtr = shared_ptr<Bool>;
class Real;
using RealPtr = shared_ptr<Real>;
class String;
using StringPtr = shared_ptr<String>;
class Tuple;
using TuplePtr = shared_ptr<Tuple>;
class Array;
using ArrayPtr = shared_ptr<Array>;
class Range;
using RangePtr = shared_ptr<Range>;
// For Environment.hh
class Expression;
using ExpressionPtr = shared_ptr<Expression>;
class Variable;
using VariablePtr = shared_ptr<Variable>;
class Function;
using FunctionPtr = shared_ptr<Function>;
// For Environment.hh
class Expression;
using ExpressionPtr = shared_ptr<Expression>;
class Variable;
using VariablePtr = shared_ptr<Variable>;
class Function;
using FunctionPtr = shared_ptr<Function>;
// For Parser.yy
class Directive;
using DirectivePtr = shared_ptr<Directive>;
class Eval;
using EvalPtr = shared_ptr<Eval>;
// For Parser.yy
class Directive;
using DirectivePtr = shared_ptr<Directive>;
class Eval;
using EvalPtr = shared_ptr<Eval>;
// For Directives.cc
class Driver;
// For Directives.cc
class Driver;
namespace codes
{
enum class BaseType
{
Bool,
Real,
String,
Array,
Range,
Tuple
};
namespace codes
{
enum class BaseType
{
Bool,
Real,
String,
Array,
Range,
Tuple
};
enum class UnaryOp
{
cast_bool,
cast_real,
cast_string,
cast_tuple,
cast_array,
logical_not,
unary_minus,
unary_plus,
length,
isempty,
isboolean,
isreal,
isstring,
istuple,
isarray,
exp,
ln,
log10,
sin,
cos,
tan,
asin,
acos,
atan,
sqrt,
cbrt,
sign,
floor,
ceil,
trunc,
sum,
erf,
erfc,
gamma,
lgamma,
round,
normpdf,
normcdf,
defined
};
enum class UnaryOp
{
cast_bool,
cast_real,
cast_string,
cast_tuple,
cast_array,
logical_not,
unary_minus,
unary_plus,
length,
isempty,
isboolean,
isreal,
isstring,
istuple,
isarray,
exp,
ln,
log10,
sin,
cos,
tan,
asin,
acos,
atan,
sqrt,
cbrt,
sign,
floor,
ceil,
trunc,
sum,
erf,
erfc,
gamma,
lgamma,
round,
normpdf,
normcdf,
defined
};
enum class BinaryOp
{
plus,
minus,
times,
divide,
power,
equal_equal,
not_equal,
less,
greater,
less_equal,
greater_equal,
logical_and,
logical_or,
in,
set_union,
set_intersection,
max,
min,
mod
};
enum class BinaryOp
{
plus,
minus,
times,
divide,
power,
equal_equal,
not_equal,
less,
greater,
less_equal,
greater_equal,
logical_and,
logical_or,
in,
set_union,
set_intersection,
max,
min,
mod
};
enum class TrinaryOp
{
normpdf,
normcdf
};
}
enum class TrinaryOp
{
normpdf,
normcdf
};
}
}
#endif