Reformat C++ source code using clang-format 15
parent
529ec50337
commit
d463607e90
|
@ -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);
|
||||
|
|
500
src/Bytecode.hh
500
src/Bytecode.hh
|
@ -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 hasn’t to be indicated)
|
||||
FLDT, // Loads a temporary term onto the stack - dynamic context (the period has to be indicated)
|
||||
FLDST, // Loads a temporary term onto the stack - static context (the period hasn’t to be indicated)
|
||||
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 hasn’t to be indicated)
|
||||
FDIMT, // Defines the number of temporary terms - dynamic context (the period has to be indicated)
|
||||
FDIMST, // Defines the number of temporary terms - static context (the period hasn’t to be
|
||||
// indicated)
|
||||
FLDT, // Loads a temporary term onto the stack - dynamic context (the period has to be indicated)
|
||||
FLDST, // Loads a temporary term onto the stack - static context (the period hasn’t to be
|
||||
// indicated)
|
||||
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 hasn’t 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 hasn’t 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 hasn’t 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 hasn’t 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 hasn’t to
|
||||
// be indicated)
|
||||
|
||||
FLDV, // Loads a variable (described in SymbolType) onto the stack - dynamic context (the period has to be indicated)
|
||||
FLDSV, // Loads a variable (described in SymbolType) onto the stack - static context (the period hasn’t to be indicated)
|
||||
FLDVS, // Loads a variable (described in SymbolType) onto the stack - dynamic context but inside the STEADY_STATE operator (the period hasn’t to be indicated)
|
||||
FSTPV, // Stores a variable (described in SymbolType) from the stack - dynamic context (the period has to be indicated)
|
||||
FSTPSV, // Stores a variable (described in SymbolType) from the stack - static context (the period hasn’t to be indicated)
|
||||
FLDV, // Loads a variable (described in SymbolType) onto the stack - dynamic context (the period
|
||||
// has to be indicated)
|
||||
FLDSV, // Loads a variable (described in SymbolType) onto the stack - static context (the period
|
||||
// hasn’t to be indicated)
|
||||
FLDVS, // Loads a variable (described in SymbolType) onto the stack - dynamic context but inside
|
||||
// the STEADY_STATE operator (the period hasn’t to be indicated)
|
||||
FSTPV, // Stores a variable (described in SymbolType) from the stack - dynamic context (the period
|
||||
// has to be indicated)
|
||||
FSTPSV, // Stores a variable (described in SymbolType) from the stack - static context (the period
|
||||
// hasn’t to be indicated)
|
||||
|
||||
FLDR, // Loads a residual onto the stack
|
||||
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
|
||||
|
|
|
@ -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 it’s the default initializer
|
||||
ll,
|
||||
dl,
|
||||
dd
|
||||
};
|
||||
{
|
||||
unspecified, // Must be the first one, because it’s 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
|
@ -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;
|
||||
|
|
|
@ -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 ¶llel_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
|
||||
|
|
193
src/DataTree.cc
193
src/DataTree.cc
|
@ -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();
|
||||
}
|
||||
|
|
153
src/DataTree.hh
153
src/DataTree.hh
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
1651
src/DynamicModel.cc
1651
src/DynamicModel.cc
File diff suppressed because it is too large
Load Diff
|
@ -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> ®imes_bind, const vector<string> ®imes_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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 << ", ";
|
||||
|
|
|
@ -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
|
||||
|
|
3268
src/ExprNode.cc
3268
src/ExprNode.cc
File diff suppressed because it is too large
Load Diff
1669
src/ExprNode.hh
1669
src/ExprNode.hh
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
587
src/ModFile.cc
587
src/ModFile.cc
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
760
src/ModelTree.cc
760
src/ModelTree.cc
File diff suppressed because it is too large
Load Diff
1756
src/ModelTree.hh
1756
src/ModelTree.hh
File diff suppressed because it is too large
Load Diff
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
1046
src/ParsingDriver.cc
1046
src/ParsingDriver.cc
File diff suppressed because it is too large
Load Diff
|
@ -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 ®ime)
|
||||
static string
|
||||
buildOccbinBindParamName(const string& regime)
|
||||
{
|
||||
return "occbin_" + regime + "_bind";
|
||||
}
|
||||
|
|
454
src/Shocks.cc
454
src/Shocks.cc
|
@ -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 << ", ";
|
||||
|
|
171
src/Shocks.hh
171
src/Shocks.hh
|
@ -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
|
||||
|
|
315
src/Statement.cc
315
src/Statement.cc
|
@ -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);
|
||||
}
|
||||
|
|
174
src/Statement.hh
174
src/Statement.hh
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
848
src/SubModel.cc
848
src/SubModel.cc
File diff suppressed because it is too large
Load Diff
198
src/SubModel.hh
198
src/SubModel.hh
|
@ -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 can’t 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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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... */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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." : " ");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue